function sync($console = false) { global $db, $page, $config; $remoteId = $this->get('node_id'); if (!$console && $this->get('use_for_outgoing') != 't') { debug("node {$remoteId} is not used for outgoing sync"); return; } debug("SYNCing with ", $this->get("node_id")); $rpc = new rpc_Utils(); if ($config['debug']) { $rpc->debug = true; } $timestamp = $db->getTimestampTz(); $url = $this->getUrl(); // remove trailing '/' while (substr($url, -1) == '/') { $url = substr($url, 0, -1); } // collect local data to send $localNode = sotf_Node::getLocalNode(); // check if url is correct... if ($localNode->get('url') != $config['rootUrl']) { $localNode->set('url', $config['rootUrl']); $localNode->update(); } //debug("localNode", $localNode); //debug("neighbour", $this); $localNodeData = $localNode->getAll(); // calculate chunking $thisChunk = 1; // do XML-RPC conversation $objectsSent = 0; $more = sotf_NodeObject::countModifiedObjects($remoteId); if (!$more) { debug("No new objects to send"); } while ($more) { $db->begin(true); $modifiedObjects = sotf_NodeObject::getModifiedObjects($remoteId, $this->objectsPerRPCRequest); $remaining = sotf_NodeObject::countModifiedObjects($remoteId); if (count($modifiedObjects) == 0 && $remaining > 0) { logError("DATA integrity problem", "{$remaining} objects remained in sotf_object_status after sync"); } if ($remaining == 0 || count($modifiedObjects) == 0) { $more = false; } else { $more = true; } $chunkInfo = array('this_chunk' => $thisChunk, 'node' => $localNodeData, 'objects_remaining' => $remaining); debug("chunk info", $chunkInfo); debug("number of sent objects", count($modifiedObjects)); $objectsSent = $objectsSent + count($modifiedObjects); $objs = array($chunkInfo, $modifiedObjects); $response = $rpc->call($url . "/xmlrpcServer.php/sync/{$thisChunk}", 'sotf.sync', $objs); // error handling $replyInfo = $response[0]; debug("replyInfo", $replyInfo); if (is_null($response) || $replyInfo['error']) { $this->set('errors', $this->get('errors') + 1); $this->update(); $db->rollback(); return; } $db->commit(); // save received data $thisChunk++; } debug("total number of objects sent", $objectsSent); //$this->log($console, "number of updated objects: " .count($updatedObjects)); // save node and neighbour stats if ($error) { $this->set('errors', $this->get('errors') + 1); } else { $this->set('success', $this->get('success') + 1); } $this->set('last_sync_out', $timestamp); $localNode->set('last_sync_out', $timestamp); // take out from pending nodes if ($this->get('pending_url')) { $remoteNode = sotf_Node::getNodeById($remoteId); // TODO: problem is that if this is first sync or one-way connection, then object fro remote node may not exist if ($remoteNode) { $this->set('pending_url', ''); } $localNode->set('neighbours', $this->getNeighbourString()); } $this->update(); $localNode->update(); }
function syncResponse($chunkInfo, $nodeData, $objects) { global $sotfVars; $timestamp = $this->db->getTimestampTz(); // save modified objects $updatedObjects = sotf_NodeObject::saveModifiedObjects($objects); debug("number of updatd objects", count($updatedObjects)); $remoteId = $this->get('node_id'); $currentStamp = $sotfVars->get('sync_stamp', 0); $lastSyncStamp = $this->lastSyncStamp(); $chunkInfo['old_stamp'] = $lastSyncStamp; $chunkInfo['current_stamp'] = $currentStamp; $count = sotf_NodeObject::countModifiedObjects($remoteId, $lastSyncStamp); if ($count > 0) { if ($chunkInfo['this_chunk'] == $chunkInfo['num_chunks']) { // last chunk: no limits $objectsPerPage = 1000000; } else { $objectsPerPage = ceil($count / $chunkInfo['num_chunks']); } $from = $objectsPerPage * ($chunkInfo['this_chunk'] - 1) + 1; debug("chunk info", $chunkInfo); // get new objects to send as reply $objects = sotf_NodeObject::getModifiedObjects($this->get('node_id'), $lastSyncStamp, $from, $objectsPerPage, $updatedObjects); } else { $objects = array(); } // save time of this sync $this->saveSyncStatus($timestamp, $currentStamp); return array($chunkInfo, $objects); }