Completed
Branch 0.4-dev (54e67b)
by Evgenij
02:52
created

SocketBag::setSocketOperation()   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 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 2
crap 1
1
<?php
2
/**
3
 * Async sockets
4
 *
5
 * @copyright Copyright (c) 2015-2016, 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\Operation\OperationInterface;
13
use AsyncSockets\RequestExecutor\EventHandlerInterface;
14
use AsyncSockets\RequestExecutor\RequestExecutorInterface;
15
use AsyncSockets\RequestExecutor\SocketBagInterface;
16
use AsyncSockets\Socket\SocketInterface;
17
18
/**
19
 * Class SocketBag
20
 */
21
class SocketBag implements SocketBagInterface
22
{
23
    /**
24
     * RequestExecutorInterface
25
     *
26
     * @var RequestExecutorInterface
27
     */
28
    private $executor;
29
30
    /**
31
     * Target metadata items
32
     *
33
     * @var RequestDescriptor[]
34
     */
35
    private $items;
36
37
    /**
38
     * Default connection timeout
39
     *
40
     * @var double
41
     */
42
    private $connectTimeout;
43
44
    /**
45
     * Default I/O timeout
46
     *
47
     * @var double
48
     */
49
    private $ioTimeout;
50
51
    /**
52
     * SocketBag constructor.
53
     *
54
     * @param RequestExecutorInterface $executor Owner RequestExecutor
55
     * @param double                   $connectTimeout Default connection timeout
56
     * @param double                   $ioTimeout Default I/O timeout
57
     */
58 162
    public function __construct(RequestExecutorInterface $executor, $connectTimeout, $ioTimeout)
59
    {
60 162
        $this->executor       = $executor;
61 162
        $this->items          = [ ];
62 162
        $this->connectTimeout = $connectTimeout;
63 162
        $this->ioTimeout      = $ioTimeout;
64 162
    }
65
66
    /** {@inheritdoc} */
67 1
    public function count()
68
    {
69 1
        return count($this->items);
70
    }
71
72
73
    /** {@inheritdoc} */
74 151
    public function addSocket(
75
        SocketInterface $socket,
76
        OperationInterface $operation,
77
        array $metadata = null,
78
        EventHandlerInterface $eventHandlers = null
79
    ) {
80 151
        $hash = $this->getOperationStorageKey($socket);
81 151
        if (isset($this->items[$hash])) {
82 1
            throw new \LogicException('Can not add socket twice.');
83
        }
84
85 151
        $meta = array_merge(
86
            [
87 151
                RequestExecutorInterface::META_ADDRESS               => null,
88 151
                RequestExecutorInterface::META_USER_CONTEXT          => null,
89 151
                RequestExecutorInterface::META_SOCKET_STREAM_CONTEXT => null,
90 151
                RequestExecutorInterface::META_CONNECTION_TIMEOUT    => $this->connectTimeout,
91 151
                RequestExecutorInterface::META_IO_TIMEOUT            => $this->ioTimeout,
92 151
            ],
93 151
            $metadata ?: [],
94
            [
95 151
                RequestExecutorInterface::META_CONNECTION_START_TIME  => null,
96 151
                RequestExecutorInterface::META_CONNECTION_FINISH_TIME => null,
97 151
                RequestExecutorInterface::META_LAST_IO_START_TIME     => null,
98 151
                RequestExecutorInterface::META_BYTES_SENT             => 0,
99 151
                RequestExecutorInterface::META_BYTES_RECEIVED         => 0,
100 151
                RequestExecutorInterface::META_REQUEST_COMPLETE       => false,
101
            ]
102 151
        );
103
104 151
        $this->items[$hash] = new RequestDescriptor($socket, $operation, $meta, $eventHandlers);
105 151
    }
106
107
    /** {@inheritdoc} */
108 1
    public function getSocketOperation(SocketInterface $socket)
109
    {
110 1
        return $this->requireDescriptor($socket)->getOperation();
111
    }
112
113
    /** {@inheritdoc} */
114 1
    public function setSocketOperation(SocketInterface $socket, OperationInterface $operation)
115
    {
116 1
        $this->requireDescriptor($socket)->setOperation($operation);
117 1
    }
118
119
120
    /** {@inheritdoc} */
121 3
    public function hasSocket(SocketInterface $socket)
122
    {
123 3
        $hash = $this->getOperationStorageKey($socket);
124 3
        return isset($this->items[$hash]);
125
    }
126
127
    /** {@inheritdoc} */
128 3
    public function removeSocket(SocketInterface $socket)
129
    {
130 3
        $key = $this->getOperationStorageKey($socket);
131 3
        if (!isset($this->items[$key])) {
132 1
            return;
133
        }
134
135 2
        $meta = $this->items[$key]->getMetadata();
136 2
        if (!$meta[RequestExecutorInterface::META_REQUEST_COMPLETE] && $this->executor->isExecuting()) {
137 1
            throw new \LogicException('Can not remove unprocessed socket during request processing.');
138
        }
139
140 1
        unset($this->items[$key]);
141 1
    }
142
143
    /** {@inheritdoc} */
144 1
    public function postponeSocket(SocketInterface $socket)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
145
    {
146 1
        $key = $this->getOperationStorageKey($socket);
147 1
        if (!isset($this->items[$key])) {
148 1
            return;
149
        }
150
151
        $this->items[$key]->postpone();
152
    }
153
154
    /** {@inheritdoc} */
155 94
    public function getSocketMetaData(SocketInterface $socket)
156
    {
157 94
        return $this->requireDescriptor($socket)->getMetadata();
158
    }
159
160
    /** {@inheritdoc} */
161 11
    public function setSocketMetaData(SocketInterface $socket, $key, $value = null)
162
    {
163
        $writableKeys = [
164 11
            RequestExecutorInterface::META_ADDRESS               => 1,
165 11
            RequestExecutorInterface::META_USER_CONTEXT          => 1,
166 11
            RequestExecutorInterface::META_CONNECTION_TIMEOUT    => 1,
167 11
            RequestExecutorInterface::META_IO_TIMEOUT            => 1,
168 11
            RequestExecutorInterface::META_SOCKET_STREAM_CONTEXT => 1,
169 11
        ];
170
171 11
        if (!is_array($key)) {
172 11
            $key = [ $key => $value ];
173 11
        }
174
175 11
        $key = array_intersect_key($key, $writableKeys);
176 11
        $this->requireDescriptor($socket)->setMetadata($key);
177 11
    }
178
179
    /**
180
     * Return socket key in internal storage
181
     *
182
     * @param SocketInterface $socket Socket object
183
     *
184
     * @return string
185
     */
186 153
    private function getOperationStorageKey(SocketInterface $socket)
187
    {
188 153
        return spl_object_hash($socket);
189
    }
190
191
    /**
192
     * Require operation descriptor for given socket
193
     *
194
     * @param SocketInterface $socket Socket object
195
     *
196
     * @return RequestDescriptor
197
     * @throws \OutOfBoundsException
198
     */
199 95
    private function requireDescriptor(SocketInterface $socket)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
200
    {
201 95
        $hash = $this->getOperationStorageKey($socket);
202 95
        if (!isset($this->items[$hash])) {
203 1
            throw new \OutOfBoundsException('Trying to perform operation on not added socket.');
204
        }
205
206 94
        return $this->items[$hash];
207
    }
208
209
    /**
210
     * Return metadata items
211
     *
212
     * @return RequestDescriptor[]
213
     */
214 133
    public function getItems()
215
    {
216 133
        return $this->items;
217
    }
218
}
219