ShmEntity   A
last analyzed

Complexity

Total Complexity 27

Size/Duplication

Total Lines 177
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
dl 0
loc 177
rs 10
c 0
b 0
f 0
wmc 27
lcom 1
cbo 3

7 Methods

Rating   Name   Duplication   Size   Complexity  
B __construct() 0 19 7
A open() 0 24 5
A getSegments() 0 4 1
A openall() 0 6 2
A write() 0 18 4
B read() 0 26 6
A delete() 0 6 2
1
<?php
2
namespace PHPDaemon\Utils;
3
4
use PHPDaemon\Core\Daemon;
5
6
/**
7
 * ShmEntity
8
 * @package PHPDaemon\Utils
9
 * @author  Vasily Zorin <[email protected]>
10
 */
11
class ShmEntity
12
{
13
    use \PHPDaemon\Traits\ClassWatchdog;
14
    use \PHPDaemon\Traits\StaticObjectWatchdog;
15
16
    /**
17
     * @var string Path
18
     */
19
    protected $path;
20
21
    /**
22
     * @var array Segments
23
     */
24
    protected $segments = [];
25
26
    /**
27
     * @var integer Segment size
28
     */
29
    protected $segsize = 1024;
30
31
    /**
32
     * @var string Name
33
     */
34
    protected $name;
35
36
    /**
37
     * @var integer Key
38
     */
39
    protected $key;
40
41
    /**
42
     * Constructor
43
     * @param string $path Path
44
     * @param integer $segsize Segment size
45
     * @param string $name Name
46
     * @param boolean $create Create
47
     */
48
    public function __construct($path, $segsize, $name, $create = false)
49
    {
50
        $this->path = $path;
51
        $this->segsize = $segsize;
52
        $this->name = $name;
53
        if ($create && !touch($this->path)) {
54
            Daemon::log('Couldn\'t touch IPC file \'' . $this->path . '\'.');
55
            exit(0);
56
        }
57
58
        if (!is_file($this->path) || ($this->key = ftok($this->path, 't')) === false) {
59
            Daemon::log('Couldn\'t ftok() IPC file \'' . $this->path . '\'.');
60
            exit(0);
61
        }
62
        if (!$this->open(0, $create) && $create) {
63
            Daemon::log('Couldn\'t open IPC-' . $this->name . '  shared memory segment (key=' . $this->key . ', segsize=' . $this->segsize . ', uid=' . posix_getuid() . ', path = ' . $this->path . ').');
64
            exit(0);
65
        }
66
    }
67
68
    /**
69
     * Opens segment of shared memory
70
     * @param  integer $segno Segment number
71
     * @param  boolean $create Create
72
     * @return integer         Segment number
73
     */
74
    public function open($segno = 0, $create = false)
75
    {
76
        if (isset($this->segments[$segno])) {
77
            return $this->segments[$segno];
78
        }
79
        $key = $this->key + $segno;
80
        if (!$create) {
81
            $shm = @shmop_open($key, 'w', 0, 0);
82
        } else {
83
            $shm = @shmop_open($key, 'w', 0, 0);
84
85
            if ($shm) {
86
                shmop_delete($shm);
87
                shmop_close($shm);
88
            }
89
90
            $shm = shmop_open($key, 'c', 0755, $this->segsize);
91
        }
92
        if (!$shm) {
93
            return false;
94
        }
95
        $this->segments[$segno] = $shm;
96
        return $shm;
97
    }
98
99
    /**
100
     * Get open segments
101
     * @return array
102
     */
103
    public function getSegments()
104
    {
105
        return $this->segments;
106
    }
107
108
    /**
109
     * Open all segments
110
     * @return void
111
     */
112
    public function openall()
113
    {
114
        do {
115
            $r = $this->open(sizeof($this->segments));
116
        } while ($r);
117
    }
118
119
    /**
120
     * Write to shared memory
121
     * @param  string $data Data
122
     * @param  integer $offset Offset
123
     * @return boolean         Success
124
     */
125
    public function write($data, $offset)
126
    {
127
        $segno = floor($offset / $this->segsize);
128
        if (!isset($this->segments[$segno])) {
129
            if (!$this->open($segno, true)) {
130
                return false;
131
            }
132
        }
133
        $sOffset = $offset % $this->segsize;
134
        $d = $this->segsize - ($sOffset + mb_orig_strlen($data));
135
        if ($d < 0) {
136
            $this->write(mb_orig_substr($data, $d), ($segno + 1) * $this->segsize);
137
            $data = mb_orig_substr($data, 0, $d);
138
        }
139
        //Daemon::log('writing to #'.$offset.' (segno '.$segno.')');
140
        shmop_write($this->segments[$segno], $data, $sOffset);
141
        return true;
142
    }
143
144
    /**
145
     * Read from shared memory
146
     * @param  integer $offset Offset
147
     * @param  integer $length Length
148
     * @return string          Data
149
     */
150
    public function read($offset, $length = 1)
151
    {
152
        $ret = '';
153
        $segno = floor($offset / $this->segsize);
154
        $sOffset = $offset % $this->segsize;
155
        while (true) {
156
            if (!isset($this->segments[$segno])) {
157
                if (!$this->open($segno)) {
158
                    goto ret;
159
                }
160
            }
161
162
            $ret .= shmop_read($this->segments[$segno], $sOffset, min($length - mb_orig_strlen($ret), $this->segsize));
163
164
            if (mb_orig_strlen($ret) >= $length) {
165
                goto ret;
166
            }
167
168
            ++$segno;
169
170
            $sOffset = 0;
171
        }
172
        ret:
173
174
        return $ret === '' ? false : $ret;
175
    }
176
177
    /**
178
     * Deletes all segments
179
     * @return void
180
     */
181
    public function delete()
182
    {
183
        foreach ($this->segments as $shm) {
184
            shmop_delete($shm);
185
        }
186
    }
187
}
188