]> git.mxchange.org Git - hub.git/blob - application/hub/main/wrapper/node/class_NodeDistributedHashTableDatabaseWrapper.php
Continued:
[hub.git] / application / hub / main / wrapper / node / class_NodeDistributedHashTableDatabaseWrapper.php
1 <?php
2 /**
3  * A database wrapper for distributed hash tables
4  *
5  * @author              Roland Haeder <webmaster@shipsimu.org>
6  * @version             0.0.0
7  * @copyright   Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2014 Hub Developer Team
8  * @license             GNU GPL 3.0 or any newer version
9  * @link                http://www.shipsimu.org
10  *
11  * This program is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation, either version 3 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program. If not, see <http://www.gnu.org/licenses/>.
23  */
24 class NodeDistributedHashTableDatabaseWrapper extends BaseDatabaseWrapper implements NodeDhtWrapper, Registerable {
25         /**
26          * "Cached" results for dabase for looking for unpublished entries
27          */
28         private $unpublishedEntriesInstance = NULL;
29
30         // Constants for database table names
31         const DB_TABLE_NODE_DHT = 'node_dht';
32
33         // Constants for database column names
34         const DB_COLUMN_NODE_ID            = 'node_id';
35         const DB_COLUMN_SESSION_ID         = 'session_id';
36         const DB_COLUMN_EXTERNAL_IP        = 'external_ip';
37         const DB_COLUMN_LISTEN_PORT        = 'listen_port';
38         const DB_COLUMN_PRIVATE_KEY_HASH   = 'private_key_hash';
39         const DB_COLUMN_NODE_MODE          = 'node_mode';
40         const DB_COLUMN_ACCEPTED_OBJECTS   = 'accepted_object_types';
41         const DB_COLUMN_NODE_LIST          = 'node_list';
42         const DB_COLUMN_PUBLICATION_STATUS = 'publication_status';
43         const DB_COLUMN_ANSWER_STATUS      = 'answer_status';
44         const DB_COLUMN_ACCEPT_BOOTSTRAP   = 'accept_bootstrap';
45
46         // Publication status'
47         const PUBLICATION_STATUS_PENDING = 'PENDING';
48
49         // Exception codes
50         const EXCEPTION_NODE_ALREADY_REGISTERED = 0x800;
51         const EXCEPTION_NODE_NOT_REGISTERED     = 0x801;
52
53         /**
54          * Protected constructor
55          *
56          * @return      void
57          */
58         protected function __construct () {
59                 // Call parent constructor
60                 parent::__construct(__CLASS__);
61         }
62
63         /**
64          * Creates an instance of this database wrapper by a provided user class
65          *
66          * @return      $wrapperInstance        An instance of the created wrapper class
67          */
68         public static final function createNodeDistributedHashTableDatabaseWrapper () {
69                 // Get a new instance
70                 $wrapperInstance = new NodeDistributedHashTableDatabaseWrapper();
71
72                 // Set (primary!) table name
73                 $wrapperInstance->setTableName(self::DB_TABLE_NODE_DHT);
74
75                 // Return the instance
76                 return $wrapperInstance;
77         }
78
79         /**
80          * Static getter for an array of all DHT database entries
81          *
82          * @return      $elements       All elements for the DHT dabase
83          */
84         public static final function getAllElements () {
85                 // Create array and ...
86                 $elements = array(
87                         self::DB_COLUMN_NODE_ID,
88                         self::DB_COLUMN_SESSION_ID,
89                         self::DB_COLUMN_EXTERNAL_IP,
90                         self::DB_COLUMN_LISTEN_PORT,
91                         self::DB_COLUMN_PRIVATE_KEY_HASH,
92                         self::DB_COLUMN_NODE_MODE,
93                         self::DB_COLUMN_ACCEPTED_OBJECTS,
94                         self::DB_COLUMN_NODE_LIST
95                 );
96
97                 // ... return it
98                 return $elements;
99         }
100
101         /**
102          * Prepares a search instance for given node data
103          *
104          * @param       $nodeData                       An array with valid node data
105          * @return      $searchInstance         An instance of a SearchCriteria class
106          */
107         private function prepareSearchInstance (array $nodeData) {
108                 // Assert on array elements
109                 assert(isset($nodeData[self::DB_COLUMN_NODE_ID]));
110
111                 // Get instance
112                 $searchInstance = ObjectFactory::createObjectByConfiguredName('search_criteria_class');
113
114                 // Search for node id and limit it to one entry
115                 $searchInstance->addCriteria(self::DB_COLUMN_NODE_ID, $nodeData[self::DB_COLUMN_NODE_ID]);
116                 $searchInstance->setLimit(1);
117
118                 // Return it
119                 return $searchInstance;
120         }
121
122         /**
123          * Getter for result instance for unpublished entries
124          *
125          * @return      $unpublishedEntriesInstance             Result instance
126          */
127         public final function getUnpublishedEntriesInstance () {
128                 return $this->unpublishedEntriesInstance;
129         }
130
131         /**
132          * Prepares a "local" instance of a StoreableCriteria class with all node
133          * data for insert/update queries. This data set contains data from *this*
134          * (local) node.
135          *
136          * @return      $dataSetInstance        An instance of a StoreableCriteria class
137          */
138         private function prepareLocalDataSetInstance () {
139                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DHT-WRAPPER[' . __METHOD__ . ':' . __LINE__ . ']: CALLED!');
140
141                 // Get node/request instances
142                 $nodeInstance = NodeObjectFactory::createNodeInstance();
143                 $requestInstance = ApplicationHelper::getSelfInstance()->getRequestInstance();
144
145                 // Get a dataset instance
146                 $dataSetInstance = ObjectFactory::createObjectByConfiguredName('dataset_criteria_class', array(self::DB_TABLE_NODE_DHT));
147
148                 // Set the primary key
149                 $dataSetInstance->setUniqueKey(self::DB_COLUMN_NODE_ID);
150
151                 // Get Universal Node Locator and "explode" it
152                 $unl = $nodeInstance->getUniversalNodeLocatorArray();
153
154                 // Make sure both is valid
155                 assert(($unl[0] !== 'invalid') && ($unl[1] !== 'invalid') && ($unl[2] !== 'invalid'));
156
157                 // Get an array of all accepted object types
158                 $objectList = $nodeInstance->getListFromAcceptedObjectTypes();
159
160                 // Make sure this is an array
161                 assert(is_array($objectList));
162
163                 // Add public node data
164                 $dataSetInstance->addCriteria(self::DB_COLUMN_NODE_MODE       , $requestInstance->getRequestElement('mode'));
165                 $dataSetInstance->addCriteria(self::DB_COLUMN_EXTERNAL_IP     , $unl[0]);
166                 $dataSetInstance->addCriteria(self::DB_COLUMN_LISTEN_PORT     , $unl[1]);
167                 $dataSetInstance->addCriteria(self::DB_COLUMN_NODE_ID         , $nodeInstance->getNodeId());
168                 $dataSetInstance->addCriteria(self::DB_COLUMN_SESSION_ID      , $nodeInstance->getSessionId());
169                 $dataSetInstance->addCriteria(self::DB_COLUMN_PRIVATE_KEY_HASH, $nodeInstance->getPrivateKeyHash());
170                 $dataSetInstance->addCriteria(self::DB_COLUMN_ACCEPTED_OBJECTS, implode(BaseHubNode::OBJECT_LIST_SEPARATOR, $objectList));
171                 $dataSetInstance->addCriteria(self::DB_COLUMN_ACCEPT_BOOTSTRAP, $this->translateBooleanToYesNo($nodeInstance->isAcceptingDhtBootstrap()));
172
173                 // Return it
174                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DHT-WRAPPER[' . __METHOD__ . ':' . __LINE__ . ']: EXIT!');
175                 return $dataSetInstance;
176         }
177
178         /**
179          * Checks whether the local (*this*) node is registered in the DHT by
180          * checking if the external ip/port is found.
181          *
182          * @return      $isRegistered   Whether *this* node is registered in the DHT
183          */
184         public function isLocalNodeRegistered () {
185                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DHT-WRAPPER[' . __METHOD__ . ':' . __LINE__ . ']: CALLED!');
186
187                 // Get a search criteria instance
188                 $searchInstance = ObjectFactory::createObjectByConfiguredName('search_criteria_class');
189
190                 // Get node instance
191                 $nodeInstance = NodeObjectFactory::createNodeInstance();
192
193                 // Get Universal Node Locator and "explode" it
194                 $unl = $nodeInstance->getUniversalNodeLocatorArray();
195
196                 /*
197                  * Make sure both is not 'invalid' which means that the resolver
198                  * didn't work.
199                  */
200                 assert(($unl[0] !== 'invalid') && ($unl[1] !== 'invalid') && ($unl[2] !== 'invalid'));
201
202                 // Add Universal Node Locator/node id as criteria
203                 $searchInstance->addCriteria(self::DB_COLUMN_EXTERNAL_IP, $unl[0]);
204                 $searchInstance->addCriteria(self::DB_COLUMN_LISTEN_PORT, $unl[1]);
205                 $searchInstance->addCriteria(self::DB_COLUMN_NODE_ID    , $nodeInstance->getNodeId());
206                 $searchInstance->addCriteria(self::DB_COLUMN_SESSION_ID , $nodeInstance->getSessionId());
207                 $searchInstance->setLimit(1);
208
209                 // Query database and get a result instance back
210                 $resultInstance = $this->doSelectByCriteria($searchInstance);
211
212                 // Cache result of if there is an entry, valid() will tell us if an entry is there
213                 $isRegistered = $resultInstance->valid();
214
215                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DHT-WRAPPER[' . __METHOD__ . ':' . __LINE__ . ']: isRegistered=' . intval($isRegistered) . ' - EXIT!');
216
217                 // Return result
218                 return $isRegistered;
219         }
220
221         /**
222          * Registeres the local (*this*) node with its data in the DHT.
223          *
224          * @return      void
225          */
226         public function registerLocalNode () {
227                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DHT-WRAPPER[' . __METHOD__ . ':' . __LINE__ . ']: CALLED!');
228
229                 // Assert to make sure this method is called with no record in DB (the actual backend of the DHT)
230                 assert(!$this->isLocalNodeRegistered());
231
232                 // Get prepared data set instance
233                 $dataSetInstance = $this->prepareLocalDataSetInstance();
234
235                 // "Insert" this dataset instance completely into the database
236                 $this->queryInsertDataSet($dataSetInstance);
237
238                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DHT-WRAPPER[' . __METHOD__ . ':' . __LINE__ . ']: EXIT!');
239         }
240
241         /**
242          * Updates local (*this*) node's data in DHT, this is but not limited to the
243          * session id, ip number (and/or hostname) and port number.
244          *
245          * @return      void
246          */
247         public function updateLocalNode () {
248                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DHT-WRAPPER[' . __METHOD__ . ':' . __LINE__ . ']: CALLED!');
249
250                 // Assert to make sure this method is called with one record in DB (the actual backend of the DHT)
251                 assert($this->isLocalNodeRegistered());
252
253                 // Get node instance
254                 $nodeInstance = NodeObjectFactory::createNodeInstance();
255
256                 // Get search criteria
257                 $searchInstance = ObjectFactory::createObjectByConfiguredName('search_criteria_class');
258
259                 // Search for node id and limit it to one entry
260                 $searchInstance->addCriteria(self::DB_COLUMN_NODE_ID, $nodeInstance->getNodeId());
261                 $searchInstance->setLimit(1);
262
263                 // Get a prepared dataset instance
264                 $dataSetInstance = $this->prepareLocalDataSetInstance();
265
266                 // Set search instance
267                 $dataSetInstance->setSearchInstance($searchInstance);
268
269                 // Update DHT database record
270                 $this->queryUpdateDataSet($dataSetInstance);
271
272                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DHT-WRAPPER[' . __METHOD__ . ':' . __LINE__ . ']: EXIT!');
273         }
274
275         /**
276          * Finds a node locally by given session id
277          *
278          * @param       $sessionId      Session id to lookup
279          * @return      $nodeData       Node data array
280          */
281         public function findNodeLocalBySessionId ($sessionId) {
282                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DHT-WRAPPER[' . __METHOD__ . ':' . __LINE__ . ']: sessionId=' . $sessionId . ' - CALLED!');
283
284                 // Get search criteria
285                 $searchInstance = ObjectFactory::createObjectByConfiguredName('search_criteria_class');
286
287                 // Search for session id and limit it to one entry
288                 $searchInstance->addCriteria(self::DB_COLUMN_SESSION_ID, $sessionId);
289                 $searchInstance->setLimit(1);
290
291                 // Query database and get a result instance back
292                 $resultInstance = $this->doSelectByCriteria($searchInstance);
293
294                 // Return result instance
295                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DHT-WRAPPER[' . __METHOD__ . ':' . __LINE__ . ']: resultInstance->valid()=' . intval($resultInstance->valid()) . ' - EXIT!');
296                 return $resultInstance;
297         }
298
299         /**
300          * Registeres a node by given message data.
301          *
302          * @param       $messageData            An array of all message data
303          * @param       $handlerInstance        An instance of a HandleableDataSet class
304          * @return      void
305          */
306         public function registerNodeByMessageData (array $messageData, HandleableDataSet $handlerInstance) {
307                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DHT-WRAPPER[' . __METHOD__ . ':' . __LINE__ . ']: handlerInstance=' . $handlerInstance->__toString() . ' - CALLED!');
308
309                 // Get a data set instance
310                 $dataSetInstance = ObjectFactory::createObjectByConfiguredName('dataset_criteria_class', array(self::DB_TABLE_NODE_DHT));
311
312                 // Set primary key (session id)
313                 $dataSetInstance->setUniqueKey(self::DB_COLUMN_SESSION_ID);
314
315                 // Add all array elements
316                 $handlerInstance->addArrayToDataSet($dataSetInstance, $messageData);
317
318                 // Remove 'node_list'
319                 $dataSetInstance->unsetCriteria(self::DB_COLUMN_NODE_LIST);
320
321                 // Run the "INSERT" query
322                 $this->queryInsertDataSet($dataSetInstance);
323
324                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DHT-WRAPPER[' . __METHOD__ . ':' . __LINE__ . '] - EXIT!');
325         }
326
327         /**
328          * Updates an existing entry in node list
329          *
330          * @param       $messageData            An array of all message data
331          * @param       $handlerInstance        An instance of a HandleableDataSet class
332          * @param       $searchInstance         An instance of LocalSearchCriteria class
333          * @return      void
334          */
335         public function updateNodeByMessageData (array $messageData, HandleableDataSet $handlerInstance, LocalSearchCriteria $searchInstance) {
336                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DHT-WRAPPER[' . __METHOD__ . ':' . __LINE__ . ']: CALLED!');
337
338                 // Get a data set instance
339                 $dataSetInstance = ObjectFactory::createObjectByConfiguredName('dataset_criteria_class', array(self::DB_TABLE_NODE_DHT));
340
341                 // Add search instance
342                 $dataSetInstance->setSearchInstance($searchInstance);
343
344                 // Set primary key (session id)
345                 $dataSetInstance->setUniqueKey(self::DB_COLUMN_SESSION_ID);
346
347                 // Add all array elements
348                 $handlerInstance->addArrayToDataSet($dataSetInstance, $messageData);
349
350                 // Remove 'node_list'
351                 $dataSetInstance->unsetCriteria(self::DB_COLUMN_NODE_LIST);
352
353                 // Run the "UPDATE" query
354                 $this->queryUpdateDataSet($dataSetInstance);
355
356                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DHT-WRAPPER[' . __METHOD__ . ':' . __LINE__ . ']: EXIT!');
357         }
358
359         /**
360          * Determines whether the given node data is already inserted in the DHT
361          *
362          * @param       $nodeData               An array with valid node data
363          * @return      $isRegistered   Whether the given node data is already inserted
364          */
365         public function isNodeRegistered (array $nodeData) {
366                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DHT-WRAPPER[' . __METHOD__ . ':' . __LINE__ . ']: CALLED!');
367
368                 // Assert on array elements
369                 assert(isset($nodeData[self::DB_COLUMN_NODE_ID]));
370
371                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DHT-WRAPPER[' . __METHOD__ . ':' . __LINE__ . ']: node-id=' . $nodeData[self::DB_COLUMN_NODE_ID]);
372
373                 // Get search criteria
374                 $searchInstance = $this->prepareSearchInstance($nodeData);
375
376                 // Query database and get a result instance back
377                 $resultInstance = $this->doSelectByCriteria(
378                         // Search instance
379                         $searchInstance,
380                         // Only look for these array elements ("keys")
381                         array(
382                                 self::DB_COLUMN_NODE_ID     => TRUE,
383                                 self::DB_COLUMN_EXTERNAL_IP => TRUE,
384                                 self::DB_COLUMN_LISTEN_PORT => TRUE,
385                         )
386                 );
387
388                 // Check if there is an entry
389                 $isRegistered = $resultInstance->valid();
390
391                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DHT-WRAPPER[' . __METHOD__ . ':' . __LINE__ . ']: isRegistered=' . intval($isRegistered) . ' - EXIT!');
392
393                 // Return registration status
394                 return $isRegistered;
395         }
396
397         /**
398          * Registers a node with given data in the DHT. If the node is already
399          * registered this method shall throw an exception.
400          *
401          * @param       $nodeData       An array with valid node data
402          * @return      void
403          * @throws      NodeAlreadyRegisteredException  If the node is already registered
404          */
405         public function registerNode (array $nodeData) {
406                 // Assert on array elements
407                 assert(isset($nodeData[self::DB_COLUMN_NODE_ID]));
408
409                 // Is the node registered?
410                 if ($this->isNodeRegistered($nodeData)) {
411                         // Throw an exception
412                         throw new NodeAlreadyRegisteredException(array($this, $nodeData), self::EXCEPTION_NODE_ALREADY_REGISTERED);
413                 } // END - if
414
415                 // @TODO Unimplemented part
416                 $this->partialStub('nodeData=' . print_r($nodeData, TRUE));
417         }
418
419         /**
420          * Updates a node's entry in the DHT with given data. This will enrich or
421          * just update already exsiting data. If the node is not found this method
422          * shall throw an exception.
423          *
424          * @param       $nodeData       An array with valid node data
425          * @return      void
426          * @throws      NodeDataMissingException        If the node's data is missing
427          */
428         public function updateNode (array $nodeData) {
429                 // Assert on array elements
430                 assert(isset($nodeData[self::DB_COLUMN_NODE_ID]));
431
432                 // Debug message
433                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DHT-WRAPPER[' . __METHOD__ . ':' . __LINE__ . ']: Updating DHT entry for node-id=' . $nodeData[self::DB_COLUMN_NODE_ID] . ' ...');
434
435                 // Is the node registered?
436                 if (!$this->isNodeRegistered($nodeData)) {
437                         // No, then throw an exception
438                         throw new NodeDataMissingException(array($this, $nodeData), self::EXCEPTION_NODE_NOT_REGISTERED);
439                 } // END - if
440
441                 // Get a search instance
442                 $searchInstance = $this->prepareSearchInstance($nodeData);
443
444                 // Get a data set instance
445                 $dataSetInstance = ObjectFactory::createObjectByConfiguredName('dataset_criteria_class', array(self::DB_TABLE_NODE_DHT));
446
447                 // Add search instance
448                 $dataSetInstance->setSearchInstance($searchInstance);
449
450                 // Set primary key (session id)
451                 $dataSetInstance->setUniqueKey(self::DB_COLUMN_SESSION_ID);
452
453                 // Get node instance
454                 $nodeInstance = NodeObjectFactory::createNodeInstance();
455
456                 // Debug message
457                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DHT-WRAPPER[' . __METHOD__ . ':' . __LINE__ . ']: nodeData=' . print_r($nodeData, TRUE));
458
459                 // Add all array elements
460                 $nodeInstance->addArrayToDataSet($dataSetInstance, $nodeData);
461
462                 // Remove 'node_list'
463                 $dataSetInstance->unsetCriteria(self::DB_COLUMN_NODE_LIST);
464
465                 // Run the "UPDATE" query
466                 $this->queryUpdateDataSet($dataSetInstance);
467         }
468
469         /**
470          * Checks whether there are unpublished entries
471          *
472          * @return      $hasUnpublished         Whether there are unpublished entries
473          * @todo        Add minimum/maximum age limitations
474          */
475         public function hasUnpublishedEntries () {
476                 // Get search instance
477                 $searchInstance = ObjectFactory::createObjectByConfiguredName('search_criteria_class');
478
479                 // Add exclusion key which is the publish status
480                 $searchInstance->addExcludeCriteria(NodeDistributedHashTableDatabaseWrapper::DB_COLUMN_PUBLICATION_STATUS, NodeDistributedHashTableDatabaseWrapper::PUBLICATION_STATUS_PENDING);
481
482                 // Remember search instance
483                 $this->setSearchInstance($searchInstance);
484
485                 // Run the query
486                 $this->unpublishedEntriesInstance = $this->doSelectByCriteria($searchInstance);
487
488                 // Check pending entries
489                 $hasUnpublished = $this->unpublishedEntriesInstance->valid();
490
491                 // Return it
492                 return $hasUnpublished;
493         }
494
495         /**
496          * Initializes publication of DHT entries. This does only prepare
497          * publication. The next step is to pickup such prepared entries and publish
498          * them by uploading to other (recently appeared) DHT members.
499          *
500          * @return      void
501          * @todo        Add timestamp to dataset instance
502          */
503         public function initEntryPublication () {
504                 /*
505                  * Make sure that hasUnpublishedEntries() has been called first by
506                  * asserting on the "cached" object instance. This "caching" saves some
507                  * needless queries as this method shall be called immediately after
508                  * hasUnpublishedEntries() returns TRUE.
509                  */
510                 assert($this->unpublishedEntriesInstance instanceof SearchableResult);
511
512                 // Result is still okay?
513                 assert($this->unpublishedEntriesInstance->valid());
514
515                 // Remove 'publication_status'
516                 $this->getSearchInstance()->unsetCriteria(self::DB_COLUMN_PUBLICATION_STATUS);
517
518                 // Make sure all entries are marked as pending, first get a dataset instance.
519                 $dataSetInstance = ObjectFactory::createObjectByConfiguredName('dataset_criteria_class', array(self::DB_TABLE_NODE_DHT));
520
521                 // Add search instance
522                 $dataSetInstance->setSearchInstance($this->getSearchInstance());
523
524                 // Set primary key (node id)
525                 $dataSetInstance->setUniqueKey(self::DB_COLUMN_NODE_ID);
526
527                 // Add criteria (that should be set)
528                 $dataSetInstance->addCriteria(self::DB_COLUMN_PUBLICATION_STATUS, self::PUBLICATION_STATUS_PENDING);
529
530                 // Run the "UPDATE" query
531                 $this->queryUpdateDataSet($dataSetInstance);
532         }
533
534         /**
535          * Removes non-public data from given array.
536          *
537          * @param       $data   An array with possible non-public data that needs to be removed.
538          * @return      $data   A cleaned up array with only public data.
539          */
540         public function removeNonPublicDataFromArray(array $data) {
541                 // Currently call only inner method
542                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DHT-WRAPPER[' . __METHOD__ . ':' . __LINE__ . ']: Calling parent::removeNonPublicDataFromArray(data) ...');
543                 $data = parent::removeNonPublicDataFromArray($data);
544                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DHT-WRAPPER[' . __METHOD__ . ':' . __LINE__ . ']: data[]=' . gettype($data));
545
546                 // Return cleaned data
547                 return $data;
548         }
549
550         /**
551          * Find recipients for given package data and exclude the sender
552          *
553          * @param       $packageData    An array of valid package data
554          * @return      $recipients             An indexed array with DHT recipients
555          */
556         public function getResultFromExcludedSender (array $packageData) {
557                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DHT-WRAPPER[' . __METHOD__ . ':' . __LINE__ . ']: CALLED!');
558
559                 // Assert on required array field
560                 assert(isset($packageData[NetworkPackage::PACKAGE_DATA_SENDER]));
561
562                 // Get max recipients
563                 $maxRecipients = $this->getConfigInstance()->getConfigEntry('max_dht_recipients');
564
565                 // First creata a search instance
566                 $searchInstance = ObjectFactory::createObjectByConfiguredName('search_criteria_class');
567
568                 // Then exclude 'sender' field as the sender is the current (*this*) node
569                 $searchInstance->addExcludeCriteria(NodeDistributedHashTableDatabaseWrapper::DB_COLUMN_SESSION_ID, $packageData[NetworkPackage::PACKAGE_DATA_SENDER]);
570
571                 // Set limit to maximum DHT recipients
572                 $searchInstance->setLimit($maxRecipients);
573
574                 // Get a result instance back from DHT database wrapper.
575                 $resultInstance = $this->doSelectByCriteria($searchInstance);
576
577                 /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DHT-WRAPPER[' . __METHOD__ . ':' . __LINE__ . ']: EXIT!');
578
579                 // Return result instance
580                 return $resultInstance;
581         }
582
583         /**
584          * Find recopients by given key/value pair. First look for the key and if it
585          * matches, compare the value.
586          *
587          * @param       $key                    Key to look for
588          * @param       $value                  Value to compare if key matches
589          * @return      $recipients             An indexed array with DHT recipients
590          */
591         public function getResultFromKeyValue ($key, $value) {
592                 // Get max recipients
593                 $maxRecipients = $this->getConfigInstance()->getConfigEntry('max_dht_recipients');
594
595                 // First creata a search instance
596                 $searchInstance = ObjectFactory::createObjectByConfiguredName('search_criteria_class');
597
598                 // Find the key/value pair
599                 $searchInstance->addCriteria($key, $value);
600
601                 // Get a result instance back from DHT database wrapper.
602                 $resultInstance = $this->doSelectByCriteria($searchInstance);
603
604                 // Return result instance
605                 return $resultInstance;
606         }
607
608         /**
609          * Enable DHT bootstrap request acceptance for local node
610          *
611          * @return      void
612          */
613         public function enableAcceptDhtBootstrap () {
614                 // Debug message
615                 /* DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('DHT-WRAPPER[' . __METHOD__ . ':' . __LINE__ . ']: Enabling DHT bootstrap requests ...');
616
617                 // Is the node already registered?
618                 if ($this->isLocalNodeRegistered()) {
619                         // Just update our record
620                         $this->updateLocalNode();
621                 } else {
622                         // Register it
623                         $this->registerLocalNode();
624                 }
625         }
626 }
627
628 // [EOF]
629 ?>