/**
  *Renames a child node
  * @param I2CE_MagicDataNode $node
  *@param string $old
  *@param string $new
  *@returns boolean.  True on success, false on failure
  */
 public function renameChild($node, $old, $new)
 {
     $keys = array(self::TYPE => true, self::VALUE => true, self::CHILDREN => true);
     $result = $this->mcoll->findOne(array(self::PATH => $node->getPath(false)), $keys);
     if (!is_array($result) || count($result) == 0) {
         I2CE::raiseError("Could not update -- non-existing node");
         return false;
     }
     if (($key = array_search($old, $result[self::CHILDREN])) === false) {
         I2CE::raiseError("Child {$old} on " . $node->getPath(false) . " does not exist");
         return false;
     }
     $result[self::CHILDREN][$key] = $new;
     $newdata = array('$set' => array(self::CHILDREN => $result[self::CHILDREN]));
     if (!is_array($res = $this->mcoll->update(array(self::PATH => $node->getPath(false)), $newdata, array('safe' => true))) || array_key_exists('err', $res) && $res['err']) {
         I2CE::raiseError("Could not update new children:" . print_r($res, true));
         return false;
     }
     return $this->renameDecendents($node, array($old => $new));
 }
 /**
  * Store the given magic data node (which should be a descendent
  * of this instance.)  Starts storing at the last added storage
  * mechanism until it reaches the first storage mechanism.  If it
  * fails saving at any storage mechanis, it will call the destroy
  * method on that storage mechanism and any remaining one.
  *
  * @param  I2CE_MagicDataNode $node
  * @param  integer            $max  The max index of storage objects to save.
  *                                  Defaults to -1 meaning we store on all 
  *                                  mechanisms
  * @returns boolean  true on success.  
  */
 public function store($node, $max = -1)
 {
     if ($node->type == I2CE_MagicDataNode::TYPE_NOT_POPULATED) {
         I2CE::raiseError("Trying to store magic data which is unpopulated at " . $node->getPath());
         return FALSE;
     }
     if ($this->num_storage === 0) {
         return TRUE;
     }
     if ($max < 0 || $max > $this->num_storage) {
         $max = $this->num_storage - 1;
     }
     //there is a problem here if there in only one storage mechanism that we have just retrieved/populated from
     $fails = array();
     for ($i = $max; $i >= 0; $i--) {
         if (!$this->storage[$i]->store($node)) {
             $fails[] = $i;
         }
     }
     if (count($fails) > 0) {
         $fail_max = max($fails);
         if ($fail_max == $this->num_storage - 1) {
             I2CE::raiseError("Unrecoverable data storage failure for " . $node->getPath());
             return false;
             //we failed on the permanent data store
         }
         I2CE::raiseError("Attempting to recover from data storage failure for " . $node->getPath());
         //we did not fail on the permanent data store
         //we try to clear all caches at and above the failure point.
         $cleared = true;
         for ($i = $fail_max; $i >= 0; $i--) {
             $cleared &= $this->storage[$i]->destroy($node);
         }
         if (!$cleared) {
             I2CE::raiseError("Could not clear cached data for " . $node->getPath());
             return false;
         }
     }
     return true;
 }
 /**
  *Renames a child node
  * @param I2CE_MagicDataNode $node
  *@param string $old
  *@param string $new
  *@returns boolean.  True on success, false on failure
  */
 public function renameChild($node, $old, $new)
 {
     if ($node instanceof I2CE_MagicData) {
         $parentPath = '/';
         $offset = strlen('/' . $old) + 1;
         $fullOffset = strlen($node->getPath(true) . '/' . $old);
         // if $old ='old', results in calling SUBSTR(parent,5)
         //so if parent = '/old/path' then substr(parent,5) = '/path'
         //we want to result in /new/path
     } else {
         $parentPath = $node->getPath(false);
         //e.g.
         $offset = strlen($node->getPath(false) . '/' . $old) + 1;
         $fullOffset = strlen($node->getPath(true) . '/' . $old);
         //child: if $old = 'old' and $node='/some', then calling SUBSTR(parent, 10)
         //so if parent = /some/old/path then substr(parent,10) = /path
         //we want to result in /some/new/path
     }
     $newPath = mysql_real_escape_string($this->getChildPath($node, $new, false));
     $newFullPath = mysql_real_escape_string($this->getChildPath($node, $new, true));
     $oldPath = mysql_real_escape_string($this->getChildPath($node, $old, false));
     $qry_node = "UPDATE config_alt SET name = '" . mysql_real_escape_string($new) . "' , path_hash = '" . mysql_real_escape_string($this->getHash($node, $new)) . "' " . "WHERE parent = '" . mysql_real_escape_string($parentPath) . "' AND name = '" . mysql_real_escape_string($old) . "'";
     //change direct children
     $qry_child = "UPDATE config_alt SET  " . "  path_hash = MD5(CONCAT('{$newFullPath}', '/',name)) " . ", parent = '{$newPath}' " . "WHERE parent = '{$oldPath}'";
     //change descendents
     $qry_desc = "UPDATE config_alt SET  " . "  path_hash = MD5( CONCAT('{$newFullPath}', SUBSTR(parent,{$offset}) , '/',name)) " . ", parent = CONCAT('{$newPath}', SUBSTR(parent,{$offset}) ) " . "WHERE parent LIKE '{$oldPath}/%'";
     $this->db->exec($qry_node);
     $this->db->exec($qry_child);
     $this->db->exec($qry_desc);
     return true;
 }
 /**
  * Return the md5 Hash of the path of this object.
  * @param I2CE_MagicDataNode $node
  * @param string $childPath 
  * @param boolean $show_top defaults to true if we are to show the parent
  * @return string
  */
 public function getChildPath($node, $childPath, $show_top = true)
 {
     if ($show_top) {
         if ($node instanceof I2CE_MagicData) {
             return $node->getPath(true) . $node->pathDivider() . $childPath;
         } else {
             return $node->getPath(true) . '/' . $childPath;
         }
     } else {
         if ($node instanceof I2CE_MagicData) {
             return '/' . $childPath;
         } else {
             return $node->getPath(false) . '/' . $childPath;
         }
     }
 }