Skip to content

Instantly share code, notes, and snippets.

@comfuture
Created May 23, 2011 06:14
Show Gist options
  • Save comfuture/986309 to your computer and use it in GitHub Desktop.
Save comfuture/986309 to your computer and use it in GitHub Desktop.
using database as filesystem
<?php
class DBStorageStream
{
const DDL = <<<EOF
CREATE TABLE IF NOT EXISTS `table_dbfs` (
`path` VARCHAR(255) NOT NULL PRIMARY KEY,
`data` LONGTEXT,
`is_dir` CHAR(1) NOT NULL DEFAULT 'N',
`created_at` DATETIME,
`updated_at` DATETIME
);
EOF;
private $pdo;
private $mode;
private $path;
private $row;
private $posotion = 0;
public function stream_open($path, $mode, $options, &$opened_path)
{
$parsed = parse_url($path);
$dbinfo = $GLOBALS['__dbfs_' . $parsed['host']];
if (!isset($dbinfo))
throw new Exception($parsed['host'] . ' is not mounted');
$this->pdo = new PDO($dbinfo['dsn'], $dbinfo['username'], $dbinfo['password']);
$this->mode = $mode;
$this->path = $parsed['path'];
if ($mode == 'r') {
try {
$sql = "SELECT * FROM `table_dbfs` WHERE `path`=?";
$stmt = $this->pdo->prepare($sql);
$stmt->execute(array($this->path));
$this->row = $stmt->fetch();
$this->position = 0;
} catch (PDOException $e) {
return false;
}
}
return true;
}
private function create_table()
{
$this->pdo->execute(self::DDL);
}
public function stream_read($count)
{
if (!$this->row)
return false;
$bytes = substr($this->row['data'], $this->position, $count);
$this->position += $count;
return $bytes;
}
public function stream_write($data)
{
if ($this->mode != 'w')
return 0;
$sql = "INSERT INTO `table_dbfs` (`path`, `data`, `created_at`, `updated_at`)" .
"VALUES(?, ?, NOW(), NOW())";
$stmt = $this->pdo->prepare($sql);
$stmt->execute(array($this->path, $data));
return strlen($data);
}
public function stream_eof()
{
if (null === $this->row)
return true;
return ($this->position == sizeof($this->row['data']));
}
public function stream_stat()
{
$stat = array();
$stat[0] = $stat['dev'] = 0;
$stat[1] = $stat['ino'] = 0;
$stat[2] = $stat['mode'] = 0;
$stat[3] = $stat['nlink'] = 0;
$stat[4] = $stat['uid'] = 0;
$stat[5] = $stat['gid'] = 0;
$stat[6] = $stat['rdev'] = 0;
if ($this->row) {
$stat[7] = $stat['size'] = strlen($this->row['data']);
$stat[8] = $stat['atime'] = date('U');
$stat[9] = $stat['mtime'] = $this->row['updated_at'];
$stat[10] = $stat['ctime'] = $this->row['created_at'];
}
$stat[11] = $stat['blksize'] = -1;
$stat[12] = $stat['blocks'] = -1;
return $stat;
}
public function stream_close()
{
// TODO: close pdo handle
$this->pdo = null;
}
public function unlink($path)
{
$sql = "DELETE FROM `table_dbfs` WHERE `path`=?";
$stmt = $this->pdo->prepare($sql);
$rows = $stmt->execute(array($path));
return ($rows == 1);
}
public function rename($path_from, $path_to)
{
$sql = "UPDATE `table_dbfs` SET `path`=? WHERE `path`=?";
$stmt = $this->pdo->prepare($sql);
$rows = $stmt->execute(array($path_to, $path_from));
return ($rows == 1);
}
public function mkdir($path, $mode, $options)
{
$sql = "INSERT INTO `table_dbfs` (`path`, `is_dir`, `created_at`, `updated_at`) " .
"VALUES (?, 'Y', NOW(), NOW())";
$stmt = $this->pdo->prepare($sql);
$rows = $stmt->execute(array($path));
return ($row == 1);
}
public function rmdir($path)
{
return $this->unlink($path);
}
}
function dbfs_mount($local, $path)
{
$parsed = parse_url($path);
$GLOBALS['__dbfs_' . $local] = $dbinfo = array(
'dsn' => $parsed['scheme'] . ':host=' . $parsed['host'] .
';dbname=' . substr($parsed['path'], 1),
'username' => $parsed['user'],
'password' => $parsed['pass']
);
// check if table exists
try {
$fp = fopen('dbfs://' . $local . '/foo', 'r');
$waste = fread($fp, 1);
fclose($fp);
} catch (PDOException $e) {
if (1146 == $e->getCode()) { // XXX: mysql only for now
$pdo = new PDO($dbinfo['dsn'], $dbinfo['username'], $dbinfo['password']);
$pdo->exec(DBStorageStream::DDL);
// catch exception again?
}
}
}
stream_register_wrapper('dbfs', 'DBStorageStream');
?>
<?php
require_once 'DBStorageStream.php';
dbfs_mount('test', 'mysql://user:pass@localhost/dbfs');
$fp = fopen('dbfs://test/image.jpg', 'w');
fwrite($fp, file_get_contents('image.jpg'));
fclose($fp);
$fp = fopen('dbfs://test/image.jpg', 'r');
echo fread($fp, 1024);
fclose($fp);
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment