1+ <?php
2+
3+ /**
4+ * ~~summary~~
5+ *
6+ * ~~description~~
7+ *
8+ * PHP version 5
9+ *
10+ * @category Net
11+ * @package PEAR2_Net_RouterOS
12+ * @author Vasil Rangelov <boen.robot@gmail.com>
13+ * @copyright 2011 Vasil Rangelov
14+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
15+ * @version GIT: $Id$
16+ * @link http://pear2.php.net/PEAR2_Net_RouterOS
17+ */
18+ /**
19+ * The namespace declaration.
20+ */
21+ namespace PEAR2 \Net \RouterOS ;
22+
23+ /**
24+ * Uses shared memory to keep responses in.
25+ */
26+ use PEAR2 \Cache \SHM ;
27+
28+ /**
29+ * A RouterOS registry.
30+ *
31+ * Provides functionality for managing the request/response flow. Particularly
32+ * useful in persistent connections.
33+ *
34+ * @category Net
35+ * @package PEAR2_Net_RouterOS
36+ * @author Vasil Rangelov <boen.robot@gmail.com>
37+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
38+ * @link http://pear2.php.net/PEAR2_Net_RouterOS
39+ */
40+ class Registry
41+ {
42+ /**
43+ * @var SHM The storage.
44+ */
45+ protected $ shm ;
46+
47+ /**
48+ * @var int ID of request. Populated at first instance in request.
49+ */
50+ protected static $ requestId = -1 ;
51+
52+ /**
53+ * @var int ID to be given to next instance, after incrementing it.
54+ */
55+ protected static $ instanceIdSeed = -1 ;
56+
57+ /**
58+ * @var int ID of instance within the request.
59+ */
60+ protected $ instanceId ;
61+
62+ /**
63+ * Creates a registry.
64+ *
65+ * @param string $uri An URI to bind the registry to.
66+ */
67+ public function __construct ($ uri )
68+ {
69+ $ this ->shm = new SHM ('PEAR2\Net\RouterOS\Registry ' . $ uri );
70+ if (-1 === self ::$ requestId ) {
71+ self ::$ requestId = $ this ->shm ->add ('requestId ' , 0 )
72+ ? 0 : $ this ->shm ->inc ('requestId ' );
73+ }
74+ $ this ->instanceId = ++self ::$ instanceIdSeed ;
75+ $ this ->shm ->add ('responseBuffer_ ' . $ this ->getOwnershipTag (), array ());
76+ }
77+
78+ /**
79+ * Parses a tag.
80+ *
81+ * Parses a tag to reveal the ownership part of it, and the original tag.
82+ *
83+ * @param string $tag The tag (as received) to parse.
84+ *
85+ * @return array An array with the first member being the ownership tag, and
86+ * the second one being the original tag.
87+ */
88+ public static function parseTag ($ tag )
89+ {
90+ if (null === $ tag ) {
91+ return array (null , null );
92+ }
93+ $ result = explode ('__ ' , $ tag , 2 );
94+ $ result [0 ] .= '__ ' ;
95+ if ('' === $ result [1 ]) {
96+ $ result [1 ] = null ;
97+ }
98+ return $ result ;
99+ }
100+
101+ /**
102+ * Get the ownership tag for this instance.
103+ *
104+ * @return string The ownership tag for this registry instance.
105+ */
106+ public function getOwnershipTag ()
107+ {
108+ return self ::$ requestId . '_ ' . $ this ->instanceId . '__ ' ;
109+ }
110+
111+ /**
112+ * Add a response to the registry.
113+ *
114+ * @param Response $response The response to add. The caller of this
115+ * function is responsible for ensuring that the ownership tag and the
116+ * original tag are separated, so that only the original one remains in the
117+ * response.
118+ * @param string $ownershipTag The ownership tag that the response had.
119+ *
120+ * @return boolean TRUE if the request was added to its buffer, FALSE if
121+ * this instance owns the response, and therefore doesn't need to add the
122+ * response to its buffer.
123+ */
124+ public function add (Response $ response , $ ownershipTag )
125+ {
126+ if ($ this ->getOwnershipTag () === $ ownershipTag ) {
127+ return false ;
128+ }
129+
130+ if (null === $ ownershipTag ) {
131+ foreach ($ this ->shm ->getIterator ('/^(responseBuffer\_)/ ' , true )
132+ as $ targetBufferName ) {
133+ $ this ->_add ($ response , $ targetBufferName );
134+ }
135+ return true ;
136+ }
137+
138+ $ this ->_add ($ response , 'responseBuffer_ ' . $ ownershipTag );
139+ return true ;
140+ }
141+
142+ /**
143+ * Adds a response to a buffer.
144+ *
145+ * @param Response $response The response to add.
146+ * @param type $targetBufferName The name of the buffer to add the
147+ * response to.
148+ *
149+ * @return void
150+ */
151+ private function _add (Response $ response , $ targetBufferName )
152+ {
153+ if ($ this ->shm ->lock ($ targetBufferName )) {
154+ $ targetBuffer = $ this ->shm ->get ($ targetBufferName );
155+ $ targetBuffer [] = $ response ;
156+ $ this ->shm ->set ($ targetBufferName , $ targetBuffer );
157+ $ this ->shm ->unlock ($ targetBufferName );
158+ }
159+ }
160+
161+ /**
162+ * Gets the next response from this instance's buffer.
163+ *
164+ * @return Response|null The next response, or NULL if there isn't one.
165+ */
166+ public function getNextResponse ()
167+ {
168+ $ response = null ;
169+ $ targetBufferName = 'responseBuffer_ ' . $ this ->getOwnershipTag ();
170+ if ($ this ->shm ->exists ($ targetBufferName )
171+ && $ this ->shm ->lock ($ targetBufferName )
172+ ) {
173+ $ targetBuffer = $ this ->shm ->get ($ targetBufferName );
174+ if (!empty ($ targetBuffer )) {
175+ $ response = array_shift ($ targetBuffer );
176+ $ this ->shm ->set ($ targetBufferName , $ targetBuffer );
177+ }
178+ $ this ->shm ->unlock ($ targetBufferName );
179+ }
180+ return $ response ;
181+ }
182+
183+ /**
184+ * Closes the registry.
185+ *
186+ * Closes the registry, meaning that all buffers are cleared.
187+ *
188+ * @return void
189+ */
190+ public function close ()
191+ {
192+ foreach ($ this ->shm ->getIterator ('/^(responseBuffer\_)/ ' , true )
193+ as $ targetBufferName ) {
194+ $ this ->_close ($ targetBufferName );
195+ }
196+ }
197+
198+ /**
199+ * Removes a buffer.
200+ *
201+ * @param string $targetBufferName The buffer to remove.
202+ *
203+ * @return void
204+ */
205+ private function _close ($ targetBufferName )
206+ {
207+ if ($ this ->shm ->lock ($ targetBufferName )) {
208+ $ this ->shm ->delete ($ targetBufferName );
209+ $ this ->shm ->unlock ($ targetBufferName );
210+ }
211+ }
212+
213+ /**
214+ * Removes this instance's buffer.
215+ */
216+ public function __destruct ()
217+ {
218+ $ this ->_close ('responseBuffer_ ' . $ this ->getOwnershipTag ());
219+ }
220+ }
0 commit comments