Completed
Branch 0.4-dev (50fa9b)
by Evgenij
02:41
created

RequestDescriptor::setRunning()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

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