[Phpfreechat-svn] SF.net SVN: phpfreechat: [1086] trunk/src
Status: Beta
Brought to you by:
kerphi
From: <gpi...@us...> - 2007-08-06 13:47:12
|
Revision: 1086 http://phpfreechat.svn.sourceforge.net/phpfreechat/?rev=1086&view=rev Author: gpinzone Date: 2007-08-06 06:47:13 -0700 (Mon, 06 Aug 2007) Log Message: ----------- Introduction of incMeta function to resolve issue of data corruption. The mysql changes need to be tested. Modified Paths: -------------- trunk/src/containers/file.class.php trunk/src/containers/mysql.class.php trunk/src/pfccontainer.class.php Modified: trunk/src/containers/file.class.php =================================================================== --- trunk/src/containers/file.class.php 2007-08-06 13:12:26 UTC (rev 1085) +++ trunk/src/containers/file.class.php 2007-08-06 13:47:13 UTC (rev 1086) @@ -102,7 +102,6 @@ return 0; // value created } - function getMeta($group, $subgroup = null, $leaf = null, $withleafvalue = false) { $c =& pfcGlobalConfig::Instance(); @@ -161,6 +160,63 @@ $ret["timestamp"][] = filemtime($leaffilename); return $ret; + } + + function incMeta($group, $subgroup, $leaf) + { + $c =& pfcGlobalConfig::Instance(); + if ($c->debug) + file_put_contents("/tmp/debug", "\nincMeta(".$group.",".$subgroup.",".$leaf.")", FILE_APPEND | LOCK_EX); + + // create directories + $dir_base = $c->container_cfg_server_dir; + $dir = $dir_base.'/'.$group.'/'.$subgroup; + + if (!is_dir($dir)) mkdir_r($dir); + + // create or replace metadata file + $leaffilename = $dir."/".$leaf; + + // create return array + $ret = array(); + $ret["timestamp"] = array(); + $ret["value"] = array(); + + // read and increment data from metadata file + clearstatcache(); + if (file_exists($leaffilename)) + { + $fh = fopen($leaffilename, 'r+'); + for($i = 0; $i < 10; $i++) // Try 10 times until an exclusive lock can be obtained + { + if (flock($fh, LOCK_EX)) + { + $leafvalue = chop(fread($fh, filesize($leaffilename))); + $leafvalue++; + rewind($fh); + fwrite($fh, $leafvalue); + fflush($fh); + ftruncate($fh, ftell($fh)); + flock($fh, LOCK_UN); + break; + } + // If flock is working properly, this will never be reached + $delay = rand(0, pow(2, ($i+1)) - 1) * 5000; // Exponential backoff + echo "try=".$i." ".$delay."\n"; + usleep($delay); + } + fclose($fh); + } + else + { + $leafvalue="1"; + file_put_contents($leaffilename, $leafvalue, LOCK_EX); + } + + $ret["value"][] = $leafvalue; + $ret["timestamp"][] = filemtime($leaffilename); + + return $ret; } function rmMeta($group, $subgroup = null, $leaf = null) Modified: trunk/src/containers/mysql.class.php =================================================================== --- trunk/src/containers/mysql.class.php 2007-08-06 13:12:26 UTC (rev 1085) +++ trunk/src/containers/mysql.class.php 2007-08-06 13:47:13 UTC (rev 1086) @@ -263,6 +263,82 @@ return $ret; } + + function incMeta($group, $subgroup, $leaf) + { + $c =& pfcGlobalConfig::Instance(); + + if ($c->debug) + file_put_contents("/tmp/debug.txt", "\ngetMeta(".$group.",".$subgroup.",".$leaf.")", FILE_APPEND | LOCK_EX); + + $ret = array(); + $ret["timestamp"] = array(); + $ret["value"] = array(); + + $server = $c->serverid; + $db = $this->_connect(); + + $sql_where .= " AND `leaf`='$leaf'"; + $value = "leafvalue"; + $sql_group_by = ""; + + $sql_select="SELECT `$value`, `timestamp` FROM ".$c->container_cfg_mysql_table." WHERE `server`='$server' $sql_where $sql_group_by ORDER BY timestamp FOR UPDATE"; + + if ($c->debug) + file_put_contents("/tmp/debug.txt", "\ngetSQL(".$sql_select.")", FILE_APPEND | LOCK_EX); + + if ($sql_select != "") + { + $thisresult = mysql_query($sql_select, $db); + if (mysql_num_rows($thisresult)) + { + while ($regel = mysql_fetch_array($thisresult)) + { + $ret["timestamp"][] = $regel["timestamp"]; + $ret["value"][] = $regel[$value]; + } + } + } + + $leafvalue = $ret["value"][]; + + if ($leafvalue == NULL) + $leafvalue = 0; + else + $leafvalue++; + + $timestamp = time(); + + $sql_count = "SELECT COUNT(*) AS C FROM ".$c->container_cfg_mysql_table." WHERE `server`='$server' AND `group`='$group' AND `subgroup`='$subgroup' AND `leaf`='$leaf' LIMIT 1"; + $sql_insert="REPLACE INTO ".$c->container_cfg_mysql_table." (`server`, `group`, `subgroup`, `leaf`, `leafvalue`, `timestamp`) VALUES('$server', '$group', '$subgroup', '$leaf', '".addslashes($leafvalue)."', '".$timestamp."')"; + $sql_update="UPDATE ".$c->container_cfg_mysql_table." SET `leafvalue`='".addslashes($leafvalue)."', `timestamp`='".$timestamp."' WHERE `server`='$server' AND `group`='$group' AND `subgroup`='$subgroup' AND `leaf`='$leaf'"; + + $res = mysql_query($sql_count, $db); + $row = mysql_fetch_array($res, MYSQL_ASSOC); + if( $row['C'] == 0 ) + { + if ($c->debug) + file_put_contents("/tmp/debug.txt", "\nsetSQL(".$sql_insert.")", FILE_APPEND | LOCK_EX); + + mysql_query($sql_insert, $db); + } + else + { + if ($sql_update != "") + { + if ($c->debug) + file_put_contents("/tmp/debug.txt", "\nsetSQL(".$sql_update.")", FILE_APPEND | LOCK_EX); + + mysql_query($sql_update, $db); + } + } + $ret["value"][] = $leafvalue; + $ret["timestamp"][] = $timestamp; + + return $ret; + } + + function rmMeta($group, $subgroup = null, $leaf = null) { $c =& pfcGlobalConfig::Instance(); Modified: trunk/src/pfccontainer.class.php =================================================================== --- trunk/src/pfccontainer.class.php 2007-08-06 13:12:26 UTC (rev 1085) +++ trunk/src/pfccontainer.class.php 2007-08-06 13:47:13 UTC (rev 1086) @@ -476,10 +476,12 @@ { if ($chan == NULL) $chan = 'SERVER'; - $lastmsgid = $this->getLastId($chan); - $lastmsgid++; - $this->setMeta("channelid-to-msgid", $this->encode($chan), 'lastmsgid', $lastmsgid); + $lastmsgid = $this->incMeta("channelid-to-msgid", $this->encode($chan), 'lastmsgid'); + if (count($lastmsgid["value"]) == 0) + $lastmsgid = 0; + else + $lastmsgid = $lastmsgid["value"][0]; return $lastmsgid; } @@ -665,8 +667,34 @@ return $ret; } - + + function incMeta($group, $subgroup, $leaf) + { + $ret = $this->_container->incMeta($group, $subgroup, $leaf); + + if ($this->_usememorycache) + { + // store the modifications in the cache + if (isset($this->_cache[$group]['value']) && + !in_array($subgroup, $this->_cache[$group]['value'])) + { + $this->_cache[$group]['value'][] = $subgroup; + $this->_cache[$group]['timestamp'][] = time(); + } + if (isset($this->_cache[$group]['childs'][$subgroup]['value']) && + !in_array($leaf, $this->_cache[$group]['childs'][$subgroup]['value'])) + { + $this->_cache[$group]['childs'][$subgroup]['value'][] = $leaf; + $this->_cache[$group]['childs'][$subgroup]['timestamp'][] = time(); + } + $this->_cache[$group]['childs'][$subgroup]['childs'][$leaf]['value'] = array($leafvalue); + $this->_cache[$group]['childs'][$subgroup]['childs'][$leaf]['timestamp'] = array(time()); + } + + return $ret; + } + /** * Remove a meta data or a group of metadata * @param $group if null then it will remove all the possible groups (all the created metadata) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |