Completed
Push — master ( c97103...9edfc5 )
by Evgenij
03:08
created

RequestDescriptor::isPostponed()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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