GearsOSの分散ファイルシステムの設計
|
Takahiro Ikki, Shinji Kono
琉球大学
|
GearsOSとその現状
- 信頼性の保証と拡張性の高さを目指したOSプロジェクト
- 軽量継続を用いた言語、CbC(Continuation based C)により記述される
- ノーマルレベルとメタレベルを分離して記述する
- 現状では言語フレームワークとしてのみ機能する
- OSとして動作するには多くの機能の開発が必要
従来の物より発展した分散ファイルシステムの設計
- データベース的なレコード操作によるアクセス
- ファイルに対する全ての操作がTransactionとなる
- 既存ではアプリケーションが担当する機能を取り込む
- 自律分散を目指した分散ファイルシステム
- 特定のサーバーを中枢にしなくても良い
- 分散フレームワークChristieの仕組みにより実現する
CbC (Continuation based C)
- C言語の拡張言語である
- 関数に代わる軽量継続をメインに記述する
- Gearというプログラム概念
- DataGearを受け取り処理を行う(InputDataGear)
- 処理の結果をDataGearに書き出す(OutputDataGear)
CbCのサンプルプログラム
__code CG2(int num3){
printf("num = %d\n", num3);
exit(0);
}
__code CG1(int num, int num1){
int num2 = num + num1;
goto CG2(num2);
}
int main(){
int a = 2;
int b = 3;
goto CG1(a, b);
}
メタレベルのGear
- CodeGearとDataGearにはメタレベルのものが存在する
- MetaCodeGear
- CodeGearの処理前と処理後に参照される
- Input/OutputDataGearを引き渡す
- CodeGear処理前に呼ばれるものを特にstubCodeGearと呼ぶ
- MetaDataGear
- MetaCodeGearにて参照されるDataGear
- ユーザーが記述する上では普段は意識しない
GearsOSの構成
- Interface
- 定義ファイル(.h)に記述を行う
- APIとなるCodeGearとその参照するDataGearを宣言する
- コンパイル時にContext(後述)に書き込まれる
- Implement
- Interfaceの実装
- プログラム内で共通して利用したい変数
typedef struct Queue<>{
union Data* queue;
union Data* data;
__code whenEmpty(...);
__code clear(Impl* queue, __code next(...));
__code put(Impl* queue, union Data* data, __code next(...));
__code take(Impl* queue, __code next(union Data* data, ...));
__code isEmpty(Impl* queue, __code next(...), __code whenEmpty(...));
__code next(...);
} Queue;
typedef struct SynchronizedQueue <> impl Queue {
struct Element* top;
struct Element* last;
struct Atomic* atomic;
} SynchronizedQueue;
ContextとGearの関係性
- Context
- 遷移の際にデータを全て記録するオブジェクト
- プログラムに使われるCodeGear/DataGearを管理する
- 軽量継続中、必ず引数で参照される
- メタレベルなCodeGearからのみ参照される
GearsOSのトランスコンパイラ
- CbCプログラムはトランスコンパイルによりC言語プログラムに書き換えられる
- トランスコンパイルの際に、メタレベルの記述が行われる
- StubCodeGearの自動生成
- Gears向けに記述された演算子(par goto、NEW)の書き換え
- StubCodeGearはCbCプログラムへ直に記述することでユーザーの任意の処理に変えられる
__code putSynchronizedQueue_stub(struct Context* context) {
SynchronizedQueue* queue = (SynchronizedQueue*)GearImpl(context, Queue, queue);
Data* data = Gearef(context, Queue)->data;
enum Code next = Gearef(context, Queue)->next;
goto putSynchronizedQueue(context, queue, data, next);
}
__code putSynchronizedQueue(struct Context *context,struct SynchronizedQueue* queue,
union Data* data, enum Code next) {
~省略~
}
分散フレームワークChristie
- Java言語で記述された分散フレームワーク
- CbCとは異なったGearというプログラム概念がある
- 特定のkeyに対する変数データ書き込みにより通信を行う
- 自律分散の実現を目指して開発された
- TopologyManagerという機能を持つ
ChristieのGear
- CodeGear
- スレッドに相当する
- 任意のkey nameを持つDataGearを待ち合わせ、揃ったら処理が実行される
- DataGear
- 変数データに相当する
- key nameと変数データのペアで管理される
- CodeGearManger
- ノードに相当する
- DataGearManagerを所持し、CodeGearとDataGearを管理する
- DataGearManager
- データプールに相当する
- DataGearとkeyの組み合わせを保持している
- LocalDGMとRemoteDGMの二種類が存在する
DataGearManagerによる通信
- ChristieではDataGearの送受信によりノードどうしの通信を行う
- LocalDataGearManager (LocalDGM)
- CodeGearManagerが持つ、自身のDataGearPool
- DataGearの大半はこれを参照する
- RemoteDataGearManager (RemoteDGM)
- 他のCodeGearManagerが持つLocalDGMに対応するploxy
- 書き込みを行うと、対応したCodeGearManagerが持つLocalDGMに書き込みがされる
- DataGearManagerによる通信がChristieの通信の要となっている
TopologyManagear
- 参加を表明したノードに対して任意の形のTopologyに接続する
- 接続 = RemoteDGMを作成する
- 接続されたノードは他のノードを相対的な名前で参照できる(例:Child/parent, right/leftなど)
GearsFileSystemの方針
- データベース的なレコード操作によるファイルアクセス
- ファイルのバックアップ
- ファイルの型の認識
- 自律分散を目指した分散ファイルシステム
GearsFSのファイル構造1/4
- ファイルのデータ単位は任意の型を持ったレコード
- 断続的に分割された状態で保存される
- Queueに保存される
- レコードを先頭から順に読むことでファイルを構成する
- ファイルレコードは構造体で再現される
- ファイルレコード構造体はGearsのDataGearとして利用できる
- レコードの構造体によりOSはファイルの型を認識する
- ファイルの特性に合わせ、レコードとその構成方法を適した形で構成できる
GearsFSのファイル構造2/4
- ファイルの読み込み/書き込みはStreamを通して行われる
- streamも同様にQueueで構成される
- streamはそれぞれ特定のkey nameをもつ
- keyを用いることでアクセスが行われる
- 最低で、Input/OutputのStreamとファイルデータを保持するmainなQueueの三つで構成される
- Write : InputStreamに対してレコードをputすれば良い
- Read : OutputStreamからレコードを全てtakeすれば良い
GearsFSのファイル構造3/4
- ChristieのDataGearManagerに相当する
- GearsOSのファイルは大域的な資源である
- 複数のプロセスより競合的なアクセスが行われる
- OutputStreamは複数のアクセスが行われても整合性が保たれる必要がある
- CAS(Compare And Swap)が採用されたSynchronizedQueueを用いる
GearsFSのファイル構造4/4
- stream、mainQueueはDataGearに相当し、keyによるアクセスが行われる
- Queueは赤黒木に保持される
- key nameで探索が行われ参照される
- DGM書き込みは対象のkey nameを指定する
遠隔からのファイル操作
- GearsOSのファイルは、ファイル通信そのものにも相当する
- RemoteDGMの仕組みを用いることで遠隔からのファイル読み込み/書き込みを行う
socketからの受信データ取り出し
- socketはImplementに記述される
- LocalDGMに相当するファイルは、接続先socketから送信されたデータを取り出す
- APIとして記述される
- 取り出されたデータは次の継続先でQueueに対してputされる
__code getDataLocalDGMQueue(struct LocalDGMQueue* cQueue, __code next(...), __code whenEOF(...), __code whenError(...)){
union Data* recv_data;
recv_size = recv(cQueue->socket, recv_data, sizeof(union Data), 0);
if (recv_size == -1) {
printf("recv error\n");
goto whenError(...);
}
FileString* fileString = NEW(FileString);
fileString = recv_data;
if (fileString->EoF) == 1) {
send_buf = 0;
send_size = send(cQueue->socket, &send_buf, 1, 0);
if (send_size == -1) {
printf("send error\n");
}
close(cQueue->buffer);
goto whenEOF(...);
} else {
send_buf = 1;
send_size = send(cQueue->socket, &send_buf, 1, 0);
if (send_size == -1) {
printf("send error\n");
goto whenError(...);
}
}
Gearef(context, cQueue)->data = recv_data;
goto putLocalDGMQueue(recv_data, next);
}
RemoteDGMのsocketによるデータ送信
- RemoteDGM側はsocketを用いてデータを送信する
- Queueに対してputされたデータを送信する
- putCodeGearの直後に呼び出される
__code sendDataRemoteDGMQueue(struct RemoteDGMQueue* cQueue, union Data* data, __code next(...), __code whenError(...)){
send_size = send(cQueue->socket, data, sizeof(union Data), 0);
if (send_size == -1) {
printf("send error\n");
goto whenError();
}
recv_size = recv(cQueue->socket, &recv_buf, 1, 0);
if (recv_size == -1) {
printf("recv error\n");
goto whenError();
}
goto next(...);
}
WordCount例題
- ChristieAPIの構成をWordCount例題を通して行った
- ファイルの中の文字列を1行ずつ読み取り、ファイル内の文字数と行数を調べる
- ファイルの送信と文字列のカウントをそれぞれ別ノード上で行うことで、ファイル読み込みとファイルレコードの通信処理が構成できる
ChristieAPIによるWordCount
- FileOpen側とWordCount側でノードが別れる
- (手順1)FileOpen側はRDGMに文字列をputする
- (手順2)WordCount側は処理の後、ackを返信する
- (手順3)1,2をループし、FileOpen側はEoFならフラグを送信する
- (手順4)EoFを受信したWordCountは結果を返信し、双方の処理を終了させる
GearsFSのディレクトリ
- ディレクトリを赤黒木で実装する
- 赤黒木のノードとしてファイル/ディレクトリが保存される
- 階層構造はファイル名がkey, データとしてinodeが保存される
GearsFSのバックアップ(1/2)
- ディレクトリツリーを非破壊的な編集で更新する
- 木構造の編集前の構造が履歴となる
- 保存容量の圧迫は対応が必要となる
GearsFSのバックアップ(2/2)
- ファイルレコードを変更差分として構成する
- GithubやMercurialのようなバージョン管理が行える
- 特定の日時までのレコードを読めばよい
- 定期的なファイルの再構築が必要
GearsFSの並列処理
- par gotoを用いる案
- 処理速度が遅い
- トランスコンパイラへの依存度が高い
- 現状バグが存在している
- 新しく並列処理を開発する
GearsOSの問題点
- 記述難易度の高さ
- Contextの操作
- トランスコンパイラでは対応できない継承が存在する
- 場合によりメタレベルの記述を行わなくてはならない
- 軽量継続
- ループ記述が複雑
- goto遷移以降の記述は実行されない
- par gotoの実用が難しい
課題
- TopologyManagerの実装
- ファイルの配線を行う
- DNSの役割
- クラスターの管理
- 並列処理方法の決定
結論
- GearsFileSystemの設計
- ファイルの構成方法
- ファイル操作API
- ファイル送受信の実装
- ディレクトリの仕組み
この先保留ページ
研究成果
- 連続するレコードで構成されるGearsOSファイルの設計
- keyアクセスを用いたファイルに対するRead, writeAPI
- 赤黒木を用いたディレクトリシステムの構築
- ファイルのバックアップ考察
- ploxyを用いたファイルの送受信
API手順
- readの場合(リモート側に読み込みたいファイルが存在する)
- (手順1)ローカル側はLocalDGMの相当する空のファイルを作成し、socketを持つ
- (手順2)リモート側はローカルの空ファイルのploxyを作成する
- (手順3)リモート側はploxyに対してデータをputする
- writeの場合(リモート側に書き込みたいファイルが存在する)
- (手順1)リモート側は対象ファイルにsocketを持たせる
- (手順2)ローカル側は対象のファイルに対応するploxy(RemoteDGM)を作成する
- (手順3)ローカル側はploxyのkeyに対してデータをputする
WordCount手順
- (手順1)ファイル内文字列を1行ずつWordCount関数へ入力する、これをループ
- (手順2)ファイル内文字列が無くなった場合(EoF)結果を出力し、終了する