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

Revision 7589, 9.5 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      :   topcollector.php
4* Project   :   Z-Push
5* Descr     :   available everywhere to collect
6*               data which could be displayed in z-push-top
7*               the 'persistent' flag should be used with care, so
8*               there is not too much information
9*
10* Created   :   20.10.2011
11*
12* Copyright 2007 - 2012 Zarafa Deutschland GmbH
13*
14* This program is free software: you can redistribute it and/or modify
15* it under the terms of the GNU Affero General Public License, version 3,
16* as published by the Free Software Foundation with the following additional
17* term according to sec. 7:
18*
19* According to sec. 7 of the GNU Affero General Public License, version 3,
20* the terms of the AGPL are supplemented with the following terms:
21*
22* "Zarafa" is a registered trademark of Zarafa B.V.
23* "Z-Push" is a registered trademark of Zarafa Deutschland GmbH
24* The licensing of the Program under the AGPL does not imply a trademark license.
25* Therefore any rights, title and interest in our trademarks remain entirely with us.
26*
27* However, if you propagate an unmodified version of the Program you are
28* allowed to use the term "Z-Push" to indicate that you distribute the Program.
29* Furthermore you may use our trademarks where it is necessary to indicate
30* the intended purpose of a product or service provided you use it in accordance
31* with honest practices in industrial or commercial matters.
32* If you want to propagate modified versions of the Program under the name "Z-Push",
33* you may only do so if you have a written permission by Zarafa Deutschland GmbH
34* (to acquire a permission please contact Zarafa at trademark@zarafa.com).
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU Affero General Public License for more details.
40*
41* You should have received a copy of the GNU Affero General Public License
42* along with this program.  If not, see <http://www.gnu.org/licenses/>.
43*
44* Consult LICENSE file for details
45************************************************/
46
47class TopCollector extends InterProcessData {
48    const ENABLEDAT = 2;
49    const TOPDATA = 3;
50
51    protected $preserved;
52    protected $latest;
53
54    /**
55     * Constructor
56     *
57     * @access public
58     */
59    public function TopCollector() {
60        // initialize super parameters
61        $this->allocate = 2097152; // 2 MB
62        $this->type = 20;
63        parent::__construct();
64
65        // initialize params
66        $this->InitializeParams();
67
68        $this->preserved = array();
69        // static vars come from the parent class
70        $this->latest = array(  "pid"       => self::$pid,
71                                "ip"        => Request::GetRemoteAddr(),
72                                "user"      => self::$user,
73                                "start"     => self::$start,
74                                "devtype"   => Request::GetDeviceType(),
75                                "devid"     => self::$devid,
76                                "devagent"  => Request::GetUserAgent(),
77                                "command"   => Request::GetCommandCode(),
78                                "ended"     => 0,
79                                "push"      => false,
80                        );
81
82        $this->AnnounceInformation("initializing");
83    }
84
85    /**
86     * Destructor
87     * indicates that the process is shutting down
88     *
89     * @access public
90     */
91    public function __destruct() {
92        $this->AnnounceInformation("OK", false, true);
93    }
94
95    /**
96     * Advices all other processes that they should start/stop
97     * collecting data. The data saved is a timestamp. It has to be
98     * reactivated every couple of seconds
99     *
100     * @param boolean   $stop       (opt) default false (do collect)
101     *
102     * @access public
103     * @return boolean  indicating if it was set to collect before
104     */
105    public function CollectData($stop = false) {
106        $wasEnabled = false;
107
108        // exclusive block
109        if ($this->blockMutex()) {
110            $wasEnabled = ($this->hasData(self::ENABLEDAT)) ? $this->getData(self::ENABLEDAT) : false;
111
112            $time = time();
113            if ($stop === true) $time = 0;
114
115            if (! $this->setData($time, self::ENABLEDAT))
116                return false;
117            $this->releaseMutex();
118        }
119        // end exclusive block
120
121        return $wasEnabled;
122    }
123
124    /**
125     * Announces a string to the TopCollector
126     *
127     * @param string    $info
128     * @param boolean   $preserve       info should be displayed when process terminates
129     * @param boolean   $terminating    indicates if the process is terminating
130     *
131     * @access public
132     * @return boolean
133     */
134    public function AnnounceInformation($addinfo, $preserve = false, $terminating = false) {
135        $this->latest["addinfo"] = $addinfo;
136        $this->latest["update"] = time();
137
138        if ($terminating) {
139            $this->latest["ended"] = time();
140            foreach ($this->preserved as $p)
141                $this->latest["addinfo"] .= " : ".$p;
142        }
143
144        if ($preserve)
145            $this->preserved[] = $addinfo;
146
147        // exclusive block
148        if ($this->blockMutex()) {
149
150            if ($this->isEnabled()) {
151                $topdata = ($this->hasData(self::TOPDATA)) ? $this->getData(self::TOPDATA): array();
152
153                $this->checkArrayStructure($topdata);
154
155                // update
156                $topdata[self::$devid][self::$user][self::$pid] = $this->latest;
157                $ok = $this->setData($topdata, self::TOPDATA);
158            }
159            $this->releaseMutex();
160        }
161        // end exclusive block
162
163        if ($this->isEnabled() === true && !$ok) {
164            ZLog::Write(LOGLEVEL_WARN, "TopCollector::AnnounceInformation(): could not write to shared memory. Z-Push top will not display this data.");
165            return false;
166        }
167
168        return true;
169    }
170
171    /**
172     * Returns all available top data
173     *
174     * @access public
175     * @return array
176     */
177    public function ReadLatest() {
178        $topdata = array();
179
180        // exclusive block
181        if ($this->blockMutex()) {
182            $topdata = ($this->hasData(self::TOPDATA)) ? $this->getData(self::TOPDATA) : array();
183            $this->releaseMutex();
184        }
185        // end exclusive block
186
187        return $topdata;
188    }
189
190    /**
191     * Cleans up data collected so far
192     *
193     * @param boolean   $all        (optional) if set all data independently from the age is removed
194     *
195     * @access public
196     * @return boolean  status
197     */
198    public function ClearLatest($all = false) {
199        // it's ok when doing this every 10 sec
200        if ($all == false && time() % 10 != 0 )
201            return true;
202
203        $stat = false;
204
205        // exclusive block
206        if ($this->blockMutex()) {
207            if ($all == true) {
208                $topdata = array();
209            }
210            else {
211                $topdata = ($this->hasData(self::TOPDATA)) ? $this->getData(self::TOPDATA) : array();
212
213                $toClear = array();
214                foreach ($topdata as $devid=>$users) {
215                    foreach ($users as $user=>$pids) {
216                        foreach ($pids as $pid=>$line) {
217                            // remove everything which terminated for 20 secs or is not updated for more than 120 secs
218                            if (($line["ended"] != 0 && time() - $line["ended"] > 20) ||
219                                time() - $line["update"] > 120) {
220                                $toClear[] = array($devid, $user, $pid);
221                            }
222                        }
223                    }
224                }
225                foreach ($toClear as $tc)
226                    unset($topdata[$tc[0]][$tc[1]][$tc[2]]);
227            }
228
229            $stat = $this->setData($topdata, self::TOPDATA);
230            $this->releaseMutex();
231        }
232        // end exclusive block
233
234        return $stat;
235    }
236
237    /**
238     * Sets a different UserAgent for this connection
239     *
240     * @param string    $agent
241     *
242     * @access public
243     * @return boolean
244     */
245    public function SetUserAgent($agent) {
246        $this->latest["devagent"] = $agent;
247    }
248
249    /**
250     * Marks this process as push connection
251     *
252     * @param string    $agent
253     *
254     * @access public
255     * @return boolean
256     */
257    public function SetAsPushConnection() {
258        $this->latest["push"] = true;
259    }
260
261    /**
262     * Indicates if top data should be saved or not
263     * Returns true for 10 seconds after the latest CollectData()
264     * SHOULD only be called with locked mutex!
265     *
266     * @access private
267     * @return boolean
268     */
269    private function isEnabled() {
270        $isEnabled = ($this->hasData(self::ENABLEDAT)) ? $this->getData(self::ENABLEDAT) : false;
271        return ($isEnabled !== false && ($isEnabled +300) > time());
272    }
273
274    /**
275     * Builds an array structure for the top data
276     *
277     * @param array $topdata    reference to the topdata array
278     *
279     * @access private
280     * @return
281     */
282    private function checkArrayStructure(&$topdata) {
283        if (!isset($topdata) || !is_array($topdata))
284            $topdata = array();
285
286        if (!isset($topdata[self::$devid]))
287            $topdata[self::$devid] = array();
288
289        if (!isset($topdata[self::$devid][self::$user]))
290            $topdata[self::$devid][self::$user] = array();
291
292        if (!isset($topdata[self::$devid][self::$user][self::$pid]))
293            $topdata[self::$devid][self::$user][self::$pid] = array();
294    }
295}
296
297?>
Note: See TracBrowser for help on using the repository browser.