mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-25 09:23:28 +01:00
ability to migrate DB based sqlfs to a filesystem based one using filemanager/cli.php (see usage)
This commit is contained in:
parent
fc07594746
commit
2978d9ddd2
@ -6,7 +6,7 @@
|
|||||||
* @link http://www.egroupware.org
|
* @link http://www.egroupware.org
|
||||||
* @package filemanager
|
* @package filemanager
|
||||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||||
* @copyright (c) 2007/8 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
* @copyright (c) 2007-10 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*
|
*
|
||||||
@ -64,6 +64,7 @@ function usage($action=null,$ret=0)
|
|||||||
echo "\t$cmd mount URL [path] (without path prints out the mounts)\n";
|
echo "\t$cmd mount URL [path] (without path prints out the mounts)\n";
|
||||||
echo "\t$cmd umount [-a|--all (restores default mounts)] URL|path\n";
|
echo "\t$cmd umount [-a|--all (restores default mounts)] URL|path\n";
|
||||||
echo "\t$cmd eacl URL [rwx-] [user or group]\n";
|
echo "\t$cmd eacl URL [rwx-] [user or group]\n";
|
||||||
|
echo "\tsudo -u apache $cmd migrate-db2fs --user root_admin --passwd password [--domain default] (migrates sqlfs content from DB to filesystem)\n";
|
||||||
|
|
||||||
echo "\nCommon options: --user user --password password [--domain domain] can be used to pass eGW credentials without using the URL writing.\n";
|
echo "\nCommon options: --user user --password password [--domain domain] can be used to pass eGW credentials without using the URL writing.\n";
|
||||||
echo "\nURL: {vfs|sqlfs|filesystem}://user:password@domain/home/user/file[?option=value&...], /dir/file, ...\n";
|
echo "\nURL: {vfs|sqlfs|filesystem}://user:password@domain/home/user/file[?option=value&...], /dir/file, ...\n";
|
||||||
@ -252,6 +253,35 @@ switch($cmd)
|
|||||||
rename($argv[0],$argv[1]);
|
rename($argv[0],$argv[1]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'migrate-db2fs':
|
||||||
|
if (empty($user) || empty($passwd) || !egw_vfs::$is_root)
|
||||||
|
{
|
||||||
|
die("\nYou need to be root to do that!\n\n");
|
||||||
|
}
|
||||||
|
if (!is_writable($GLOBALS['egw_info']['server']['files_dir'])) exit; // we need write access, error msg already given
|
||||||
|
$fstab = egw_vfs::mount();
|
||||||
|
if (!is_array($fstab) || !isset($fstab['/']) || strpos($fstab['/'],'storage=db') === false)
|
||||||
|
{
|
||||||
|
foreach($fstab as $path => $url)
|
||||||
|
{
|
||||||
|
echo "$url\t$path\n";
|
||||||
|
}
|
||||||
|
die("\n/ NOT mounted with 'storage=db' --> no need to convert!\n\n");
|
||||||
|
}
|
||||||
|
$num_files = sqlfs_stream_wrapper::migrate_db2fs(); // throws exception on error
|
||||||
|
echo "\n$num_files files migrated from DB to filesystem.\n";
|
||||||
|
$new_url = preg_replace('/storage=db&?/','',$fstab['/']);
|
||||||
|
if (substr($new_url,-1) == '?') $new_url = substr($new_url,0,-1);
|
||||||
|
if (egw_vfs::mount($new_url,'/'))
|
||||||
|
{
|
||||||
|
echo "/ successful re-mounted on $new_url\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
echo "\nre-mounting $new_url on / failed!\n\n";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
while($argv)
|
while($argv)
|
||||||
{
|
{
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
/**
|
/**
|
||||||
* eGroupWare API: VFS - new DB based VFS stream wrapper
|
* eGroupWare API: VFS - new DB based VFS stream wrapper
|
||||||
*
|
*
|
||||||
* The sqlfs stream wrapper has 3 operation modi:
|
* The sqlfs stream wrapper has 2 operation modi:
|
||||||
* - content of files is stored in the filesystem (eGW's files_dir) (default)
|
* - content of files is stored in the filesystem (eGW's files_dir) (default)
|
||||||
* - content of files is stored as BLOB in the DB (can be enabled by mounting sqlfs://...?storage=db)
|
* - content of files is stored as BLOB in the DB (can be enabled by mounting sqlfs://...?storage=db)
|
||||||
* please note the current (php5.2.6) problems:
|
* please note the current (php5.2.6) problems:
|
||||||
@ -1800,6 +1800,80 @@ class sqlfs_stream_wrapper implements iface_stream_wrapper
|
|||||||
if (self::LOG_LEVEL > 1) foreach((array)$props as $k => $v) error_log(__METHOD__."($path_ids,$ns) $k => ".array2string($v));
|
if (self::LOG_LEVEL > 1) foreach((array)$props as $k => $v) error_log(__METHOD__."($path_ids,$ns) $k => ".array2string($v));
|
||||||
return $props;
|
return $props;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migrate SQLFS content from DB to filesystem
|
||||||
|
*
|
||||||
|
* @param boolean $debug true to echo a message for each copied file
|
||||||
|
*/
|
||||||
|
static function migrate_db2fs($debug=false)
|
||||||
|
{
|
||||||
|
if (!is_object(self::$pdo))
|
||||||
|
{
|
||||||
|
self::_pdo();
|
||||||
|
}
|
||||||
|
$query = 'SELECT fs_id,fs_name,fs_size,fs_content'.
|
||||||
|
' FROM '.self::TABLE.' WHERE fs_content IS NOT NULL';
|
||||||
|
|
||||||
|
$stmt = self::$pdo->prepare($query);
|
||||||
|
$stmt->bindColumn(1,$fs_id);
|
||||||
|
$stmt->bindColumn(2,$fs_name);
|
||||||
|
$stmt->bindColumn(3,$fs_size);
|
||||||
|
$stmt->bindColumn(4,$fs_content,PDO::PARAM_LOB);
|
||||||
|
|
||||||
|
if ($stmt->execute())
|
||||||
|
{
|
||||||
|
foreach($stmt as $row)
|
||||||
|
{
|
||||||
|
// hack to work around a current php bug (http://bugs.php.net/bug.php?id=40913)
|
||||||
|
// PDOStatement::bindColumn(,,PDO::PARAM_LOB) is not working for MySQL, content is returned as string :-(
|
||||||
|
if (is_string($fs_content))
|
||||||
|
{
|
||||||
|
$name = md5($fs_name.$fs_id);
|
||||||
|
$GLOBALS[$name] =& $fs_content;
|
||||||
|
require_once(EGW_API_INC.'/class.global_stream_wrapper.inc.php');
|
||||||
|
$content = fopen('global://'.$name,'r');
|
||||||
|
if (!$content) echo "fopen('global://$name','w' failed, strlen(\$GLOBALS['$name'])=".strlen($GLOBALS[$name]).", \$GLOBALS['$name']=".substr($GLOBALS['$name'],0,100)."...\n";
|
||||||
|
unset($GLOBALS[$name]); // unset it, so it does not use up memory, once the stream is closed
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$content = $fs_content;
|
||||||
|
}
|
||||||
|
if (!is_resource($content))
|
||||||
|
{
|
||||||
|
throw new egw_exception_assertion_failed(__METHOD__."(): fs_id=$fs_id ($fs_name, $fs_size bytes) content is NO resource! ".array2string($content));
|
||||||
|
}
|
||||||
|
$filename = self::_fs_path($fs_id);
|
||||||
|
if (!file_exists($fs_dir=dirname($filename)))
|
||||||
|
{
|
||||||
|
self::mkdir_recursive($fs_dir,0700,true);
|
||||||
|
}
|
||||||
|
if (!($dest = fopen($filename,'w')))
|
||||||
|
{
|
||||||
|
throw new egw_exception_assertion_failed(__METHOD__."(): fopen($filename,'w') failed!");
|
||||||
|
}
|
||||||
|
if (($bytes = stream_copy_to_stream($content,$dest)) != $fs_size)
|
||||||
|
{
|
||||||
|
throw new egw_exception_assertion_failed(__METHOD__."(): fs_id=$fs_id ($fs_name) $bytes bytes copied != size of $fs_size bytes!");
|
||||||
|
}
|
||||||
|
if ($debug) echo "$fs_id: $fs_name: $bytes bytes copied to fs\n";
|
||||||
|
fclose($dest);
|
||||||
|
fclose($content); unset($content);
|
||||||
|
|
||||||
|
++$n;
|
||||||
|
}
|
||||||
|
unset($stmt);
|
||||||
|
|
||||||
|
if ($n) // delete all content in DB, if there was some AND no error (exception thrown!)
|
||||||
|
{
|
||||||
|
$query = 'UPDATE '.self::TABLE.' SET fs_content=NULL WHERE fs_content IS NOT NULL';
|
||||||
|
$stmt = self::$pdo->prepare($query);
|
||||||
|
$stmt->execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $n;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stream_register_wrapper(sqlfs_stream_wrapper::SCHEME ,'sqlfs_stream_wrapper');
|
stream_register_wrapper(sqlfs_stream_wrapper::SCHEME ,'sqlfs_stream_wrapper');
|
||||||
|
Loading…
Reference in New Issue
Block a user