起動プロセス(7) open_or_create_data_files関数

innobase_start_or_create_for_mysql関数の中で呼び出される。



データファイルは最大で1000個まで。

1. srv_n_data_files(データファイルの個数)の数だけ、for文で必要に応じて複数回os_file_create関数を呼び出す。ここでは以下のフラグを渡している。この時点ではデータファイルを新規作成するのか既存のファイルがあるので開くだけなのかの区別は無い。新規作成の場合にはファイルディスクリプタ番号、既存のファイルが存在する場合には-1を受け取る。

  • OS_FILE_CREATE, OS_FILE_NORMAL, OS_DATA_FILE

2. 既にファイルが存在している場合には、同じforループ内でフラグを変えて再度os_file_create関数を呼び出す。

  • OS_FILE_OPEN_RETRY, OS_FILE_NORMAL, OS_DATA_FILE

3. 既にファイルが存在している場合には、os_file_get_size関数を呼び出してファイルのサイズを取得する。この時、システムコールlseekを使用しているが、このシステムコールが返すファイルサイズは4bytesではなく8bytesで表現されているため、 4GB超のファイルであっても扱うことができる。InnoDBはこれを4bytesの2つの変数に分割して受け取り、内部管理を行う。(&size、&size_high。)ちなみに8bytes分の数値情報を2つの4bytes変数で保持するというやり方はInnoDBでは随所で見られる。そのために(今回は使用していないが)dulintという構造体が使用されることがある。
4. ファイルの新規作成の場合には、この時点ではまだibdata1等のサイズが0のままなので、指定された初期サイズまで拡張させる必要がある。os_file_set_size関数をibdata1等が指定サイズに達するまで繰り返し呼び出す。
5. その後、ibdata1等のファイルをcloseする。fil_node_createの処理の際にcloseしてある必要があるため。
6. fil_space_create関数を呼び出す。
7. fil_node_create関数を呼び出す。



■os_file_create関数
この関数ではいくつかの条件分岐が存在する。OS_FILE_CREATEが指定されている場合には、デバッガで見たところ、システムコールのopen関数を以下のように呼び出していた。

file = open(name, create_flag, os_innodb_umask);

ここで使用しているcreate_flagはos0file.cの1250行目過ぎで設定されているが、デバッガで見ていたときには以下の3つのフラグが設定されていた。

  • O_RDWR, O_CREATE, O_EXCL

またos_innodb_umaskは0660。ここでファイルのアクセス権限を指定している。

フラグO_CREATEを使用しているのでファイルが存在しない場合には作成することになるが、O_EXCLも使用しているので既にファイルが存在する場合にはファイルを開くのではなくエラーが返ることになる。(システムコールopenはファイルディスクリプタ番号の代わりに-1を返す。)

os_file_create関数はこの戻り値をopen_or_create_data_files関数に返す。

OS_FILE_OPEN_RETRYが指定されている場合には、今度はO_RDWRのみをcreate_flagに指定してシステムコールopenを呼び出す。

file = open(name, create_flag);



■os_file_set_size関数
1MBのバッファを用意し、その中身をmemsetでゼロで埋めた後、指定のサイズに達するまで繰り返し書き込みを行う。

os_file_set_siz関数はさらにos_file_pwrite関数を呼び出す。os_file_pwrite関数ではシステムコールlseekを使ってオフセットを指定位置に変更した後、システムコールwriteを使ってバッファをファイルに書き込む。