/**
* Open file
* @param string $path Path
* @param string $flags Flags
* @param callable $cb Callback (File)
* @param integer $mode Mode (see EIO_S_I* constants)
* @param integer $pri Priority
* @return resource
*/
public static function open($path, $flags, $cb, $mode = null, $pri = EIO_PRI_DEFAULT)
{
$cb = CallbackWrapper::forceWrap($cb);
if (!FileSystem::$supported) {
$mode = File::convertFlags($flags, true);
$fd = fopen($path, $mode);
if (!$fd) {
call_user_func($cb, false);
return false;
}
$file = new File($fd, $path);
call_user_func($cb, $file);
return true;
}
$fdCacheKey = $path . "" . $flags;
$noncache = strpos($flags, '!') !== false;
$flags = File::convertFlags($flags);
if (!$noncache && ($item = FileSystem::$fdCache->get($fdCacheKey))) {
// cache hit
$file = $item->getValue();
if ($file === null) {
// operation in progress
$item->addListener($cb);
} else {
// hit
call_user_func($cb, $file);
}
return null;
} elseif (!$noncache) {
$item = FileSystem::$fdCache->put($fdCacheKey, null);
$item->addListener($cb);
}
return eio_open($path, $flags, $mode, $pri, function ($path, $fd) use($cb, $flags, $fdCacheKey, $noncache) {
if ($fd === -1) {
if ($noncache) {
call_user_func($cb, false);
} else {
FileSystem::$fdCache->put($fdCacheKey, false, self::$badFDttl);
}
return;
}
$file = new File($fd, $path);
$file->append = ($flags | EIO_O_APPEND) === $flags;
if ($file->append) {
$file->stat(function ($file, $stat) use($cb, $noncache, $fdCacheKey) {
$file->offset = $stat['size'];
if (!$noncache) {
$file->fdCacheKey = $fdCacheKey;
FileSystem::$fdCache->put($fdCacheKey, $file);
} else {
call_user_func($cb, $file);
}
});
} else {
if (!$noncache) {
$file->fdCacheKey = $fdCacheKey;
FileSystem::$fdCache->put($fdCacheKey, $file);
} else {
call_user_func($cb, $file);
}
}
}, $path);
}