1
0
Fork 0
mirror of https://github.com/YunoHost-Apps/z-push_ynh.git synced 2024-09-03 18:05:58 +02:00
z-push_ynh/sources/lib/core/topcollector.php
2014-12-17 15:40:48 +00:00

299 lines
No EOL
9.6 KiB
PHP

<?php
/***********************************************
* File : topcollector.php
* Project : Z-Push
* Descr : available everywhere to collect
* data which could be displayed in z-push-top
* the 'persistent' flag should be used with care, so
* there is not too much information
*
* Created : 20.10.2011
*
* Copyright 2007 - 2013 Zarafa Deutschland GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation with the following additional
* term according to sec. 7:
*
* According to sec. 7 of the GNU Affero General Public License, version 3,
* the terms of the AGPL are supplemented with the following terms:
*
* "Zarafa" is a registered trademark of Zarafa B.V.
* "Z-Push" is a registered trademark of Zarafa Deutschland GmbH
* The licensing of the Program under the AGPL does not imply a trademark license.
* Therefore any rights, title and interest in our trademarks remain entirely with us.
*
* However, if you propagate an unmodified version of the Program you are
* allowed to use the term "Z-Push" to indicate that you distribute the Program.
* Furthermore you may use our trademarks where it is necessary to indicate
* the intended purpose of a product or service provided you use it in accordance
* with honest practices in industrial or commercial matters.
* If you want to propagate modified versions of the Program under the name "Z-Push",
* you may only do so if you have a written permission by Zarafa Deutschland GmbH
* (to acquire a permission please contact Zarafa at trademark@zarafa.com).
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Consult LICENSE file for details
************************************************/
class TopCollector extends InterProcessData {
const ENABLEDAT = 2;
const TOPDATA = 3;
protected $preserved;
protected $latest;
/**
* Constructor
*
* @access public
*/
public function TopCollector() {
// initialize super parameters
$this->allocate = 2097152; // 2 MB
$this->type = 20;
parent::__construct();
// initialize params
$this->InitializeParams();
$this->preserved = array();
// static vars come from the parent class
$this->latest = array( "pid" => self::$pid,
"ip" => Request::GetRemoteAddr(),
"user" => self::$user,
"start" => self::$start,
"devtype" => Request::GetDeviceType(),
"devid" => self::$devid,
"devagent" => Request::GetUserAgent(),
"command" => Request::GetCommandCode(),
"ended" => 0,
"push" => false,
);
$this->AnnounceInformation("initializing");
}
/**
* Destructor
* indicates that the process is shutting down
*
* @access public
*/
public function __destruct() {
$this->AnnounceInformation("OK", false, true);
}
/**
* Advices all other processes that they should start/stop
* collecting data. The data saved is a timestamp. It has to be
* reactivated every couple of seconds
*
* @param boolean $stop (opt) default false (do collect)
*
* @access public
* @return boolean indicating if it was set to collect before
*/
public function CollectData($stop = false) {
$wasEnabled = false;
// exclusive block
if ($this->blockMutex()) {
$wasEnabled = ($this->hasData(self::ENABLEDAT)) ? $this->getData(self::ENABLEDAT) : false;
$time = time();
if ($stop === true) $time = 0;
if (! $this->setData($time, self::ENABLEDAT))
return false;
$this->releaseMutex();
}
// end exclusive block
return $wasEnabled;
}
/**
* Announces a string to the TopCollector
*
* @param string $info
* @param boolean $preserve info should be displayed when process terminates
* @param boolean $terminating indicates if the process is terminating
*
* @access public
* @return boolean
*/
public function AnnounceInformation($addinfo, $preserve = false, $terminating = false) {
$this->latest["addinfo"] = $addinfo;
$this->latest["update"] = time();
if ($terminating) {
$this->latest["ended"] = time();
foreach ($this->preserved as $p)
$this->latest["addinfo"] .= " : ".$p;
}
if ($preserve)
$this->preserved[] = $addinfo;
// exclusive block
if ($this->blockMutex()) {
if ($this->isEnabled()) {
$topdata = ($this->hasData(self::TOPDATA)) ? $this->getData(self::TOPDATA): array();
$this->checkArrayStructure($topdata);
// update
$topdata[self::$devid][self::$user][self::$pid] = $this->latest;
$ok = $this->setData($topdata, self::TOPDATA);
}
$this->releaseMutex();
}
// end exclusive block
if ($this->isEnabled() === true && !$ok) {
ZLog::Write(LOGLEVEL_WARN, "TopCollector::AnnounceInformation(): could not write to shared memory. Z-Push top will not display this data.");
return false;
}
return true;
}
/**
* Returns all available top data
*
* @access public
* @return array
*/
public function ReadLatest() {
$topdata = array();
// exclusive block
if ($this->blockMutex()) {
$topdata = ($this->hasData(self::TOPDATA)) ? $this->getData(self::TOPDATA) : array();
$this->releaseMutex();
}
// end exclusive block
return $topdata;
}
/**
* Cleans up data collected so far
*
* @param boolean $all (optional) if set all data independently from the age is removed
*
* @access public
* @return boolean status
*/
public function ClearLatest($all = false) {
// it's ok when doing this every 10 sec
if ($all == false && time() % 10 != 0 )
return true;
$stat = false;
// exclusive block
if ($this->blockMutex()) {
if ($all == true) {
$topdata = array();
}
else {
$topdata = ($this->hasData(self::TOPDATA)) ? $this->getData(self::TOPDATA) : array();
$toClear = array();
foreach ($topdata as $devid=>$users) {
foreach ($users as $user=>$pids) {
foreach ($pids as $pid=>$line) {
// remove everything which terminated for 20 secs or is not updated for more than 120 secs
if (($line["ended"] != 0 && time() - $line["ended"] > 20) ||
time() - $line["update"] > 120) {
$toClear[] = array($devid, $user, $pid);
}
}
}
}
foreach ($toClear as $tc)
unset($topdata[$tc[0]][$tc[1]][$tc[2]]);
}
$stat = $this->setData($topdata, self::TOPDATA);
$this->releaseMutex();
}
// end exclusive block
return $stat;
}
/**
* Sets a different UserAgent for this connection
*
* @param string $agent
*
* @access public
* @return boolean
*/
public function SetUserAgent($agent) {
$this->latest["devagent"] = $agent;
return true;
}
/**
* Marks this process as push connection
*
* @param string $agent
*
* @access public
* @return boolean
*/
public function SetAsPushConnection() {
$this->latest["push"] = true;
return true;
}
/**
* Indicates if top data should be saved or not
* Returns true for 10 seconds after the latest CollectData()
* SHOULD only be called with locked mutex!
*
* @access private
* @return boolean
*/
private function isEnabled() {
$isEnabled = ($this->hasData(self::ENABLEDAT)) ? $this->getData(self::ENABLEDAT) : false;
return ($isEnabled !== false && ($isEnabled +300) > time());
}
/**
* Builds an array structure for the top data
*
* @param array $topdata reference to the topdata array
*
* @access private
* @return
*/
private function checkArrayStructure(&$topdata) {
if (!isset($topdata) || !is_array($topdata))
$topdata = array();
if (!isset($topdata[self::$devid]))
$topdata[self::$devid] = array();
if (!isset($topdata[self::$devid][self::$user]))
$topdata[self::$devid][self::$user] = array();
if (!isset($topdata[self::$devid][self::$user][self::$pid]))
$topdata[self::$devid][self::$user][self::$pid] = array();
}
}
?>