Completed
Branch 0.4-dev (dcd04a)
by Evgenij
02:34
created

RequestDescriptor   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 331
Duplicated Lines 0 %

Coupling/Cohesion

Components 5
Dependencies 2

Test Coverage

Coverage 98.55%

Importance

Changes 0
Metric Value
wmc 26
lcom 5
cbo 2
dl 0
loc 331
ccs 68
cts 69
cp 0.9855
rs 10
c 0
b 0
f 0

19 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 13 1
A initialize() 0 4 1
A getOperation() 0 4 1
A setOperation() 0 4 1
A isRunning() 0 4 1
A setRunning() 0 4 1
A getSocket() 0 4 1
A getStreamResource() 0 4 1
A getMetadata() 0 4 1
A setMetadata() 0 11 2
A invokeEvent() 0 6 2
A postpone() 0 8 2
A isPostponed() 0 4 1
A hasState() 0 4 1
A setState() 0 4 1
A clearState() 0 4 1
A registerCounter() 0 6 2
A getCounter() 0 4 2
A resetCounter() 0 21 3
1
<?php
2
/**
3
 * Async sockets
4
 *
5
 * @copyright Copyright (c) 2015-2017, Efimov Evgenij <[email protected]>
6
 *
7
 * This source file is subject to the MIT license that is bundled
8
 * with this source code in the file LICENSE.
9
 */
10
namespace AsyncSockets\RequestExecutor\Metadata;
11
12
use AsyncSockets\Event\Event;
13
use AsyncSockets\Operation\OperationInterface;
14
use AsyncSockets\RequestExecutor\EventHandlerInterface;
15
use AsyncSockets\RequestExecutor\RequestExecutorInterface;
16
use AsyncSockets\Socket\PersistentClientSocket;
17
use AsyncSockets\Socket\SocketInterface;
18
use AsyncSockets\Socket\StreamResourceInterface;
19
20
/**
21
 * Class RequestDescriptor
22
 */
23
class RequestDescriptor implements StreamResourceInterface, EventHandlerInterface
24
{
25
    /**
26
     * This descriptor is ready for reading
27
     */
28
    const RDS_READ = 0x0001;
29
30
    /**
31
     * This descriptor is ready for writing
32
     */
33
    const RDS_WRITE = 0x0002;
34
35
    /**
36
     * This descriptor is has OOB data
37
     */
38
    const RDS_OOB = 0x0004;
39
40
    /**
41
     * Minimum transfer rate counter for receiving data
42
     */
43
    const COUNTER_RECV_MIN_RATE = 'recv_speed_rate_counter';
44
45
    /**
46
     * Minimum transfer rate counter for sending data
47
     */
48
    const COUNTER_SEND_MIN_RATE = 'send_speed_rate_counter';
49
50
    /**
51
     * Socket for this operation
52
     *
53
     * @var SocketInterface
54
     */
55
    private $socket;
56
57
    /**
58
     * Key-value pairs with meta information
59
     *
60
     * @var array
61
     */
62
    private $metadata;
63
64
    /**
65
     * Event handler object
66
     *
67
     * @var EventHandlerInterface
68
     */
69
    private $handlers;
70
71
    /**
72
     * Flag whether this socket request is running
73
     *
74
     * @var bool
75
     */
76
    private $isRunning;
77
78
    /**
79
     * Operation to perform on socket
80
     *
81
     * @var OperationInterface
82
     */
83
    private $operation;
84
85
    /**
86
     * Flag if this socket is postponed
87
     *
88
     * @var bool
89
     */
90
    private $isPostponed = false;
91
92
    /**
93
     * Set of state flags: RDS_* consts
94
     *
95
     * @var int
96
     */
97
    private $state = 0;
98
99
    /**
100
     * Array of counters
101
     *
102
     * @var SpeedRateCounter[]
103
     */
104
    private $counters;
105
106
    /**
107
     * RequestDescriptor constructor.
108
     *
109
     * @param SocketInterface       $socket Socket object
110
     * @param OperationInterface    $operation Operation to perform on socket
111
     * @param array                 $metadata Metadata
112
     * @param EventHandlerInterface $handlers Handlers for this socket
113
     */
114 109
    public function __construct(
115
        SocketInterface $socket,
116
        OperationInterface $operation,
117
        array $metadata,
118
        EventHandlerInterface $handlers = null
119
    ) {
120 109
        $this->socket    = $socket;
121 109
        $this->operation = $operation;
122 109
        $this->metadata  = $metadata;
123 109
        $this->handlers  = $handlers;
124 109
        $this->counters  = [];
125 109
        $this->initialize();
126 109
    }
127
128
    /**
129
     * Initialize data before request
130
     *
131
     * @return void
132
     */
133 109
    public function initialize()
134
    {
135 109
        $this->isRunning = false;
136 109
    }
137
138
    /**
139
     * Return Operation
140
     *
141
     * @return OperationInterface
142
     */
143 55
    public function getOperation()
144
    {
145 55
        return $this->operation;
146
    }
147
148
    /**
149
     * Sets Operation
150
     *
151
     * @param OperationInterface $operation New operation
152
     *
153
     * @return void
154
     */
155 26
    public function setOperation(OperationInterface $operation)
156
    {
157 26
        $this->operation = $operation;
158 26
    }
159
160
    /**
161
     * Return flag whether request is running
162
     *
163
     * @return boolean
164
     */
165 70
    public function isRunning()
166
    {
167 70
        return $this->isRunning;
168
    }
169
170
    /**
171
     * Sets running flag
172
     *
173
     * @param boolean $isRunning New value for IsRunning
174
     *
175
     * @return void
176
     */
177 55
    public function setRunning($isRunning)
178
    {
179 55
        $this->isRunning = $isRunning;
180 55
    }
181
182
    /**
183
     * Return Socket
184
     *
185
     * @return SocketInterface
186
     */
187 68
    public function getSocket()
188
    {
189 68
        return $this->socket;
190
    }
191
192
    /** {@inheritdoc} */
193 53
    public function getStreamResource()
194
    {
195 53
        return $this->socket->getStreamResource();
196
    }
197
198
    /**
199
     * Return key-value array with metadata
200
     *
201
     * @return array
202
     */
203 95
    public function getMetadata()
204
    {
205 95
        return $this->metadata;
206
    }
207
208
    /**
209
     * Set metadata for given socket
210
     *
211
     * @param string|array    $key Either string or key-value array of metadata. If string, then value must be
212
     *                             passed in third argument, if array, then third argument will be ignored
213
     * @param mixed           $value Value for key or null, if $key is array
214
     *
215
     * @return void
216
     */
217 92
    public function setMetadata($key, $value = null)
218
    {
219 92
        if (!is_array($key)) {
220 73
            $this->metadata[$key] = $value;
221
        } else {
222 27
            $this->metadata = array_merge(
223 27
                $this->metadata,
224
                $key
225
            );
226
        }
227 92
    }
228
229
    /** {@inheritdoc} */
230 68
    public function invokeEvent(Event $event)
231
    {
232 68
        if ($this->handlers) {
233 11
            $this->handlers->invokeEvent($event);
234
        }
235 66
    }
236
237
    /**
238
     * Completes processing this socket in event loop, but keep this socket connection opened. Applicable
239
     * only to persistent sockets, all other socket types are ignored by this method.
240
     *
241
     * @return void
242
     */
243 6
    public function postpone()
244
    {
245 6
        if (!($this->socket instanceof PersistentClientSocket)) {
246 5
            return;
247
        }
248
249 1
        $this->isPostponed = true;
250 1
    }
251
252
    /**
253
     * Return true, if this socket shouldn't be processed by executor engine
254
     *
255
     * @return bool
256
     */
257 69
    public function isPostponed()
258
    {
259 69
        return $this->isPostponed;
260
    }
261
262
    /**
263
     * Return true if descriptor has given state
264
     *
265
     * @param int $state State to check, set of RDS_* consts
266
     *
267
     * @return bool
268
     */
269 70
    public function hasState($state)
270
    {
271 70
        return (bool) ($this->state & $state);
272
    }
273
274
    /**
275
     * Sets one state into an object
276
     *
277
     * @param int $state State to set, set of RDS_* consts
278
     *
279
     * @return void
280
     */
281 76
    public function setState($state)
282
    {
283 76
        $this->state |= $state;
284 76
    }
285
286
    /**
287
     * Clears given state in object
288
     *
289
     * @param int $state State to clear, set of RDS_* consts
290
     *
291
     * @return void
292
     */
293 70
    public function clearState($state)
294
    {
295 70
        $this->state &= ~$state;
296 70
    }
297
298
    /**
299
     * Registers counter in this descriptor
300
     *
301
     * @param string           $name SpeedRateCounter name for retrieving
302
     * @param SpeedRateCounter $counter A counter object
303
     *
304
     * @return void
305
     */
306 47
    public function registerCounter($name, SpeedRateCounter $counter)
307
    {
308 47
        if (!isset($this->counters[$name])) {
309 47
            $this->counters[$name] = $counter;
310
        }
311 47
    }
312
313
    /**
314
     * Return counter by given name
315
     *
316
     * @param string $name SpeedRateCounter name
317
     *
318
     * @return SpeedRateCounter|null
319
     */
320 47
    public function getCounter($name)
321
    {
322 47
        return isset($this->counters[$name]) ? $this->counters[$name] : null;
323
    }
324
325
    /**
326
     * Resets counter with given name
327
     *
328
     * @param string $name Counter name
329
     *
330
     * @return void
331
     */
332 47
    public function resetCounter($name)
333
    {
334 47
        $counter = $this->getCounter($name);
335 47
        if (!$counter) {
336 46
            return;
337
        }
338
339
        $resetMetadata = [
340 1
            self::COUNTER_RECV_MIN_RATE => [
341
                RequestExecutorInterface::META_RECEIVE_SPEED => 0,
342 1
            ],
343
            self::COUNTER_SEND_MIN_RATE => [
344
                RequestExecutorInterface::META_SEND_SPEED => 0,
345
            ],
346
        ];
347
348 1
        $counter->reset();
349 1
        if (isset($resetMetadata[$name])) {
350 1
            $this->setMetadata($resetMetadata[$name]);
351
        }
352 1
    }
353
}
354