CRSアーカイブ

CRSアーカイブとは

CRSアーカイブは、拡張子carを持つファイルで、複数のファイルを圧縮してひとつのファイルにまとめた物です。
CRSアーカイブは略してCAR(Crs ARchive)ファイルと呼びます。関連するプログラムやデータをCARファイルに収めることにより、通信オーバーヘッドの低減や、暗号化してプログラムを秘匿することなど、多くのメリットがあります。

CARファイルのロード

CARファイルは、URLによって指し示す場所よりimport文によってロードします。

import car-file-url[ ,version] ;
car-file-urlで指定するURLの拡張子部分が.carまたは.car60の場合、import文はロードする対象がCARファイルと見なして動作します。
拡張子がこれら以外の場合には、たとえ内容がCARファイルであってもCARファイルとは見なされず、正常にロードすることはできません。
省略可能なオプション、versionを指定することにより、特定のバージョンのCARファイルをロードすることができます。
CARファイルのバージョンは、Biz/Designer DTの「プロジェクトの設定」タブ内にある「アーカイブ情報」ボタンをクリックし表示されるダイアログ内の「バージョン番号」に指定します。
../_images/core15_image001.png
versionを指定した場合、すでにローカルコンピュータにキャッシュさたCARファイルがある場合に、そのバージョン番号と照合して、不一致となったとき、CARファイルのキャッシュおよび、そのCARファイルから取り出されてキャッシュされた関連ファイルを全て削除してから、car-file-urlで指示された場所より新しくダウンロードを行います。

project.xml

CRSアーカイブの属性を記述したxmlファイルです。

Biz/DesignerからCARファイルを生成する場合は指定されたアーカイブ情報に基づき自動的に生成されます。

car.exeコマンドラインツールを使用してCARファイルを作成する場合、project.xmlは自動生成されないため以下のフォーマットのファイルを用意する必要があります。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.opst.co.jp/CRS/2017/project" xmlns:xlink="http://www.w3.org/1999/xlink">
  <import src="初期インポートするCRS" />
  <carinfo>
    <description>アーカイブの説明</description>
    <company>作成者、企業名など</company>
    <copyright>著作権情報など</copyright>
    <carversion>6.0.0</carversion><!-- 現在固定値 -->
    <apiversion>対応APIバージョン(参考情報)</apiversion>
    <comment>コメント</comment>
    <version>CARファイルのバージョン</version>
  </carinfo>
</project>

importの動作

CARファイルをロードするとき、次の動作が行われます。

1. importに指定したURLが既にメモリ上にロードされているか検索する
検索した結果、メモリ上に同一URLを持つCARファイルが見つかり、importでversionが指定されていた場合、バージョンの照合が行われます。
その結果バージョンが不一致となったとき、CRS例外がスローされ、処理は中止されます。

メモリ上に同一URLを持つCARファイルが見つかり、version番号の指定がない場合、既にロード済みとなり何もせずに復帰します。
2. CARファイルイメージの取得
メモリ上に指定URLのCARファイルが見つからない場合、次の順序で検索してCARファイルを取得します。

(1) キャッシュ

importで指定したURLをキャッシュから検索します。


(2) 既にメモリ上にロードされている別のCARファイルの内部

importで指定したURLを解析し、別のCARファイルの内部を指すURLと識別した場合、 認識したCARファイルをメモリ上から検索し、含まれる指定URLのCARファイルを取り出します。


例えば次のようなケースです

import "http://server/lib1.car";
import "http://server/lib1.car/subdir/lib2.car";

この例では、先にlib1.carがロードされ、つづくimportでlib1.car内部を指すURLでlib2.carが指定されているため、lib2.carはlib1.car内部から検索されます。


(3) WEBサーバなどの外部リソース

上記の検索で、対象CARファイルが見つからない場合、指定URLからのダウンロードを行います。

以上の検索で指定されたCARファイルが見つからない場合、原因を示す例外がスローされ、import処理は中断されます。


3. 取得したCARファイルの検証
圧縮されているCARファイルのヘッダ情報などを検証し、正規のCARファイルであることを確認します。
不正なファイルと認識された場合には、原因を示す例外がスローされ、import処理は中断されます。
4. バージョンの確認
import文で、オプションのversionを指定した場合、取得したCARファイルに含まれるバージョン情報と照合されます。
照合の結果バージョンが不一致となったとき、CARファイルがキャッシュから取得されている場合には、CARファイルおよび、そのCARファイルから取り出されたファイルのキャッシュを全て削除し、「2 CARファイルイメージの取得」処理に戻り、キャッシュ以外からの再取得が試みられます。
キャッシュ以外から取得したCARファイルのバージョンが不一致の場合、CRS例外がスローされ、import動作は中断します。
5. CARファイルのメモリ展開
以上の処理で正常にロードされたCARファイルは、内部に含まれるファイルのディレクトリ情報と共にメモリ上に維持されます。
以降の処理でロードされたCARファイルに含まれるファイルが要求された場合、ファイルはこのメモリイメージから取り出されることになります。
6. project.xmlの処理
CARファイルに含まれるproject.xmlを読み込み、CARファイルの作成元となったプロジェクト情報を取得します。
プロジェクト情報に「インポートCRSファイル」の指定がある場合、そのURLをimport文と同等の処理によりロードします。

CARファイルの整合性維持

CARファイルもObject.getメソッドと同様のルールによりキャッシュされます。
また、CARファイルの内部に含まれるファイルをGETメソッドによりロードした場合も同様に、キャッシュの対象となります。
従って、CARファイルとその内部ファイルは、それぞれが別々にキャッシュされることになります。
../_images/core15_image002.png
ある意味、CARファイルは2重にキャッシュされる事になります。
また、CARファイルがロードされると、メモリ上にイメージが維持されるため、サーバ上のCARファイル、メモリ上のCARファイル、CARファイルのキャッシュ、CARファイルに含まれるファイルのキャッシュと、ひとつのCARファイルは複数のコピーを持つことになります。この事は、CARファイルを正しく使用するためには、少し注意が必要となることを示唆しています。
CARファイルに関する整合性を保ち、正しく運用するためには、次のルールを考慮してください。
1. メモリ上にロードされたCARファイルを削除する方法はありません。
CARファイルのバージョンをアプリケーションで管理する場合、CARファイルにバージョンを示すファイルを収めて、その値で判断したくなりますが、そのような事は実現できません。
それは、CARファイルの中身を取り出すときには、既にCARファイルはメモリ上にロードされているためです。
仮に取り出したファイルに記載されているバージョン番号が、期待した番号ではない場合に、CARファイルのキャッシュを削除したとしても、CARファイルは既にメモリ上に維持されている訳ですから、新しいバージョンのCARファイルがダウンロードされるのは、次回起動時になります。

不正なバージョン管理の例

import "/lib1.car";
var lib_ver = HttpSession.getSession().Get("/lib1.car/ver.txt");
if (lib_ver.Read() != "3.0") {
    //.DeleteCache("/lib1.car");
    import "/lib1.car";
}
Get("/lib1.car/main.crs");
この例のDeleteCacheでは、キャッシュは削除されますが、メモリ上にロードされているlib1.carは有効なままです。
getにより読み込まれる、main.crsは、メモリ上のCARファイルから読み込まれます。
2. CARファイルから取り出されたファイルのキャッシュだけを削除しても、有用な意味はありません。
CARファイルがメモリ上または、キャッシュに維持されている場合、CARファイルから取り出したファイルのキャッシュを削除しても、再びメモリ上またはキャッシュ上のCARファイルからロードされます。
キャッシュを削除する場合、必ずCARファイルのキャッシュを削除する必要があります。
3. CARファイルのキャッシュを削除すると、そのCARファイルから取り出されたファイルのキャッシュも同時に削除されます。
4. importでバージョンを指定する場合、同じCARファイルのimportでは、すべて同じバージョンの明示が必要です。
ひとつのCARファイルを複数のCRSファイルでimportする事はよくあることです。
しかし、そのような場合にバージョン番号の指定は必ず一致させないと、例外が発生します。

例外が発生する例

--- file1.crs ---

import "lib1.car","ver1.0";
    :

--- file2.crs ---

import "lib1.car","ver2.0";
    :

上の例では、後に実行したほうのimport文はバージョン不一致で例外を起こします。

--- file1.crs ---

import "lib1.car";
    :

--- file2.crs ---

import "lib1.car","ver2.0";
    :

この例では、file2.crsが後に実行された場合、file1.crsが異なるバージョンをロードした時に限って例外を起こします。

CARファイルを使った運用で、最も容易にバージョン管理を行う方法は、import文のバージョン指定ですが、先にあげた例のように、複数のCRSでimportしている場合には、複数のCRSをメンテナンスする必要があり、別の面で非合理的です。

通常のCRSファイルに対するバージョン管理と同じ方法でCARファイルのバージョンを維持することも可能です。


--- lib1_version.crs ---

String lib1_version = "2.0.0.1";

--- app.crs ---

String lib1_curVersion = "2.0.0.2";
Get("lib1_version.crs");
if (lib1_curVersion != lib1_version) {
    //.DeleteCache("lib1_version.crs");
    //.DeleteCache("lib1.car");
    Get("lib1_version.crs");
}
import "lib1.car"
この方法の場合、CARファイルの更新にあわせて、lib1_version.crsを常に正しく維持することが重要となります。
また、import文のバージョン指定に比べて、記述が煩雑となり多くのCARファイルのバージョンを管理するためには、さらに多くの記述が必要となります。
どちらが優れている方法とは、一概に決めることはできませんので、アプリケーションの特性に合わせて適した方法を選択してください。