public function nodeEnclose(Node $node, $sortNodes = true, $level = 1) { if (!$this->getLocalNode()) { throw new RuntimeException('localNode not set.'); } $nodeEncloseReturnValue = $node; /*if($level >= 260){ fwrite(STDOUT, str_repeat("\t", $level).'ERROR: level '.$level.' is too deep'."\n"); throw new RuntimeException('enclose level too deep: '.$level); }*/ /*$printLevel = $level; if($printLevel >= 5){ $printLevel = 5; } $printPrefix = str_repeat("\t", $printLevel); */ if ($node->getIdHexStr() != '00000000-0000-4000-8000-000000000000') { $distance = $node->getDistance(); if (!$distance) { $distance = $this->getLocalNode()->distance($node); $node->setDistance($distance); } $maskByte = 0; $maskBit = 7; // Root MaskBit if ($this->getIsUpper() || $this->getIsLower()) { #fwrite(STDOUT, $printPrefix.'no root bucket'."\n"); $maskByte = $this->getMaskByte(); $maskBit = $this->getMaskBit(); } else { #fwrite(STDOUT, $printPrefix.'root bucket'."\n"); $this->setMaskByte($maskByte); $this->setMaskBit($maskBit); } $maskBitValue = 1 << $maskBit; #fwrite(STDOUT, $printPrefix.'level: '.$level."\n"); #fwrite(STDOUT, $printPrefix.'node: '.$node->getIdHexStr()."\n"); #fwrite(STDOUT, $printPrefix.'dist: '.intToBin($distance[$maskByte])."\n"); #fwrite(STDOUT, $printPrefix.'maskByte: '.$maskByte."\n"); #fwrite(STDOUT, $printPrefix.'maskBit: '.$maskBit."\n"); #fwrite(STDOUT, $printPrefix.'maskBitValue: '.intToBin($maskBitValue)."\n"); #fwrite(STDOUT, $printPrefix.'mask: /'.$maskByte.'/ /'.$maskBit.'/ /'.intToBin($maskBitValue).'/'."\n"); /* if($this->childBucketUpper){ #fwrite(STDOUT, $printPrefix.'upper: '.intToBin($this->childBucketUpper->getMaskBit())."\n"); } else{ #fwrite(STDOUT, $printPrefix.'upper: N/A'."\n"); } if($this->childBucketLower){ #fwrite(STDOUT, $printPrefix.'lower: '.intToBin($this->childBucketLower->getMaskBit())."\n"); } else{ #fwrite(STDOUT, $printPrefix.'lower: N/A'."\n"); } */ #timeStop('onode find start'); $onode = $this->nodeFind($node); #timeStop('onode find end'); if (!$onode) { #fwrite(STDOUT, $printPrefix.'old node not found'."\n"); if ($this->getNodesNum() < static::$SIZE_MAX && !$this->getIsFull()) { #fwrite(STDOUT, $printPrefix.'add node'."\n"); $this->nodeAdd($node, $sortNodes); $nodeEncloseReturnValue = $node; if ($this->isFull()) { #fwrite(STDOUT, $printPrefix.'FULL end'."\n"); #timeStop('nodesReEnclose start'); $this->nodesReEnclose($sortNodes, $level + 1); #timeStop('nodesReEnclose end'); } } else { #fwrite(STDOUT, $printPrefix.'FULL new'."\n"); $bucket = null; if ($distance[$maskByte] & $maskBitValue) { #fwrite(STDOUT, $printPrefix.'match: upper'."\n"); $this->setChildBucketUpper($distance[$maskByte]); $bucket = $this->childBucketUpper; } else { #fwrite(STDOUT, $printPrefix.'match: lower'."\n"); $this->setChildBucketLower($distance[$maskByte]); $bucket = $this->childBucketLower; } if ($bucket !== null) { #$msgOut = intToBin($bucket->getMaskBit()).' d='.intToBin($bucket->getDistance()).''; #fwrite(STDOUT, $printPrefix.'child bucket: '.$msgOut."\n"); $bucket->nodeEnclose($node, $sortNodes, $level + 1); } /*else{ #$msgOut = 'enclose: bucket is full: '; #$msgOut .= 'l='.$level.' '; #$msgOut .= 'd='.intToBin($distance[$maskByte]).' '; #$msgOut .= 'm='.intToBin($maskBitValue).' n='.$node->getIdHexStr().''; #fwrite(STDOUT, $printPrefix.$msgOut."\n"); #throw new RuntimeException($msgOut); # NOT_IMPLEMENTED: what happens when a bucket is not found? }*/ } } else { #fwrite(STDOUT, $printPrefix.'update existing node'."\n"); #usleep(1000000); #timeStop('onode update start'); $onode->update($node); #timeStop('onode update end'); $nodeEncloseReturnValue = $onode; } } return $nodeEncloseReturnValue; }
public function testSetDistance() { $distance = array_fill(0, Node::ID_LEN_BYTE, 0); $distance[0] = 1; $distance[1] = 2; $distance[2] = 3; $distance[3] = 4; $node = new Node(); $node->setDistance($distance); $this->assertEquals($distance, $node->getDistance()); }