* @version 0.0.0 * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2012 Hub Developer Team * @license GNU GPL 3.0 or any newer version * @link http://www.ship-simu.org * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ class NodeDistributedHashTableDatabaseWrapper extends BaseDatabaseWrapper implements NodeDhtWrapper, Registerable { // Constants for database table names const DB_TABLE_NODE_DHT = 'node_dht'; // Constants for database column names const DB_COLUMN_NODE_ID = 'node_id'; const DB_COLUMN_SESSION_ID = 'session_id'; const DB_COLUMN_EXTERNAL_IP = 'external_ip'; const DB_COLUMN_LISTEN_PORT = 'listen_port'; const DB_COLUMN_PRIVATE_KEY = 'private_key'; const DB_COLUMN_PRIVATE_KEY_HASH = 'private_key_hash'; const DB_COLUMN_NODE_TYPE = 'node_type'; /** * Protected constructor * * @return void */ protected function __construct () { // Call parent constructor parent::__construct(__CLASS__); } /** * Creates an instance of this database wrapper by a provided user class * * @return $wrapperInstance An instance of the created wrapper class */ public static final function createNodeDistributedHashTableDatabaseWrapper () { // Get a new instance $wrapperInstance = new NodeDistributedHashTableDatabaseWrapper(); // Set (primary!) table name $wrapperInstance->setTableName(self::DB_TABLE_NODE_DHT); // Return the instance return $wrapperInstance; } /** * Prepares a "local" instance of a StoreableCriteria class with all node * data for insert/update queries. This data set contains data from *this* * (local) node. * * @return $dataSetInstance An instance of a StoreableCriteria class */ private function prepareLocalDataSetInstance () { // Get node/request instances $nodeInstance = Registry::getRegistry()->getInstance('node'); $requestInstance = ApplicationHelper::getSelfInstance()->getRequestInstance(); // Get a dataset instance $dataSetInstance = ObjectFactory::createObjectByConfiguredName('dataset_criteria_class', array(self::DB_TABLE_NODE_DHT)); // Set the primary key $dataSetInstance->setUniqueKey(self::DB_COLUMN_NODE_ID); // Get ip:port combination and "explode" it $ipPort = $nodeInstance->getAddressPortArray(); // Make sure both is valid assert(($ipPort[0] !== 'invalid') && ($ipPort[1] !== 'invalid')); // Add public node data $dataSetInstance->addCriteria(self::DB_COLUMN_NODE_TYPE , $requestInstance->getRequestElement('mode')); $dataSetInstance->addCriteria(self::DB_COLUMN_EXTERNAL_IP , $ipPort[0]); $dataSetInstance->addCriteria(self::DB_COLUMN_LISTEN_PORT , $ipPort[1]); $dataSetInstance->addCriteria(self::DB_COLUMN_NODE_ID , $nodeInstance->getNodeId()); $dataSetInstance->addCriteria(self::DB_COLUMN_SESSION_ID , $nodeInstance->getSessionId()); $dataSetInstance->addCriteria(self::DB_COLUMN_PRIVATE_KEY_HASH, $nodeInstance->getPrivateKeyHash()); // Return it return $dataSetInstance; } /** * Checks whether the local (*this*) node is registered in the DHT by * checking if the external ip/port is found. * * @return $isRegistered Whether *this* node is registered in the DHT */ public function isLocalNodeRegistered () { // Is there cache? if (!isset($GLOBALS[__METHOD__])) { // Get a search criteria instance $searchInstance = ObjectFactory::createObjectByConfiguredName('search_criteria_class'); // Get node instance $nodeInstance = Registry::getRegistry()->getInstance('node'); // Get ip:port combination and "explode" it $ipPort = $nodeInstance->getAddressPortArray(); // Make sure both is valid assert(($ipPort[0] !== 'invalid') && ($ipPort[1] !== 'invalid')); // Add ip:port/node id as criteria $searchInstance->addCriteria(self::DB_COLUMN_EXTERNAL_IP, $ipPort[0]); $searchInstance->addCriteria(self::DB_COLUMN_LISTEN_PORT, $ipPort[1]); $searchInstance->addCriteria(self::DB_COLUMN_NODE_ID , $nodeInstance->getNodeId()); $searchInstance->setLimit(1); // Query database and get a result instance back $resultInstance = $this->doSelectByCriteria($searchInstance); // Cache result of if there is an entry, next() will tell us if the next entry is valid $GLOBALS[__METHOD__] = $resultInstance->next(); } // END - if // Return result return $GLOBALS[__METHOD__]; } /** * Registeres the local (*this*) node with its data in the DHT. * * @return void */ public function registerLocalNode () { // Assert to make sure this method is called with no record in DB (the actual backend of the DHT) assert(!$this->isLocalNodeRegistered()); // Get prepared data set instance $dataSetInstance = $this->prepareLocalDataSetInstance(); // "Insert" this dataset instance completely into the database $this->queryInsertDataSet($dataSetInstance); } /** * Updates local (*this*) node data in DHT, this is but not limited to the * session id, ip number (and/or hostname) and port number. * * @return void */ public function updateLocalNode () { // Assert to make sure this method is called with one record in DB (the actual backend of the DHT) assert($this->isLocalNodeRegistered()); // Get node instance $nodeInstance = Registry::getRegistry()->getInstance('node'); // Get search criteria $searchInstance = ObjectFactory::createObjectByConfiguredName('search_criteria_class'); // Search for node id and limit it to one entry $searchInstance->addCriteria(self::DB_COLUMN_NODE_ID, $nodeInstance->getNodeId()); $searchInstance->setLimit(1); // Get a prepared dataset instance $dataSetInstance = $this->prepareLocalDataSetInstance(); // Set search instance $dataSetInstance->setSearchInstance($searchInstance); // Update DHT database record $this->queryUpdateDataSet($dataSetInstance); } /** * Finds a node locally by given session id * * @param $sessionId Session id to lookup * @return $nodeData Node data array */ public function findNodeLocalBySessionId ($sessionId) { // Get search criteria $searchInstance = ObjectFactory::createObjectByConfiguredName('search_criteria_class'); // Search for session id and limit it to one entry $searchInstance->addCriteria(self::DB_COLUMN_SESSION_ID, $sessionId); $searchInstance->setLimit(1); // Query database and get a result instance back $resultInstance = $this->doSelectByCriteria($searchInstance); // Return result instance return $resultInstance; } /** * Registeres a node by given message data. * * @param $messageData An array of all message data * @param $handlerInstance An instance of a HandleableMessage class * @return void */ public function registerNodeByMessageData (array $messageData, Handleable $handlerInstance) { // Get a data set instance $dataSetInstance = ObjectFactory::createObjectByConfiguredName('dataset_criteria_class', array(self::DB_TABLE_NODE_DHT)); // Set primary key (session id) $dataSetInstance->setUniqueKey(self::DB_COLUMN_SESSION_ID); // Add all array elements $handlerInstance->addArrayToDataSet($dataSetInstance, $messageData); // Run the "INSERT" query $this->queryInsertDataSet($dataSetInstance); } /** * Updates an existing entry in node list * * @param $messageData An array of all message data * @param $handlerInstance An instance of a HandleableMessage class * @param $searchInstance An instance of LocalSearchCriteria class * @return void */ public function updateNodeByMessageData (array $messageData, Handleable $handlerInstance, LocalSearchCriteria $searchInstance) { // Get a data set instance $dataSetInstance = ObjectFactory::createObjectByConfiguredName('dataset_criteria_class', array(self::DB_TABLE_NODE_DHT)); // Add search instance $dataSetInstance->setSearchInstance($searchInstance); // Set primary key (session id) $dataSetInstance->setUniqueKey(self::DB_COLUMN_SESSION_ID); // Add all array elements $handlerInstance->addArrayToDataSet($dataSetInstance, $messageData); // Run the "UPDATE" query $this->queryUpdateDataSet($dataSetInstance); } } // [EOF] ?>