ThreadWorker::getServerConnectionResource()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 4
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 2
1
<?php
2
3
/**
4
 * \AppserverIo\Server\Workers\ThreadWorker
5
 *
6
 * NOTICE OF LICENSE
7
 *
8
 * This source file is subject to the Open Software License (OSL 3.0)
9
 * that is available through the world-wide-web at this URL:
10
 * http://opensource.org/licenses/osl-3.0.php
11
 *
12
 * PHP version 5
13
 *
14
 * @author    Johann Zelger <[email protected]>
15
 * @copyright 2015 TechDivision GmbH <[email protected]>
16
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
17
 * @link      https://github.com/appserver-io/server
18
 * @link      http://www.appserver.io
19
 */
20
21
namespace AppserverIo\Server\Workers;
22
23
use AppserverIo\Server\Dictionaries\ServerVars;
24
use AppserverIo\Server\Interfaces\ConfigInterface;
25
use AppserverIo\Server\Interfaces\ConnectionHandlerInterface;
26
use AppserverIo\Server\Interfaces\RequestContextInterface;
27
use AppserverIo\Server\Interfaces\ServerContextInterface;
28
use AppserverIo\Server\Interfaces\ServerInterface;
29
use AppserverIo\Server\Interfaces\WorkerInterface;
30
use AppserverIo\Server\Exceptions\ModuleNotFoundException;
31
use AppserverIo\Server\Exceptions\ConnectionHandlerNotFoundException;
32
use AppserverIo\Server\RequestHandlerThread;
33
use AppserverIo\Server\Sockets\SocketInterface;
34
use AppserverIo\Server\Sockets\StreamSocket;
35
36
/**
37
 * Class ThreadWorker
38
 *
39
 * @author    Johann Zelger <[email protected]>
40
 * @copyright 2015 TechDivision GmbH <[email protected]>
41
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
42
 * @link      https://github.com/appserver-io/server
43
 * @link      http://www.appserver.io
44
 */
45
class ThreadWorker extends \Thread implements WorkerInterface
46
{
47
    /**
48
     * Define's the default value for accept min count
49
     *
50
     * @var int
51
     */
52
    const DEFAULT_ACCEPT_MIN = 8;
53
54
    /**
55
     * Define's the default value for accept max count
56
     *
57
     * @var int
58
     */
59
    const DEFAULT_ACCEPT_MAX = 32;
60
61
    /**
62
     * Hold's the serer connection resource
63
     *
64
     * @var resource
65
     */
66
    protected $serverConnectionResource;
67
68
    /**
69
     * Holds the server context object
70
     *
71
     * @var \AppserverIo\Server\Interfaces\ServerContextInterface
72
     */
73
    protected $serverContext;
74
75
    /**
76
     * Hold's an array of connection handlers to use
77
     *
78
     * @var array
79
     */
80
    protected $connectionHandlers;
81
82
    /**
83
     * Defines the minimum count of connections for the worker to accept
84
     *
85
     * @var int
86
     */
87
    protected $acceptMin;
88
89
    /**
90
     * Defines the maximum count of connections for the worker to accept
91
     *
92
     * @var int
93
     */
94
    protected $acceptMax;
95
96
    /**
97
     * Flag if worker should be restarted by server
98
     *
99
     * @var bool
100
     */
101
    public $shouldRestart;
102
103
    /**
104
     * Constructs the worker by setting the server context
105
     *
106
     * @param resource                                              $serverConnectionResource The server's file descriptor resource
107
     * @param \AppserverIo\Server\Interfaces\ServerContextInterface $serverContext            The server's context
108
     * @param array                                                 $connectionHandlers       An array of connection handlers to use
109
     */
110
    public function __construct($serverConnectionResource, ServerContextInterface $serverContext, array $connectionHandlers)
111
    {
112
        $this->serverConnectionResource = $serverConnectionResource;
113
        // connection context init
114
        $this->serverContext = $serverContext;
115
        // connection handler init
116
        $this->connectionHandlers = $connectionHandlers;
117
        // init woker
118
        $this->init();
119
        // autostart worker
120
        $this->start(PTHREADS_INHERIT_NONE | PTHREADS_INHERIT_CONSTANTS | PTHREADS_ALLOW_HEADERS);
0 ignored issues
show
Unused Code introduced by
The call to ThreadWorker::start() has too many arguments starting with PTHREADS_INHERIT_NONE | ... PTHREADS_ALLOW_HEADERS.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
121
    }
122
123
    /**
124
     * Init's the worker before it runs
125
     *
126
     * @return void
127
     */
128
    public function init()
129
    {
130
        // get server config to local ref
131
        $serverConfig = $this->getServerContext()->getServerConfig();
132
        // read min and max accept stuff out of config
133
        $this->acceptMin = $serverConfig->getWorkerAcceptMin();
134
        $this->acceptMax = $serverConfig->getWorkerAcceptMax();
135
    }
136
137
    /**
138
     * Return's an array of connection handlers to use
139
     *
140
     * @return array
141
     */
142
    public function getConnectionHandlers()
143
    {
144
        return $this->connectionHandlers;
145
    }
146
147
    /**
148
     * Return's the server context instance
149
     *
150
     * @return \AppserverIo\Server\Interfaces\ServerContextInterface The server's context
151
     */
152
    public function getServerContext()
153
    {
154
        return $this->serverContext;
155
    }
156
157
    /**
158
     * Return's the server's connection resource ref
159
     *
160
     * @return resource
161
     */
162
    protected function getServerConnectionResource()
163
    {
164
        return $this->serverConnectionResource;
165
    }
166
167
    /**
168
     * Starts the worker doing logic.
169
     *
170
     * @return void
171
     */
172
    public function run()
173
    {
174
        // set current dir to base dir for relative dirs
175
        chdir(SERVER_BASEDIR);
176
        // setup environment for worker
177
        require SERVER_AUTOLOADER;
178
        // prepare worker for upcoming connections in specific context
179
        $this->prepare();
180
        // register shutdown handler
181
        register_shutdown_function(array(&$this, "shutdown"));
182
        // do work
183
        $this->work();
184
    }
185
186
    /**
187
     * Prepares the worker's in it's own context for upcoming work to do on things
188
     * that can not be shared by using the init method in the parent's context.
189
     *
190
     * @return void
191
     */
192
    public function prepare()
193
    {
194
        // get local ref of connection handlers
195
        $connectionHandlers = $this->getConnectionHandlers();
196
        // iterate then and call prepare on the it's modules
197
        foreach ($connectionHandlers as $connectionHandler) {
198
            // iterate all modules of connection handler
199
            foreach ($connectionHandler->getModules() as $name => $moduleInstance) {
200
                // prepare things in worker context
201
                $moduleInstance->prepare();
202
            }
203
        }
204
    }
205
206
    /**
207
     * Implements the workers actual logic
208
     *
209
     * @return void
210
     *
211
     * @throws \AppserverIo\Server\Exceptions\ModuleNotFoundException
212
     * @throws \AppserverIo\Server\Exceptions\ConnectionHandlerNotFoundException
213
     */
214
    public function work()
215
    {
216
        // get server context
217
        $serverContext = $this->getServerContext();
218
        // get connection handlers
219
        $connectionHandlers = $this->getConnectionHandlers();
220
221
        // set should restart initial flag
222
        $this->shouldRestart = false;
223
224
        try {
225
            // get socket type
226
            $socketType = $serverContext->getServerConfig()->getSocketType();
227
228
            /** @var SocketInterface $socketType */
229
            // build connection instance by resource
230
            $serverConnection = $socketType::getInstance($this->serverConnectionResource);
231
232
            // init connection count
233
            $connectionCount = 0;
234
            $connectionLimit = rand($this->getAcceptMin(), $this->getAcceptMax());
235
236
            // while worker not reached connection limit accept connections and process
237
            while (++$connectionCount <= $connectionLimit) {
238
                // accept connections and process working connection by handlers
239
                if (($connection = $serverConnection->accept()) !== false) {
240
                    /**
241
                     * This is for testing async request processing only.
242
                     *
243
                     * It'll delegate the request handling to another thread which will be processed async.
244
                     *
245
                    // call async request handler to handle connection
246
                    $requestHandler = new RequestHandlerThread(
247
                        $connection->getConnectionResource(),
248
                        $connectionHandlers,
249
                        $serverContext,
250
                        $this
251
                    ); */
252
253
                    // iterate all connection handlers to handle connection right
254
                    foreach ($connectionHandlers as $connectionHandler) {
255
                        // if connectionHandler handled connection than break out of foreach
256
                        if ($connectionHandler->handle($connection, $this)) {
257
                            break;
258
                        }
259
                    }
260
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
261
                }
262
            }
263
        } catch (\Exception $e) {
264
            // log error
265
            $serverContext->getLogger()->error($e->__toString());
266
        }
267
        // call internal shutdown
268
        $this->shutdown();
269
    }
270
271
    /**
272
     * Does shutdown logic for worker if something breaks in process.
273
     *
274
     * This shutdown function will be called from specific connection handler if an error occurs, so the connection
275
     * handler can send an response in the correct protocol specifications and a new worker can be started
276
     *
277
     * @return void
278
     */
279 View Code Duplication
    public function shutdown()
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...
280
    {
281
        // check if there was a fatal error caused shutdown
282
        $lastError = error_get_last();
283
        if ($lastError['type'] === E_ERROR || $lastError['type'] === E_USER_ERROR) {
284
            // log error
285
            $this->getServerContext()->getLogger()->error($lastError['message']);
286
        }
287
        $this->shouldRestart = true;
288
    }
289
290
    /**
291
     * Return's if worker should be restarted by server
292
     *
293
     * @return bool
294
     */
295
    public function shouldRestart()
296
    {
297
        return $this->shouldRestart;
298
    }
299
300
    /**
301
     * Return's the max count for the worker to accept
302
     *
303
     * @return int
304
     */
305
    public function getAcceptMax()
306
    {
307
        if ($this->acceptMax) {
308
            return $this->acceptMax;
309
        }
310
        return self::DEFAULT_ACCEPT_MAX;
311
    }
312
313
    /**
314
     * Return's the min count for the worker to accept
315
     *
316
     * @return int
317
     */
318
    public function getAcceptMin()
319
    {
320
        if ($this->acceptMin) {
321
            return $this->acceptMin;
322
        }
323
        return self::DEFAULT_ACCEPT_MIN;
324
    }
325
}
326