Skip to content

Commit c6262a8

Browse files
committed
Persistent tests now pass;
!done response is now always given to callbacks when canceling.
1 parent 1a0af09 commit c6262a8

File tree

6 files changed

+136
-61
lines changed

6 files changed

+136
-61
lines changed

nbproject/private/private.xml

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,4 @@
22
<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
33
<coverage xmlns="http://www.netbeans.org/ns/code-coverage/1" enabled="true"/>
44
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/1"/>
5-
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/1">
6-
<file>file:/D:/Projects/PEAR2_Net_RouterOS.git/src/PEAR2/Net/RouterOS/SocketException.php</file>
7-
<file>file:/D:/Projects/PEAR2_Net_RouterOS.git/src/PEAR2/Net/RouterOS/Client.php</file>
8-
<file>file:/D:/Projects/PEAR2_Net_RouterOS.git/src/PEAR2/Net/RouterOS/Communicator.php</file>
9-
<file>file:/D:/Projects/PEAR2_Net_RouterOS.git/src/PEAR2/Net/RouterOS/Query.php</file>
10-
<file>file:/D:/Projects/PEAR2_Net_RouterOS.git/src/PEAR2/Net/RouterOS/Request.php</file>
11-
<file>file:/D:/Projects/PEAR2_Net_RouterOS.git/src/PEAR2/Net/RouterOS/Registry.php</file>
12-
<file>file:/D:/Projects/PEAR2_Net_RouterOS.git/src/PEAR2/Net/RouterOS/PersistentRegistry.php</file>
13-
</open-files>
145
</project-private>

src/PEAR2/Net/RouterOS/Client.php

Lines changed: 48 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ public function completeRequest($tag = null)
438438
*/
439439
public function extractNewResponses($tag = null)
440440
{
441-
if ('' == $tag) {
441+
if (null === $tag) {
442442
$result = array();
443443
foreach (array_keys($this->responseBuffer) as $tag) {
444444
$result = array_merge(
@@ -529,40 +529,43 @@ public function cancelRequest($tag = null)
529529
$tags = array_merge(
530530
array_keys($this->responseBuffer), array_keys($this->callbacks)
531531
);
532+
$this->registry->setTaglessMode(true);
532533
foreach ($tags as $t) {
533-
$this->cancelRequest($t);
534+
$cancelRequest->setArgument(
535+
'tag', $this->registry->getOwnershipTag() . $t
536+
);
537+
$this->sendSync($cancelRequest);
534538
}
535-
return $this;
536-
}
537-
538-
if ($hasTag) {
539-
if ($this->isRequestActive($tag)) {
540-
if ($hasReg) {
541-
$cancelRequest->setArgument(
542-
'tag', $this->registry->getOwnershipTag() . $tag
543-
);
539+
$this->registry->setTaglessMode(false);
540+
} else {
541+
if ($hasTag) {
542+
if ($this->isRequestActive($tag)) {
543+
if ($hasReg) {
544+
$this->registry->setTaglessMode(true);
545+
$cancelRequest->setArgument(
546+
'tag', $this->registry->getOwnershipTag() . $tag
547+
);
548+
} else {
549+
$cancelRequest->setArgument('tag', $tag);
550+
}
544551
} else {
545-
$cancelRequest->setArgument('tag', $tag);
552+
throw new DataFlowException(
553+
'No such request. Canceling aborted.', 11200
554+
);
546555
}
547-
} else {
548-
throw new DataFlowException(
549-
'No such request. Canceling aborted.', 11200
550-
);
556+
}
557+
$this->sendSync($cancelRequest);
558+
if ($hasReg) {
559+
$this->registry->setTaglessMode(false);
551560
}
552561
}
553-
554-
$regBackup = $this->registry;
555-
$this->registry = null;
556-
$this->sendSync($cancelRequest);
557-
$this->registry = $regBackup;
558562

559563
if ($hasTag) {
560564
if ($this->isRequestActive($tag, self::FILTER_BUFFER)) {
561-
unset($this->responseBuffer[$tag]);
562-
} elseif ($this->isRequestActive($tag, self::FILTER_CALLBACK)) {
563-
unset($this->callbacks[$tag]);
565+
$this->responseBuffer[$tag] = $this->completeRequest($tag);
566+
} else {
567+
$this->completeRequest($tag);
564568
}
565-
$this->pendingRequestsCount--;
566569
} else {
567570
$this->responseBuffer = array();
568571
$this->callbacks = array();
@@ -615,19 +618,27 @@ public function isStreamingResponses()
615618
*/
616619
public function close()
617620
{
618-
$result = false;
621+
$result = true;
619622
try {
620-
$response = $this->sendSync(new Request('/quit'));
621-
$result = $this->com->close()
622-
&& $response->getType() === Response::TYPE_FATAL;
623+
if (0 !== $this->pendingRequestsCount) {
624+
if (null !== $this->registry) {
625+
$this->registry->setTaglessMode(true);
626+
}
627+
$response = $this->sendSync(new Request('/quit'));
628+
if (null !== $this->registry) {
629+
$this->registry->setTaglessMode(false);
630+
}
631+
$result = $response->getType() === Response::TYPE_FATAL;
632+
}
633+
$result = $result && $this->com->close();
623634
} catch (SocketException $e) {
624635
$result = $e->getCode() === 205;
625636
}
626637
$this->callbacks = array();
627638
$this->pendingRequestsCount = 0;
628-
if (null !== $this->registry) {
629-
$this->registry->close();
630-
}
639+
//if (null !== $this->registry) {
640+
// $this->registry->close();
641+
//}
631642
return $result;
632643
}
633644

@@ -636,7 +647,11 @@ public function close()
636647
*/
637648
public function __destruct()
638649
{
639-
if (!$this->com->getTransmitter()->isPersistent()) {
650+
if ($this->com->getTransmitter()->isPersistent()) {
651+
if (0 !== $this->pendingRequestsCount) {
652+
$this->cancelRequest();
653+
}
654+
} else {
640655
$this->close();
641656
}
642657
}

src/PEAR2/Net/RouterOS/Message.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ abstract class Message
4141
/**
4242
* @var string An optional tag to associate the message with.
4343
*/
44-
private $_tag = null;
44+
protected $_tag = null;
4545

4646
/**
4747
* A shorthand gateway.

src/PEAR2/Net/RouterOS/Registry.php

Lines changed: 68 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,49 @@ public static function parseTag($tag)
9898
return $result;
9999
}
100100

101+
/**
102+
* Checks if any instance is in tagless mode right now.
103+
*
104+
* @return bool TRUE if an instance is in tagless mode, FALSE otherwise.
105+
*/
106+
public function isTaglessModeOwner()
107+
{
108+
$this->shm->lock('taglessModeOwner');
109+
$result = $this->shm->exists('taglessModeOwner')
110+
&& $this->getOwnershipTag() === $this->shm->get('taglessModeOwner');
111+
$this->shm->unlock('taglessModeOwner');
112+
return $result;
113+
}
114+
115+
/**
116+
* Sets the "tagless mode" setting.
117+
*
118+
* While in tagless mode, this instance will claim owhership of any
119+
* responses without a tag. While not in this mode, any requests without a
120+
* tag will be given to all instances.
121+
*
122+
* Regardless of mode, if the type of the response is
123+
* {@link Response::TYPE_FATAL}, it will be given to all instances.
124+
*
125+
* @param bool $taglessMode TRUE to claim tagless ownership, FALSE to
126+
* release such ownership, if taken.
127+
*
128+
* @return bool TRUE on success, FALSE on failure.
129+
*/
130+
public function setTaglessMode($taglessMode)
131+
{
132+
return $taglessMode
133+
? ($this->shm->lock('taglessMode')
134+
&& $this->shm->lock('taglessModeOwner')
135+
&& $this->shm->add('taglessModeOwner', $this->getOwnershipTag())
136+
&& $this->shm->unlock('taglessModeOwner'))
137+
: ($this->isTaglessModeOwner()
138+
&& $this->shm->lock('taglessModeOwner')
139+
&& $this->shm->delete('taglessModeOwner')
140+
&& $this->shm->unlock('taglessModeOwner')
141+
&& $this->shm->unlock('taglessMode'));
142+
}
143+
101144
/**
102145
* Get the ownership tag for this instance.
103146
*
@@ -123,16 +166,28 @@ public function getOwnershipTag()
123166
*/
124167
public function add(Response $response, $ownershipTag)
125168
{
126-
if ($this->getOwnershipTag() === $ownershipTag) {
169+
if ($this->getOwnershipTag() === $ownershipTag
170+
|| ($this->isTaglessModeOwner()
171+
&& $response->getType() !== Response::TYPE_FATAL)
172+
) {
127173
return false;
128174
}
129175

130176
if (null === $ownershipTag) {
131-
foreach ($this->shm->getIterator('/^(responseBuffer\_)/', true)
132-
as $targetBufferName) {
133-
$this->_add($response, $targetBufferName);
177+
$this->shm->lock('taglessModeOwner');
178+
if ($this->shm->exists('taglessModeOwner')
179+
&& $response->getType() !== Response::TYPE_FATAL
180+
) {
181+
$ownershipTag = $this->shm->get('taglessModeOwner');
182+
$this->shm->unlock('taglessModeOwner');
183+
} else {
184+
$this->shm->unlock('taglessModeOwner');
185+
foreach ($this->shm->getIterator('/^(responseBuffer\_)/', true)
186+
as $targetBufferName) {
187+
$this->_add($response, $targetBufferName);
188+
}
189+
return true;
134190
}
135-
return true;
136191
}
137192

138193
$this->_add($response, 'responseBuffer_' . $ownershipTag);
@@ -189,10 +244,14 @@ public function getNextResponse()
189244
*/
190245
public function close()
191246
{
192-
foreach ($this->shm->getIterator('/^(responseBuffer\_)/', true)
193-
as $targetBufferName) {
194-
$this->_close($targetBufferName);
195-
}
247+
self::$requestId = -1;
248+
self::$instanceIdSeed = -1;
249+
$this->shm->clear();
250+
251+
//foreach ($this->shm->getIterator('/^(responseBuffer\_)/', true)
252+
// as $targetBufferName) {
253+
// $this->_close($targetBufferName);
254+
//}
196255
}
197256

198257
/**

src/PEAR2/Net/RouterOS/Request.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,9 @@ public function removeAllArguments()
245245
*/
246246
public function send(Communicator $com, Registry $reg = null)
247247
{
248-
if (null !== $reg) {
248+
if (null !== $reg
249+
&& (null != $this->getTag() || !$reg->isTaglessModeOwner())
250+
) {
249251
$originalTag = $this->getTag();
250252
$this->setTag($reg->getOwnershipTag() . $originalTag);
251253
$bytes = $this->send($com);

tests/ClientFeaturesTest.php

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -334,8 +334,8 @@ function($response, $client) use (&$responseCount) {
334334
"No responses for '" . HOSTNAME . "' in 2 seconds."
335335
);
336336
$this->assertGreaterThanOrEqual(
337+
$finalRepliesCount + 2/* The !trap and !done */,
337338
$responseCount,
338-
$finalRepliesCount + 1/* The !trap */,
339339
"Insufficient callbacks during second loop."
340340
);
341341
}
@@ -370,7 +370,7 @@ function($response, $client) use (&$repliesCount, $limit) {
370370

371371
$this->object->loop();
372372
$this->assertEquals(
373-
$limit + 1/* The !trap */, $repliesCount,
373+
$limit + 2/* The !trap and !done*/, $repliesCount,
374374
"Extra callbacks were executed during second loop."
375375
);
376376
}
@@ -435,12 +435,12 @@ function($response, $client) use (&$repliesCount) {
435435
$repliesCount++;
436436
}
437437
);
438+
sleep(1);
438439

439440

440441
$arpPrint = new Request('/ip/arp/print');
441442
$arpPrint->setTag('arp');
442443
$this->object->sendAsync($arpPrint);
443-
444444
$list = $this->object->completeRequest('arp');
445445

446446

@@ -513,8 +513,12 @@ public function testSendAsyncAndCompleteRequestWithCallback()
513513

514514
$arpPrint = new Request('/ip/arp/print');
515515
$arpPrint->setTag('arp');
516-
$list1 = $this->object->sendSync($arpPrint);
517-
$list2 = array();
516+
$list1 = $list2 = array();
517+
foreach ($this->object->sendSync($arpPrint) as $response) {
518+
$list1[(string) $response->getArgument('.id')] = $response;
519+
}
520+
ksort($list1);
521+
518522
$this->object->sendAsync(
519523
$arpPrint,
520524
function($response, $client) use (&$list2) {
@@ -531,12 +535,13 @@ function($response, $client) use (&$list2) {
531535
'arp', $response->getTag(),
532536
'The callback must only receive responses meant for it.'
533537
);
534-
$list2[] = $response;
538+
$list2[(string) $response->getArgument('.id')] = $response;
535539
}
536540
);
537541

538542
$this->assertEmpty($this->object->completeRequest('arp')->toArray());
539-
$this->assertEquals($list1->toArray(), $list2);
543+
ksort($list2);
544+
$this->assertEquals($list1, $list2);
540545
}
541546

542547
public function testCompleteRequestEmptyQueue()
@@ -623,7 +628,10 @@ public function testClientInvokability()
623628
$obj(new Request('/ip/arp/print', null, 'arp'));
624629
$this->assertEquals(1, $obj->getPendingRequestsCount());
625630
$obj();
626-
$arpResponses2 = $obj('arp');
631+
$this->assertEquals(0, $obj->getPendingRequestsCount());
632+
$arpResponses2 = $obj->extractNewResponses('arp');
633+
//$arpResponses2 = $obj('arp');
634+
$this->assertEquals(0, $obj->getPendingRequestsCount());
627635
$this->assertGreaterThan(0, count($arpResponses2));
628636
$this->assertEquals(count($arpResponses1), count($arpResponses2));
629637
$this->assertInstanceOf(__NAMESPACE__ . '\Response', $arpResponses1(0));

0 commit comments

Comments
 (0)