Completed
Push — master ( 0ed363...3da2c5 )
by Hu
03:43
created

SystemVMessageQueue::__destruct()   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
c 0
b 0
f 0
dl 0
loc 4
rs 10
ccs 3
cts 3
cp 1
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: Jenner
5
 * Date: 2015/8/12
6
 * Time: 15:15
7
 */
8
9
namespace Jenner\SimpleFork\Queue;
10
11
12
/**
13
 * system v message queue
14
 *
15
 * @package Jenner\SimpleFork\Queue
16
 */
17
class SystemVMessageQueue implements QueueInterface
18
{
19
    /**
20
     * @var int channel
21
     */
22
    protected $msg_type;
23
24
    /**
25
     * @var
26
     */
27
    protected $queue;
28
29
    /**
30
     * @var bool
31
     */
32
    protected $serialize_needed;
33
34
    /**
35
     * @var bool
36
     */
37
    protected $block_send;
38
39
    /**
40
     * @var int
41
     */
42
    protected $option_receive;
43
44
    /**
45
     * @var int
46
     */
47
    protected $maxsize;
48
49
    /**
50
     * @var
51
     */
52
    protected $key_t;
53
54
    /**
55
     * @var string
56
     */
57
    protected $ipc_filename;
58
59
    /**
60
     * @param string $ipc_filename ipc file to make ipc key.
61
     * if it does not exists, it will try to create the file.
62
     * @param int $channel message type
63
     * @param bool $serialize_needed serialize or not
64
     * @param bool $block_send if block when the queue is full
65
     * @param int $option_receive if the value is MSG_IPC_NOWAIT it will not
66
     * going to wait a message coming. if the value is null,
67
     * it will block and wait a message
68
     * @param int $maxsize the max size of queue
69
     */
70 3
    public function __construct(
71
        $ipc_filename = __FILE__,
72
        $channel = 1,
73
        $serialize_needed = true,
74
        $block_send = true,
75
        $option_receive = MSG_IPC_NOWAIT,
76
        $maxsize = 100000
77
    )
78
    {
79 3
        $this->ipc_filename = $ipc_filename;
80 3
        $this->msg_type = $channel;
81 3
        $this->serialize_needed = $serialize_needed;
82 3
        $this->block_send = $block_send;
83 3
        $this->option_receive = $option_receive;
84 3
        $this->maxsize = $maxsize;
85 3
        $this->initQueue($ipc_filename, $channel);
86 3
    }
87
88
    /**
89
     * init queue
90
     *
91
     * @param $ipc_filename
92
     * @param $msg_type
93
     * @throws \Exception
94
     */
95 3
    protected function initQueue($ipc_filename, $msg_type)
96
    {
97 3
        $this->key_t = $this->getIpcKey($ipc_filename, $msg_type);
98 3
        $this->queue = \msg_get_queue($this->key_t);
99 3
        if (!$this->queue) throw new \RuntimeException('msg_get_queue failed');
100 3
    }
101
102
    /**
103
     * @param $ipc_filename
104
     * @param $msg_type
105
     * @throws \Exception
106
     * @return int
107
     */
108 3
    public function getIpcKey($ipc_filename, $msg_type)
109
    {
110 3
        if (!file_exists($ipc_filename)) {
111
            $create_file = touch($ipc_filename);
112
            if ($create_file === false) {
113
                throw new \RuntimeException('ipc_file is not exists and create failed');
114
            }
115
        }
116
117 3
        $key_t = \ftok($ipc_filename, $msg_type);
118 3
        if ($key_t == 0) throw new \RuntimeException('ftok error');
119
120 3
        return $key_t;
121
    }
122
123
    /**
124
     * get message
125
     *
126
     * @param bool $block if block when the queue is empty
127
     * @return bool|string
128
     */
129 3
    public function get($block = false)
130
    {
131 3
        $queue_status = $this->status();
132 3
        if ($queue_status['msg_qnum'] > 0) {
133 3
            $option_receive = $block ? 0 : $this->option_receive;
134 3
            if (\msg_receive(
135 3
                    $this->queue,
136 3
                    $this->msg_type,
137
                    $msgtype_erhalten,
0 ignored issues
show
Bug introduced by
The variable $msgtype_erhalten does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
138 3
                    $this->maxsize,
139
                    $data,
140 3
                    $this->serialize_needed,
141 3
                    $option_receive,
142
                    $err
0 ignored issues
show
Bug introduced by
The variable $err does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
143 3
                ) === true
144 3
            ) {
145 3
                return $data;
0 ignored issues
show
Bug introduced by
The variable $data does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
146
            } else {
147
                throw new \RuntimeException($err);
148
            }
149
        } else {
150
            return false;
151
        }
152
    }
153
154 3
    public function status()
155
    {
156 3
        $queue_status = \msg_stat_queue($this->queue);
157 3
        return $queue_status;
158
    }
159
160
    /*
161
     * return array's keys
162
     * msg_perm.uid	 The uid of the owner of the queue.
163
     * msg_perm.gid	 The gid of the owner of the queue.
164
     * msg_perm.mode	 The file access mode of the queue.
165
     * msg_stime	 The time that the last message was sent to the queue.
166
     * msg_rtime	 The time that the last message was received from the queue.
167
     * msg_ctime	 The time that the queue was last changed.
168
     * msg_qnum	 The number of messages waiting to be read from the queue.
169
     * msg_qbytes	 The maximum number of bytes allowed in one message queue.
170
     *               On Linux, this value may be read and modified via /proc/sys/kernel/msgmnb.
171
     * msg_lspid	 The pid of the process that sent the last message to the queue.
172
     * msg_lrpid	 The pid of the process that received the last message from the queue.
173
     *
174
     * @return array
175
     */
176
177
    /**
178
     * put message
179
     *
180
     * @param $message
181
     * @return bool
182
     * @throws \Exception
183
     */
184
    public function put($message)
185
    {
186
        if (!\msg_send($this->queue, $this->msg_type, $message, $this->serialize_needed, $this->block_send, $err) === true) {
0 ignored issues
show
Bug introduced by
The variable $err does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
187
            throw new \RuntimeException($err);
188
        }
189
190
        return true;
191
    }
192
193
    /**
194
     * get the size of queue
195
     *
196
     * @return mixed
197
     */
198 3
    public function size()
199
    {
200 3
        $status = $this->status();
201
202 3
        return $status['msg_qnum'];
203
    }
204
205
    /**
206
     * allows you to change the values of the msg_perm.uid,
207
     * msg_perm.gid, msg_perm.mode and msg_qbytes fields of the underlying message queue data structure
208
     *
209
     * @param string $key status key
210
     * @param int $value status value
211
     * @return bool
212
     */
213
    public function setStatus($key, $value)
214
    {
215
        $this->checkSetPrivilege($key);
216
        if ($key == 'msg_qbytes')
217
            return $this->setMaxQueueSize($value);
218
        $queue_status[$key] = $value;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$queue_status was never initialized. Although not strictly required by PHP, it is generally a good practice to add $queue_status = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
219
220
        return \msg_set_queue($this->queue, $queue_status);
221
    }
222
223
    /**
224
     * check the privilege of update the queue's status
225
     *
226
     * @param $key
227
     * @throws \Exception
228
     */
229
    private function checkSetPrivilege($key)
230
    {
231
        $privilege_field = array('msg_perm.uid', 'msg_perm.gid', 'msg_perm.mode');
232
        if (!\in_array($key, $privilege_field)) {
233
            $message = 'you can only change msg_perm.uid, msg_perm.gid, ' .
234
                ' msg_perm.mode and msg_qbytes. And msg_qbytes needs root privileges';
235
236
            throw new \RuntimeException($message);
237
        }
238
    }
239
240
    /**
241
     * update the max size of queue
242
     * need root
243
     *
244
     * @param $size
245
     * @throws \Exception
246
     * @return bool
247
     */
248
    public function setMaxQueueSize($size)
249
    {
250
        $user = \get_current_user();
251
        if ($user !== 'root')
252
            throw new \Exception('changing msg_qbytes needs root privileges');
253
254
        return $this->setStatus('msg_qbytes', $size);
255
    }
256
257
    /**
258
     * remove queue
259
     *
260
     * @return bool
261
     */
262
    public function remove()
263
    {
264
        return \msg_remove_queue($this->queue);
265
    }
266
267
    /**
268
     * check if the queue is exists or not
269
     *
270
     * @param $key
271
     * @return bool
272
     */
273
    public function queueExists($key)
274
    {
275
        return \msg_queue_exists($key);
276
    }
277
278
    /**
279
     * init when wakeup
280
     */
281
    public function __wakeup()
282
    {
283
        $this->initQueue($this->ipc_filename, $this->msg_type);
284
    }
285
286
    /**
287
     *
288
     */
289 3
    public function __destruct()
290
    {
291 3
        unset($this);
292
    }
293
}