source: trunk/zpush/lib/core/interprocessdata.php @ 7589

Revision 7589, 9.3 KB checked in by douglas, 11 years ago (diff)

Ticket #3209 - Integrar módulo de sincronização Z-push ao Expresso

Line 
1<?php
2/***********************************************
3* File      :   interprocessdata.php
4* Project   :   Z-Push
5* Descr     :   Class takes care of interprocess
6*               communicaton for different purposes
7*
8* Created   :   20.10.2011
9*
10* Copyright 2007 - 2012 Zarafa Deutschland GmbH
11*
12* This program is free software: you can redistribute it and/or modify
13* it under the terms of the GNU Affero General Public License, version 3,
14* as published by the Free Software Foundation with the following additional
15* term according to sec. 7:
16*
17* According to sec. 7 of the GNU Affero General Public License, version 3,
18* the terms of the AGPL are supplemented with the following terms:
19*
20* "Zarafa" is a registered trademark of Zarafa B.V.
21* "Z-Push" is a registered trademark of Zarafa Deutschland GmbH
22* The licensing of the Program under the AGPL does not imply a trademark license.
23* Therefore any rights, title and interest in our trademarks remain entirely with us.
24*
25* However, if you propagate an unmodified version of the Program you are
26* allowed to use the term "Z-Push" to indicate that you distribute the Program.
27* Furthermore you may use our trademarks where it is necessary to indicate
28* the intended purpose of a product or service provided you use it in accordance
29* with honest practices in industrial or commercial matters.
30* If you want to propagate modified versions of the Program under the name "Z-Push",
31* you may only do so if you have a written permission by Zarafa Deutschland GmbH
32* (to acquire a permission please contact Zarafa at trademark@zarafa.com).
33*
34* This program is distributed in the hope that it will be useful,
35* but WITHOUT ANY WARRANTY; without even the implied warranty of
36* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37* GNU Affero General Public License for more details.
38*
39* You should have received a copy of the GNU Affero General Public License
40* along with this program.  If not, see <http://www.gnu.org/licenses/>.
41*
42* Consult LICENSE file for details
43************************************************/
44
45abstract class InterProcessData {
46    const CLEANUPTIME = 1;
47
48    static protected $devid;
49    static protected $pid;
50    static protected $user;
51    static protected $start;
52    protected $type;
53    protected $allocate;
54    private $mutexid;
55    private $memid;
56
57    /**
58     * Constructor
59     *
60     * @access public
61     */
62    public function InterProcessData() {
63        if (!isset($this->type) || !isset($this->allocate))
64            throw new FatalNotImplementedException(sprintf("Class InterProcessData can not be initialized. Subclass %s did not initialize type and allocable memory.", get_class($this)));
65
66        if ($this->InitSharedMem())
67            ZLog::Write(LOGLEVEL_DEBUG, sprintf("%s(): Initialized mutexid %s and memid %s.", get_class($this), $this->mutexid, $this->memid));
68    }
69
70    /**
71     * Initializes internal parameters
72     *
73     * @access public
74     * @return boolean
75     */
76    public function InitializeParams() {
77        if (!isset(self::$devid)) {
78            self::$devid = Request::GetDeviceID();
79            self::$pid = @getmypid();
80            self::$user = Request::GetAuthUser();
81            self::$start = time();
82        }
83        return true;
84    }
85
86    /**
87     * Allocates shared memory
88     *
89     * @access private
90     * @return boolean
91     */
92    private function InitSharedMem() {
93        // shared mem general "turn off switch"
94        if (defined("USE_SHARED_MEM") && USE_SHARED_MEM === false) {
95            ZLog::Write(LOGLEVEL_INFO, "InterProcessData::InitSharedMem(): the usage of shared memory for Z-Push has been disabled. Check your config for 'USE_SHARED_MEM'.");
96            return false;
97        }
98
99        if (!function_exists('sem_get') || !function_exists('shm_attach') || !function_exists('sem_acquire')|| !function_exists('shm_get_var')) {
100            ZLog::Write(LOGLEVEL_INFO, "InterProcessData::InitSharedMem(): PHP libraries for the use shared memory are not available. Functionalities like z-push-top or loop detection are not available. Check your php packages.");
101            return false;
102        }
103
104        // Create mutex
105        $this->mutexid = @sem_get($this->type, 1);
106        if ($this->mutexid === false) {
107            ZLog::Write(LOGLEVEL_ERROR, "InterProcessData::InitSharedMem(): could not aquire semaphore");
108            return false;
109        }
110
111        // Attach shared memory
112        $this->memid = shm_attach($this->type+10, $this->allocate);
113        if ($this->memid === false) {
114            ZLog::Write(LOGLEVEL_ERROR, "InterProcessData::InitSharedMem(): could not attach shared memory");
115            @sem_remove($this->mutexid);
116            $this->mutexid = false;
117            return false;
118        }
119
120        // TODO mem cleanup has to be implemented
121        //$this->setInitialCleanTime();
122
123        return true;
124    }
125
126    /**
127     * Removes and detaches shared memory
128     *
129     * @access private
130     * @return boolean
131     */
132    private function RemoveSharedMem() {
133        if ((isset($this->mutexid) && $this->mutexid !== false) && (isset($this->memid) && $this->memid !== false)) {
134            @sem_acquire($this->mutexid);
135            $memid = $this->memid;
136            $this->memid = false;
137            @sem_release($this->mutexid);
138
139            @sem_remove($this->mutexid);
140            @shm_remove($memid);
141            @shm_detach($memid);
142
143            $this->mutexid = false;
144
145            return true;
146        }
147        return false;
148    }
149
150    /**
151     * Reinitializes shared memory by removing, detaching and re-allocating it
152     *
153     * @access public
154     * @return boolean
155     */
156    public function ReInitSharedMem() {
157        return ($this->RemoveSharedMem() && $this->InitSharedMem());
158    }
159
160    /**
161     * Cleans up the shared memory block
162     *
163     * @access public
164     * @return boolean
165     */
166    public function Clean() {
167        $stat = false;
168
169        // exclusive block
170        if ($this->blockMutex()) {
171            $cleanuptime = ($this->hasData(1)) ? $this->getData(1) : false;
172
173            // TODO implement Shared Memory cleanup
174
175            $this->releaseMutex();
176        }
177        // end exclusive block
178
179        return $stat;
180    }
181
182    /**
183     * Indicates if the shared memory is active
184     *
185     * @access public
186     * @return boolean
187     */
188    public function IsActive() {
189        return ((isset($this->mutexid) && $this->mutexid !== false) && (isset($this->memid) && $this->memid !== false));
190    }
191
192    /**
193     * Blocks the class mutex
194     * Method blocks until mutex is available!
195     * ATTENTION: make sure that you *always* release a blocked mutex!
196     *
197     * @access protected
198     * @return boolean
199     */
200    protected function blockMutex() {
201        if ((isset($this->mutexid) && $this->mutexid !== false) && (isset($this->memid) && $this->memid !== false))
202            return @sem_acquire($this->mutexid);
203
204        return false;
205    }
206
207    /**
208     * Releases the class mutex
209     * After the release other processes are able to block the mutex themselfs
210     *
211     * @access protected
212     * @return boolean
213     */
214    protected function releaseMutex() {
215        if ((isset($this->mutexid) && $this->mutexid !== false) && (isset($this->memid) && $this->memid !== false))
216            return @sem_release($this->mutexid);
217
218        return false;
219    }
220
221    /**
222     * Indicates if the requested variable is available in shared memory
223     *
224     * @param int   $id     int indicating the variable
225     *
226     * @access protected
227     * @return boolean
228     */
229    protected function hasData($id = 2) {
230        if ((isset($this->mutexid) && $this->mutexid !== false) && (isset($this->memid) && $this->memid !== false)) {
231            if (function_exists("shm_has_var"))
232                return @shm_has_var($this->memid, $id);
233            else {
234                $some = $this->getData($id);
235                return isset($some);
236            }
237        }
238        return false;
239    }
240
241    /**
242     * Returns the requested variable from shared memory
243     *
244     * @param int   $id     int indicating the variable
245     *
246     * @access protected
247     * @return mixed
248     */
249    protected function getData($id = 2) {
250        if ((isset($this->mutexid) && $this->mutexid !== false) && (isset($this->memid) && $this->memid !== false))
251            return @shm_get_var($this->memid, $id);
252
253        return ;
254    }
255
256    /**
257     * Writes the transmitted variable to shared memory
258     * Subclasses may never use an id < 2!
259     *
260     * @param mixed $data   data which should be saved into shared memory
261     * @param int   $id     int indicating the variable (bigger than 2!)
262     *
263     * @access protected
264     * @return boolean
265     */
266    protected function setData($data, $id = 2) {
267        if ((isset($this->mutexid) && $this->mutexid !== false) && (isset($this->memid) && $this->memid !== false))
268            return @shm_put_var($this->memid, $id, $data);
269
270        return false;
271    }
272
273    /**
274     * Sets the time when the shared memory block was created
275     *
276     * @access private
277     * @return boolean
278     */
279    private function setInitialCleanTime() {
280        $stat = false;
281
282        // exclusive block
283        if ($this->blockMutex()) {
284
285            if ($this->hasData(1) == false)
286                $stat = $this->setData(time(), 1);
287
288            $this->releaseMutex();
289        }
290        // end exclusive block
291
292        return $stat;
293    }
294
295}
296
297?>
Note: See TracBrowser for help on using the repository browser.