Reputation: 1
}
public function backup(){
$app =& JFactory::getApplication();
$createTablesSQL = $this->_dbo->getTableCreate($this->_tables);
$databaseName = $app->getCfg("db");
$data = "--\n-- Database: `{$databaseName}`\n--\n\n";
foreach ($createTablesSQL as $key => $value){
$data .= "DROP TABLE IF EXISTS `{$key}`;\n";
$data .= "\n--\n-- Table structure for table `{$key}`\n--\n";
$data .= $value . ";\n";
$tableFields = $this->_dbo->getTableFields($key);
$this->_dbo->setQuery("SELECT * FROM `{$key}`");
$this->_dbo->query();
if($this->_dbo->getNumRows()){
$data .= "--\n-- Dumping data for table `{$key}`\n--\n";
$data .= "LOCK TABLES `{$key}` WRITE;\n";
$fields = array_keys($tableFields);
$data .= "REPLACE INTO `{$key}` (`".implode("`, `", array_keys($tableFields[$fields[0]]))."`) VALUES \n";
// Load data from table
$rows = $this->_dbo->loadRowList();
$_ = array();
foreach ($rows as $row){
foreach ($row as $k => $v){
if(!isset($v))
$row[$k] = 'NULL';
else
$row[$k] = "'".addslashes($v)."'";
}
$_[] = "\t(".implode(", ", $row).")";
}
$data .= implode(",\n", $_);
$data .= ";\nUNLOCK TABLES;\n\n";
}
}
// fix dbprefix after getTableCreate
$tablePrefix = $app->getCfg("dbprefix");
$data = str_replace($tablePrefix, "#__", $data);
// write backup file
$path2Filename = $this->path2BackupFiles;
$filename = $this->filePrefix . date("Y_m_d_H_i_s", time()) . "_" . CompanyUpdate::getCurrentVersion() . ".sql";
if(JFile::write($path2Filename . $filename, $data)){
// compression
if(false != ($arFile = $this->compressFile($path2Filename, $filename, 'zip', true))){
return $arFile;
}else{
return false;
}
}else{
return false;
}
}
/**
*
* @param string $path2Filename
* @param string $filename
* @param string $type
* @param bool $cleanUp
* @return bool
*/
private function compressFile($path2Filename, $filename, $type = 'zip', $cleanUp = false){
$fullPathFilename = $path2Filename . $filename;
$adapter =& JArchive::getAdapter($type); // type compression
$files2ZIP = array();
$files2ZIP[0]["name"] = $filename;
$files2ZIP[0]["data"] = JFile::read($fullPathFilename);
if($adapter->create($fullPathFilename . "." . $type, $files2ZIP, $type, $path2Filename)){
if($cleanUp)
JFile::delete($fullPathFilename);
return JFile::stripExt($filename) . "." . $type;
}else{
return false;
}
}
} ?>
Anyone see a leak here somewhere?
EDIT: Should have thought to post the error. Sorry
Fatal error: Out of memory (allocated 65536000) (tried to allocate 125459 bytes) in /home/user2/public_html/administrator/components/com_company/lib/CompanyBaseDManagement.php on line 395
According to Dreamweaver this is line 395: $row[$k] = "'".addslashes($v)."'";
Upvotes: 0
Views: 1036
Reputation: 2092
The whole script is horribly memory inefficient. It should be appending the data out in chunks to the backup file rather than reading the entire damn database into memory and then running a str_replace() on it, then possibly sending that over to a compression function which re-reads the file into memory and compresses it. !!!
Honestly, the only easy way I can see this getting fixed is to up the memory limit in your php.ini file, try 128MB. If your db keeps growing then this number will keep having to go up. It'd be more efficient to scrap that script and use mysqldump + gzip on the command line, if you have access.
Upvotes: 3
Reputation:
Are you very sure it's a leak? Not just the backup exceeding your memory limit? I can't see what the obvious problem is but have you considered putting in some debugging of the memory consumption and loop iteration number around that loop? It could be an iffy row of data which should be very obvious with a sudden jump in consumption
http://uk.php.net/manual/en/function.memory-get-usage.php
Upvotes: 0
Reputation: 15093
Well I know for a fact that editing an array that is being acted upon by a foreach
loop (like how that foreach
loop is in your code) is very dangerous. I am surprised it's not throwing an error (I thought for some rea-- wait nevermind, wrong language that throws an error about editing foreach loop arrays). I think there might be an infinite loop there. I have seen instances where a foreach loop would push a new object onto the array it was referencing, ultimately causing an infinite loop (since it never runs out of elements to iterate upon)!
A good place to start would be to separate the array being referenced and a new array with the new values, and then merging them or whatever after the foreach loop.
Upvotes: 0