PHP標準のmkdirsだと、異なるプロセスやスレッドから新規に複数階層のディレクトリを同時に作成しようとすると後続のmkdirsがエラーになることがあった。
PHPのソースを確認したところ、タイミングによっては、先行するプロセスやスレッドで作成されたディレクトリを後続のプロセスやスレッドが同じディレクトリを作成しようとして失敗し、その結果エラーになる可能性があった。
そこで、ディレクトリ階層のmkdirで失敗してもディレクトリが存在する場合はエラーとしないようにコードを書いてみた。
サンプルコード
const DIRECTORY_SEPARATOR = '/';
function mkdirs($path, $mode = 0777) {
$dirs = explode(DIRECTORY_SEPARATOR, $path);
$currentPath = '';
foreach ($dirs as $dir) {
$currentPath .= _joinDir($currentPath, $dir);
if (!is_dir($currentPath) && !mkdir($currentPath, $mode)) {
$error = error_get_last();
if (!is_dir($currentPath)) {
return false;
}
}
}
return true;
}
function _joinDir($currentDir, $dir) {
if (strlen($dir) <= 0) {
return DIRECTORY_SEPARATOR;
}
if (strlen($currentDir) <= 0 && 0 < strlen($dir)) {
return $dir;
}
if ($currentDir == DIRECTORY_SEPARATOR) {
return $dir;
}
return DIRECTORY_SEPARATOR .$dir;
}
参考
同時実行に耐えうるファイル操作の方式検討 (mkdir システムコール直接発行等 · Issue #12 · ToshiyukiTerashita/castoro