From: sleepy Date: Tue, 28 Apr 2020 09:45:30 +0000 (+1000) Subject: Добавлены прочие проекты X-Git-Url: http://git.ultra-x.su/?a=commitdiff_plain;h=ea915df80bb85e7e4663971b5a253942253b4e64;p=dev Добавлены прочие проекты --- diff --git a/dedupler/dedupler.php b/dedupler/dedupler.php new file mode 100644 index 0000000..8a43459 --- /dev/null +++ b/dedupler/dedupler.php @@ -0,0 +1,243 @@ +#!/usr/bin/env php +execute($FIELD); + } + } +echo "reading directory tree... $counter_dirs dirs $counter_files files \r"; +} +function help_topic($short = FALSE) +{ + global $argv; + echo 'File deduplicator ver. ', VERSION, PHP_EOL; + echo 'Usage: ', $argv[0],' [-options] directory',PHP_EOL; + echo 'Searches for identical files and allows you to remove duplicates', PHP_EOL ,'by deleting them or creating links instead.', PHP_EOL; + if ($short == TRUE) + { + echo 'Use -h for help.', PHP_EOL, PHP_EOL; + return; + } + $opts[] = '-n'; + $descr[] = 'Action as do nothing (default).'; + $opts[] = '-r'; + $descr[] = 'Report to file in csv format, if file not set send to STDIN.'; + $opts[] = '-d'; + $descr[] = 'Delete duplicates. Conflict with -n -l -s.'; + $opts[] = '-l'; + $descr[] = 'Delete duplicates and create hardlinks. Duplicates must have same uid, gid and permissions, otherwise you should use -i. Conflict with -n -d -s.'; + $opts[] = '-s'; + $descr[] = 'Delete duplicates and create symlinks. Duplicates must have same uid, gid and permissions, otherwise you should use -i. Conflict with -n -d -l.'; + $opts[] = '-i'; + $descr[] = 'Ignore different uid, gid and permissions between duplicates. It will be used from the first file.'; + $opts[] = '-h'; + $descr[] = 'Show this help topic.'; + $opts[] = '-v'; + $descr[] = 'Be verbose while processing.'; + $opts[] = '-V'; + $descr[] = 'Show version.'; + + + echo 'options:', PHP_EOL; + foreach ($opts as $key => $val) + { + preg_match_all('/(.{0,60})(\ |$)/', $descr[$key],$parts); + foreach ($parts[1] as $part) + { + if ($part == '') + { + continue; + } + echo "\t", $val, "\t", $part, PHP_EOL; + $val = ''; + } + } + echo PHP_EOL; +} + +function reporter() +{ + global $opts; + if (!isset($opts['r'])) + { + return; + } + +} +$counter_dirs = 0; +$counter_files = 0; +$tmpfile = '/tmp/dedupler.tmp'; +$optind = null; +$opts = getopt('nrdlsihvV'); +var_dump($opts,$argv); +if($argc > 1) +{ + $dir = array_pop ($argv); +} + +if ($argc == 1) +{ + help_topic(TRUE); + exit(); +} + + +if (isset($opts['V'])) +{ + echo VERSION,PHP_EOL; + exit(); +} + +if (isset($opts['h'])) +{ + help_topic(); + exit(); +} + + +$colopts['n'] = FALSE; +$colopts['d'] = FALSE; +$colopts['l'] = FALSE; +$colopts['s'] = FALSE; + +if (count(array_diff_key ($colopts,$opts)) < 3 ) +{ + echo 'You can not use options -n, -d, -l, -s together in any combinations, because it conflict between themselves.', PHP_EOL; + exit(2); + +} +$_actmode = 0; + +if (isset($opts['d'])) +{ + $_actmode = 1; +} +if (isset($opts['l'])) +{ + $_actmode = 2; +} +if (isset($opts['s'])) +{ + $_actmode = 3; +} + + + + +if (!is_dir($dir)) +{ + echo $dir,' is not a directory!',PHP_EOL; + exit(1); +} +if (substr($dir, -1) == DIRECTORY_SEPARATOR) +{ + $dir = substr($dir,0,-1); +} +$_FSTREE = []; +if (file_exists($tmpfile)) +{ + unlink($tmpfile); +} +$DBH = new PDO("sqlite:".$tmpfile); +$DBH->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); +$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION ); +$DBH->exec ('CREATE TABLE fstree + ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + path text, + size INTEGER + ) + '); + +$STH = $DBH->prepare("INSERT INTO fstree (path, size) values (?, ?)"); +$DBH->beginTransaction(); +$tree = get_dir_tree($dir); +$DBH->commit(); +$STH = $DBH->prepare("select path from fstree where size = ?"); + +echo "\n"; +$stmt_sizes = $DBH->query('select size from fstree GROUP BY `size` HAVING count(*)>1'); +while ($size = $stmt_sizes->fetch()) +{ + $size = implode($size); + echo PHP_EOL, "now analyzing group of files having size $size bytes:", PHP_EOL; + $STH->execute(array($size)); + while ($path = $STH->fetch()) + { + $path = implode($path); + if (!is_link($path)) + { + $stat = stat($path); + if (!isset($first_flag)) + { + $first_path = $path; + unset($first_md5); + $first_inodev = $stat['dev']."+".$stat['ino']; + $first_uidgid = $stat['uid']."+".$stat['gid']; + $first_flag = TRUE; + echo $path, ' is first file',PHP_EOL; + } + else + { + $cmp_inodev = $stat['dev']."+".$stat['ino']; + $cmp_uidgid = $stat['uid']."+".$stat['gid']; + if ($first_inodev == $cmp_inodev) + { + echo $path, ' is hardlink',PHP_EOL; + continue; + } + if (!isset($first_md5)) + { + echo 'calculate md5 for first file',PHP_EOL; + $first_md5 = md5_file($first_path); + } + echo 'calculate md5 for next file',PHP_EOL; + $cmp_md5 = md5_file($path); + if ($first_md5 == $cmp_md5) + { + echo $path, ' is copy',PHP_EOL; + if ($mode == 0) + { + + } + } + else + { + echo $path, ' is unique',PHP_EOL; + + } + } + +// var_dump($path); +// var_dump(stat($path)); + + } + } + unset($first_flag); + +} + diff --git a/dedupler/dscd/dscd.php b/dedupler/dscd/dscd.php new file mode 100644 index 0000000..3ac00fa --- /dev/null +++ b/dedupler/dscd/dscd.php @@ -0,0 +1,8 @@ +unique_flag) + { + !unlink($this->pidfilename); + } + + } + + public function daemonize() + { + $pid = pcntl_fork(); + if ($pid == -1) + { + return FALSE; + } + elseif ($pid > 0) + { + exit; + } + umask(0); + chdir('/'); + if (posix_setsid() == -1) + { + return FALSE; + } + + fclose(STDIN); + fclose(STDOUT); + fclose(STDERR); + $GLOBALS['STDIN'] = fopen('/dev/null', 'r'); + $GLOBALS['STDOUT']= fopen('/dev/null', 'w'); + $GLOBALS['STDERR'] = fopen('/dev/null', 'w'); + + return TRUE; + } + + public function is_unique($pidfilename) + { + $mypid = posix_getpid(); + if (is_readable($pidfilename)) + { + $pid = (int) rtrim(file_get_contents($pidfilename)); + if ($pid == $mypid) + { + return TRUE; + } + if ($pid > 0 && posix_kill($pid, 0)) + { + return FALSE; + } + } + return TRUE; + + } + + public function no_unique($pidfilename) + { + if (!unlink($pidfilename)) + { + return FALSE; + } + } + + public function do_unique($pidfilename) + { + if (!$this->is_unique($pidfilename)) + { + return FALSE; + } + + $mypid = posix_getpid(); + if (!file_put_contents($pidfilename, $mypid.PHP_EOL)) + { + return FALSE; + } + return TRUE; + } +} + +class Children +{ + protected $PIPE; + protected $ROLE; + protected static $CHILDREN; + protected $CHILD; + protected $PARENT; + + + public function __construct() + { + self::set_sig_handlers(); + $this->create_child(); + switch ($this->ROLE) + { + case -1: + return FALSE; + case 0: + return TRUE; + case 1: + $this->ChildBody(); + exit(); + } + + } + + public function __destruct() + { + if ($this->ROLE == 0) + { + posix_kill($this->CHILD, SIGTERM); + } + } + + protected function ChildBody() + { + + } + + static function set_sig_handlers() + { + pcntl_signal(SIGCHLD, [__CLASS__, 'handler_sigchld']); + } + + public function SendUnixSignal($sig) + { + return posix_kill($this->CHILD, $sig); + } + + public function IsAlive() + { + if ($this->ROLE == 1) + { + return TRUE; + } + if (isset(self::$CHILDREN[$this->CHILD])) + { + return TRUE; + } + else + { + return FALSE; + } + } + + public static function handler_sigchld() + { + $pid = pcntl_waitpid(0, $status, WNOHANG); + if($pid > 0) + { + unset(self::$CHILDREN[$pid]); + } + } + + protected function create_child() + { + $sockets = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP); + stream_set_blocking ($sockets[0] , 0); + stream_set_blocking ($sockets[1] , 0); + $pid = pcntl_fork(); + if ($pid == -1) + { + $this->ROLE = -1; + return FALSE; + } + elseif ($pid > 0) + { + // код для родителя + $this->CHILD = $pid; + self::$CHILDREN[$pid] = $pid; + $this->PARENT = FALSE; + $this->ROLE = 0; + $this->PIPE = &$sockets[0]; + unset($sockets); + } + elseif ($pid == 0) + { + // код для ребёнка + $this->CHILD = FALSE; + $this->PARENT = posix_getppid(); + $this->ROLE = 1; + $this->PIPE = &$sockets[1]; + unset($sockets); + } + return TRUE; + } + + public function SendEvent($eventname, $data) + { + if (!is_resource($this->PIPE)) + { + return FALSE; + } + $eventpack = base64_encode($eventname).chr(255).chr(0).chr(255).base64_encode(serialize($data)).chr(0).chr(15).chr(240).chr(255); + + $res = @stream_socket_sendto($this->PIPE, $eventpack); + if ($res == -1) + { + return TRUE; + } + else + { + return FALSE; + } + } + + public function WaitEvent($wait = TRUE) + { + if (!is_resource($this->PIPE)) + { + return FALSE; + } + + $r = [$this->PIPE]; + if ($wait) + { + while (stream_select($r, $w, $x, 0) == 0) + { + usleep(10000); + $r = [$this->PIPE]; + } + } + elseif (stream_select($r, $w, $x, 0) == 0) + { + return NULL; + } + $ipc_msg = ''; + while (substr($ipc_msg , -4) != chr(0).chr(15).chr(240).chr(255)) + { + $rcv_buf = stream_socket_recvfrom($this->PIPE, 1500); + var_dump($rcv_buf); + if ($rcv_buf == '') + { + return NULL; + } + $ipc_msg .= $rcv_buf; + } + $ipc_msg = substr($ipc_msg,0,-4); + $ipc_msg = explode(chr(255).chr(0).chr(255), $ipc_msg); + $retval['eventname'] = base64_decode($ipc_msg[0]); + $retval['data'] = unserialize(base64_decode($ipc_msg[1])); + + return $retval; + + } +} diff --git a/dedupler/dscd/libbox/timer.php b/dedupler/dscd/libbox/timer.php new file mode 100644 index 0000000..0221bcb --- /dev/null +++ b/dedupler/dscd/libbox/timer.php @@ -0,0 +1,97 @@ +id = uniqid(); + $this->time = $time; + $this->UserCall = $callable; + $this->type = $type; + $this->start(); + self::$timers[$this->id] = &$this; + } + + public function __destruct() + { + unset(self::$timers[$this->id]); + } + + private function getId() + { + return $this->id; + } + + public function getTimeLeft() + { + return $this->ltime; + } + + public function setTimeLeft($time) + { + $this->time = $time; + } + + + public function reset() + { + $this->StartTime = microtime(true); + $this->IsStop = FALSE; + } + + public function start() + { + $this->reset(); + $this->IsStop = FALSE; + } + + public function stop() + { + $this->IsStop = TRUE; + } + + public static function poll() + { + foreach (self::$timers as $timer) + { + if ($timer->IsStop == FALSE) + { + $timer->update(); + } + } + } + + private function update() + { + $this->ltime = $this->StartTime - microtime(true) + $this->time; + if ($this->ltime <= 0) + { + $this->ltime = 0; + $this->task(); + if ($this->type == FALSE) + { + $this->stop(); + } + else + { + $this->reset(); + } + } + } + + private function task() + { + call_user_func_array ($this->UserCall, $this->UserCallArg = []); + } +} diff --git a/dvblastmaster/dvbmaster.ini b/dvblastmaster/dvbmaster.ini new file mode 100644 index 0000000..e359723 --- /dev/null +++ b/dvblastmaster/dvbmaster.ini @@ -0,0 +1,52 @@ +[common] +pidfile = /var/run/dvbmaster.pid +dvblast_path = /usr/local/bin/dvblast +dvblastctl_path = /usr/local/bin/dvblastctl +es_timeout = 3000 +epg_passthrough = yes +;provider_name = pizda +;network_id = azaz +;network_name = aaaa +ttl = 64 +use_rtp = yes +pidmap = 100,200,300,400 +run_user = nobody +run_group = video + + +[adapters] +podryad1 = /devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.3 +podryad2 = /devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.2 +adap1 = /devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.1/1-8.1.2 +adap2 = /devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.1/1-8.1.4 + +[enable] +;podryad1 = mux-1 +podryad2 = mux-1 +;adap1 = off +adap2 = mux-1 + +[mux-1] +delivery_system = DVBC_ANNEX_A +frequency = 778000000 +symbol_rate = 6875000 +out[] = 239.1.2.51:2020 1 2701 +out[] = 239.1.2.52:2020 1 2702 +out[] = 239.1.2.53:2020 1 2703 +out[] = 239.1.2.54:2020 1 2704 +out[] = 239.1.2.55:2020 1 2705 +out[] = 239.1.2.56:2020 1 2706 +out[] = 239.1.2.57:2020 1 2707 +out[] = 239.1.2.58:2020 1 2708 +out[] = 239.1.2.59:2020 1 2709 +out[] = 239.1.2.60:2020 1 2710 +out[] = 239.1.2.61:2020 1 2711 +out[] = 239.1.2.62:2020 1 2712 +out[] = 239.1.2.63:2020 1 2713 + + +[mux-2] +delivery_system = DVBT2 +frequency = 610000000 +symbol_rate = 6875000 +plp_id = 0 \ No newline at end of file diff --git a/dvblastmaster/dvbmaster.php b/dvblastmaster/dvbmaster.php new file mode 100644 index 0000000..177e575 --- /dev/null +++ b/dvblastmaster/dvbmaster.php @@ -0,0 +1,897 @@ +#!/usr/bin/env php +CliParseOptions(); + STS::stdout_prefix('dvbmaster: '); + + declare(ticks = 1); + cli_set_process_title('dvbmaster: master process'); + if (!$this->ReadConfig()) + { + echo "ERROR: Reading config file error!\n"; + exit(); + } + if (!isset($this->WorkCommonParams['pidfile'])) + { + echo "ERROR: Pidfile not defined in config file!\n"; + exit(); + } + $_PIDFILENAME = &$this->WorkCommonParams['pidfile']; + + if ($this->RunAsDaemon) + { + Daemon::daemonize(); + } + if (!Daemon::is_unique($_PIDFILENAME)) + { + echo "ERROR: This program already runed!\n"; + exit(); + } + if (!Daemon::do_unique($_PIDFILENAME)) + { + echo "ERROR: Can't make this program instance is unique!\n"; + exit(); + + } + $this->SetUidGid(); + + pcntl_signal(SIGHUP, [$this, 'handler_sighup']); + pcntl_signal(SIGTERM, [$this, 'handler_sigintterm']); + pcntl_signal(SIGINT, [$this, 'handler_sigintterm']); + + + $this->dvblastctl = new dvblastctl(); + $this->dvblastctl->SendEvent('updateconfig', $this->GetConfigForDvblastctl()); + $this->RUN = TRUE; + while ($this->RUN) + { + $this->loop(); + sleep(1); + } + $this->WaitForShutdown(); + + } + + public function __destruct() + { + STS::stdout_unprefix(); + + } + public function handler_sighup() + { + echo "Got SIGHUP, rereading configuration file...\n"; + if (!$this->ReadConfig()) + { + echo "Reading config error!\n"; + } + else + { + $this->dvblastctl->SendEvent('updateconfig', $this->GetConfigForDvblastctl()); + + echo "Reread configuration file is finished!\n"; + } + } + + public function handler_sigintterm() + { + echo "Got SIGINT/SIGTERM, wait for the completion of worker processes...\n"; + $this->RUN = FALSE; + $this->dvblastctl->SendEvent('shutdown', NULL); + } + protected function WaitForShutdown() + { + for ($c = 0; $c < 15; $c++) + { + sleep(1); + if (!$this->dvblastctl->IsAlive()) + { + break; + } + + } + + + + } + + public function loop() + { + echo 'LOOP'.PHP_EOL; + $this->EventReciever(); + } + + protected function EventReciever() + { + while (($DvblastctlMessage = $this->dvblastctl->WaitEvent(FALSE)) !== NULL && $DvblastctlMessage !== FALSE) + { + $this->EventProcessor('dvblastctl',$DvblastctlMessage); + } + } + + protected function EventProcessor($module, $message) + { + if ($module == 'dvblastctl') + { + switch ($message['eventname']) + { + case 'updatestats': + $this->XmlStatsData = array_replace_recursive($this->XmlStatsData, $message['data']); + break; + + } + } + } + + + // сканер физических устройств DVB + // вход: нет + // выход array устройства из udev + public function ScanDvbDevices() + { + + echo 'scan devices...',PHP_EOL; + if (!file_exists('/dev/dvb/')) + { + exit("dvb frontend devices not found\n"); + } + else + { + exec ('find /dev/dvb/ -name "frontend*"', $devnames); + if (count($devnames) == 0) + { + exit("dvb frontend devices not found\n"); + } + } + $DVBDevs = []; + foreach ($devnames as $devname) + { + exec ('udevadm info '.$devname, $devinfo); + foreach ($devinfo as $str) + { + if(preg_match('/^.:\s(.+)=(.*)$/', $str, $d) > 0) + { + $DVBDevs[$devname][$d[1]] = $d[2]; + } + if (isset($DVBDevs[$devname]['DEVPATH'])) + { + $DVBDevs[$devname]['DEVPORT'] = preg_replace ('/\/dvb\/.*/', '', $DVBDevs[$devname]['DEVPATH']); + } + + } + unset($devinfo,$d,$str); + } + return $DVBDevs; + } + + + public function GenerateDevConfig($DVBDevs) + { + $adaptername = 0; + $ini = []; + foreach ($DVBDevs as $name => $data) + { + $ini['adapters']['adaptername-'.$adaptername] = $data['DEVPORT']; + + $adaptername++; + } + echo STS::generate_ini($ini); + } + + public function HelpTopic() + { + echo "This is a help topic \n"; + } + + public function CliParseOptions() + { + $shortoptlist = 'hsdc:'; + $longoptlist = ['help','scandev', 'daemon', 'config-file:']; + $opts = getopt($shortoptlist, $longoptlist, $optindex); + var_dump($opts, $optindex); + + if (isset($opts['h']) || isset($opts['help'])) + { + $this->HelpTopic(); + exit(); + } + + if (isset($opts['s']) || isset($opts['scandev'])) + { + $scandev = $this->ScanDvbDevices(); + echo "\n;Insert this output to your configuration file (.ini) file.\n\n"; + $this->GenerateDevConfig($scandev); + exit(); + } + + if (isset($opts['d']) || isset($opts['daemon'])) + { + $this->RunAsDaemon = TRUE; + } + + if (isset($opts['c'])) + { + $IniFile = $opts['c']; + } + + if (isset($opts['config-file'])) + { + $IniFile = $opts['config-file']; + } + if (is_string($IniFile)) + { + $this->IniFile = $IniFile; + } + + } + + public function ReadConfig() + { + $ini_file = &$this->IniFile; + if (!file_exists($ini_file)) + { + echo "ERROR: Configuration file {$ini_file} not found. \n"; + return FALSE; + } + $this->IniConfig = @parse_ini_file($ini_file, TRUE, INI_SCANNER_TYPED); + if ($this->IniConfig === FALSE) + { + echo "ERROR: Configuration file {$ini_file} contain syntax errors. \n"; + return FALSE; + } + if (!isset($this->IniConfig['adapters'])) + { + return FALSE; + } + + $this->Multiplexes = []; + $this->WorkAdaptersCfg = []; + $this->WorkCommonParams = []; + + $ScannedDevs = $this->ScanDvbDevices(); + foreach ($this->IniConfig['adapters'] as $AdapterName => $AdapterPort) + { + foreach ($ScannedDevs as $Dev) + { + if ($AdapterPort == $Dev['DEVPORT']) + { + $this->WorkAdaptersCfg[$AdapterName]['DEVNAME'] = $Dev['DEVNAME']; + $this->WorkAdaptersCfg[$AdapterName]['ADAPTER_NUM'] = $Dev['DEVPORT']; + $this->WorkAdaptersCfg[$AdapterName]['ADAPTER_NUM'] = $Dev['DVB_ADAPTER_NUM']; + $this->WorkAdaptersCfg[$AdapterName]['FRONTEND_NUM'] = $Dev['DVB_DEVICE_NUM']; + if (isset($this->IniConfig['enable'][$AdapterName])) + { + $this->WorkAdaptersCfg[$AdapterName]['MUX'] = $this->IniConfig['enable'][$AdapterName]; + } + else + { + $this->WorkAdaptersCfg[$AdapterName]['MUX'] = FALSE; + } + } + } + } + $ValidDelSys = ['DVBS', 'DVBS2', 'DVBC_ANNEX_A', 'DVBT','DVBT2', 'ATSC','ISDBT','DVBC_ANNEX_B']; + $ValidModulationC = ['qpsk','qam_16','qam_32','qam_64','qam_128','qam_256']; + $ValidModulationT = ['qam_16','qam_32','qam_64','qam_128','qam_256']; + $ValidModulationS = ['qpsk','psk_8','apsk_16','apsk_32']; + foreach ($this->IniConfig as $SectionName => $Section) + { + if (isset($Section['delivery_system'])) + { + if(array_search($Section['delivery_system'], $ValidDelSys) !== FALSE) + { + $this->Multiplexes[$SectionName] = $Section; + + } + if (isset($this->Multiplexes[$SectionName]['modulation'])) + { + $modname = $this->Multiplexes[$SectionName]['modulation']; + if (($this->Multiplexes[$SectionName]['delivery_system'] == 'DVBS' || $this->Multiplexes[$SectionName]['delivery_system'] == 'DVBS2') && array_search($this->Multiplexes[$SectionName]['modulation'], $ValidModulationS) === FALSE) + { + $this->Multiplexes[$SectionName]['modulation'] = FALSE; + } + if (($this->Multiplexes[$SectionName]['delivery_system'] == 'DVBC_ANNEX_A' || $this->Multiplexes[$SectionName]['delivery_system'] == 'DVBC_ANNEX_B')&& array_search($this->Multiplexes[$SectionName]['modulation'], $ValidModulationC) === FALSE) + { + $this->Multiplexes[$SectionName]['modulation'] = FALSE; + } + if (($this->Multiplexes[$SectionName]['delivery_system'] == 'DVBT' || $this->Multiplexes[$SectionName]['delivery_system'] == 'DVBT2')&& array_search($this->Multiplexes[$SectionName]['modulation'], $ValidModulationT) === FALSE) + { + $this->Multiplexes[$SectionName]['modulation'] = FALSE; + } + if ($this->Multiplexes[$SectionName]['modulation'] === FALSE) + { + echo "WARNING: In MUX '{$SectionName}' modulation '{$modname}' can't be used with system {$this->Multiplexes[$SectionName]['delivery_system']}, using default.\n"; + unset($this->Multiplexes[$SectionName]['modulation']); + } + } + } + } + + foreach ($this->WorkAdaptersCfg as $AdapterName => $AdapterCfg) + { + if ($AdapterCfg['MUX'] === FALSE) + { + continue; + } + if (!isset($this->Multiplexes[$AdapterCfg['MUX']])) + { + echo "ERROR: Multiplex configuration with name {$AdapterCfg['MUX']} for adapter {$AdapterName} not found.\n"; + return FALSE; + } + } + + if (!isset($this->IniConfig['common']['dvblast_path'])) + { + echo "ERROR: Common configuration 'dvblast_path' not found\n"; + return FALSE; + } + if (!isset($this->IniConfig['common']['dvblastctl_path'])) + { + echo "ERROR: Common configuration 'dvblastctl_path' not found\n"; + return FALSE; + } + if (!file_exists($this->IniConfig['common']['dvblast_path'])) + { + echo "ERROR: File in 'dvblast_path' not found\n"; + return FALSE; + } + if (!file_exists($this->IniConfig['common']['dvblastctl_path'])) + { + echo "ERROR: File in 'dvblastctl_path' not found\n"; + return FALSE; + } + + $this->WorkCommonParams = $this->IniConfig['common']; + return TRUE; + + } + + public function GetConfigForDvblastctl() + { + $config = []; + $config['Multiplexes'] = $this->Multiplexes; + $config['WorkAdaptersCfg'] = $this->WorkAdaptersCfg; + $config['WorkCommonParams'] = $this->WorkCommonParams; + return $config; + } + + public function SetUidGid() + { + $FAILFLAG = FALSE; + $_PIDFILENAME = &$this->WorkCommonParams['pidfile']; + if (isset($this->WorkCommonParams['run_group'])) + { + if(!chgrp($_PIDFILENAME, $this->WorkCommonParams['run_group'])) + { + echo 'WARNING: Could not change group for file ',$_PIDFILENAME; + } + echo "Set process group (GID) to {$this->WorkCommonParams['run_group']} ..."; + $userinfo = posix_getgrnam($this->WorkCommonParams['run_group']); + if ($userinfo === FALSE) + { + echo "FAIL\n"; + $FAILFLAG = TRUE; + + } + elseif (!posix_setgid($userinfo['gid'])) + { + echo "FAIL\n"; + $FAILFLAG = TRUE; + } + else + { + echo "DONE\n"; + } + } + if (isset($this->WorkCommonParams['run_user'])) + { + if(!chown($_PIDFILENAME, $this->WorkCommonParams['run_user'])) + { + echo 'WARNING: Could not change user for file ',$_PIDFILENAME; + } + echo "Set process user (UID) to {$this->WorkCommonParams['run_user']} ..."; + $userinfo = posix_getpwnam($this->WorkCommonParams['run_user']); + if ($userinfo === FALSE) + { + echo "FAIL\n"; + $FAILFLAG = TRUE; + + } + elseif (!posix_setuid($userinfo['uid'])) + { + echo "FAIL\n"; + $FAILFLAG = TRUE; + } + else + { + echo "DONE\n"; + } + } + + return !$FAILFLAG; + } + +} +// класс контроллера процессов dvblast +class dvblastctl extends Children +{ + protected $PIPES = []; + protected $dvbprc = []; + protected $runcmd = []; + protected $errbuffer = []; + protected $RestartFlag = []; + protected $config; + protected $wdlock = FALSE; + protected $usdlock = FALSE; + protected $timers = []; + protected $RUN = TRUE; + protected $StatMd5 = []; + protected $QueueUpdateStatData = []; + + + public function handler_sig($SIG) + { + $SIGMNEMO = STS::GetSignalMnemonicByNumber($SIG); + if ($SIGMNEMO === FALSE) + { + $SIGMNEMO = 'unknown'; + } + $this->wdlock = TRUE; + echo "Got '{$SIGMNEMO}' ({$SIG}) signal! Shutting down all dvblast process...\n"; + $this->timers['WatchdogDvblast']->stop(); + $this->timers['UpdateMsgBuffer']->stop(); + $this->timers['GetMsgBuffer']->stop(); + foreach ($this->dvbprc as $procname => $procdesc) + { + $this->StopDvblast($procname); + } + echo "All processes was shuted down.\n"; + $this->RUN = FALSE; + + } + + public function __destruct() + { + parent::__destruct(); + if ($this->ROLE == MPRole_CHILD) + { + STS::stdout_unprefix(); + } + + } + protected function ChildBody($INPARAM) + { + //init + declare(ticks = 1); + cli_set_process_title('dvblastctl: controller process'); + unset($GLOBALS['PRG']); + STS::stdout_unprefix(); + STS::stdout_prefix('dvblastctl: '); + pcntl_signal(SIGTERM, [&$this, 'handler_sig']); + pcntl_signal(SIGINT, [&$this, 'handler_sig']); + pcntl_signal(SIGHUP,SIG_IGN); + echo "remove temporary files..."; + @array_map('unlink', glob("/tmp/*.dvbmcfg")); + echo "DONE\n"; + //get config after starts + echo "wait for config..."; + $event = $this->WaitEvent(TRUE); + if ($event['eventname'] != 'updateconfig') + { + echo "FAIL\nERROR: fetched is not config.\n"; + exit(1); + } + $this->config = $event['data']; + echo "DONE\n"; + + //start dvblast pool + $CmdParams = $this->PrepareDvblastParams($this->config); + + foreach ($CmdParams as $NameInstance => $CmdParam) + { + $this->StartDvblast($NameInstance, $CmdParam); + } + $ListUpdateStatData = ['fe_status' => 60, 'mmi_status' => 100, 'get_pat' => 300, 'get_cat' => 300, 'get_nit' => 300, 'get_sdt' => 300, 'get_pids' => 10]; + $this->timers['WatchdogDvblast'] = new Timer(30, [$this, 'WatchdogDvblast'], NULL, TRUE); + $this->timers['UpdateMsgBuffer'] = new Timer(10, [$this, 'UpdateMsgBuffer'], NULL, TRUE); + $this->timers['UpdateStatData'] = new Timer(10, [$this, 'UpdateStatData'], NULL, TRUE); + $this->timers['GetMsgBuffer'] = new Timer(3600, [$this, 'GetMsgBuffer'], NULL, TRUE); + foreach ($ListUpdateStatData as $infcmd => $time) + { + $this->timers['AddToQueueUpdateStatData'] = new Timer($time, [$this, 'AddToQueueUpdateStatData'], [$infcmd], TRUE); + $this->AddToQueueUpdateStatData($infcmd); + } + while ($this->RUN) + { + sleep(1); + $this->loop(); + } + echo "Shuted down controller process\n"; + STS::stdout_unprefix(); + } + + protected function EventProcessor() + { + while (($event = $this->WaitEvent(FALSE)) !== NULL && $event !== FALSE) + { + switch ($event['eventname']) + { + case 'updateconfig': + $this->ReuseConfig($event['data']); + break; + case 'shutdown': + $this->handler_sig(3); + break; + } + } + } + + protected function ReuseConfig($NewConfig) + { + $result = array_udiff_assoc($NewConfig, $this->config, function ($a, $b) {return (int)!($a === $b);}); + $stoplist = []; + $startlist = []; + if (isset($result['WorkCommonParams'])) + { + $stoplist = array_keys($this->dvbprc); + foreach ($stoplist as $AdapterName) + { + $this->StopDvblast($AdapterName); + } + $this->config = $NewConfig; + $CmdParams = $this->PrepareDvblastParams($this->config); + foreach ($CmdParams as $NameInstance => $CmdParam) + { + $this->StartDvblast($NameInstance, $CmdParam); + } + return; + } + if (isset($result['WorkAdaptersCfg'])) + { + $stoplist = array_keys(array_udiff_assoc($this->config['WorkAdaptersCfg'], $NewConfig['WorkAdaptersCfg'], function ($a, $b) {return (int)!($a === $b);})); + $startlist = array_keys(array_udiff_assoc($NewConfig['WorkAdaptersCfg'], $this->config['WorkAdaptersCfg'], function ($a, $b) {return (int)!($a === $b);})); + } + if (isset($result['Multiplexes'])) + { + $omux = array_keys(array_udiff_assoc($this->config['Multiplexes'], $NewConfig['Multiplexes'], function ($a, $b) {return (int)!($a === $b);})); + $diffmux = array_keys(array_udiff_assoc($NewConfig['Multiplexes'], $this->config['Multiplexes'], function ($a, $b) {return (int)!($a === $b);})); + foreach ($this->config['WorkAdaptersCfg'] as $AdapterName => $AdapterConfig) + { + if (array_search($AdapterConfig['MUX'], $omux) !== FALSE) + { + $stoplist[] = $AdapterName; + } + } + foreach ($NewConfig['WorkAdaptersCfg'] as $AdapterName => $AdapterConfig) + { + if (array_search($AdapterConfig['MUX'], $diffmux) !== FALSE) + { + $startlist[] = $AdapterName; + } + } + + } + + $stoplist = array_unique($stoplist); + $startlist = array_unique($startlist); + foreach ($stoplist as $NameInstance) + { + if (isset($this->dvbprc[$NameInstance])) + { + $this->StopDvblast($NameInstance); + } + } + + $this->config = $NewConfig; + $CmdParams = $this->PrepareDvblastParams($this->config); + foreach ($startlist as $NameInstance) + { + if (isset($CmdParams[$NameInstance])) + { + $this->StartDvblast($NameInstance, $CmdParams[$NameInstance]); + } + } + + } + + public function AddToQueueUpdateStatData($infcmd) + { + $this->QueueUpdateStatData[] = $infcmd; + } + + public function UpdateStatData() + { + if ($this->wdlock || $this->usdlock) + { + return; + } + $this->usdlock = TRUE; + $AdapterNames = array_keys($this->dvbprc); + $this->QueueUpdateStatData = array_unique($this->QueueUpdateStatData); + while (count($this->QueueUpdateStatData) > 0) + { + $infcmd = array_pop($this->QueueUpdateStatData); + foreach ($AdapterNames as $AdapterName) + { + $cmd = $this->config['WorkCommonParams']['dvblastctl_path'].' -r /tmp/dvb-'.$AdapterName.'.sock -t 5 -x xml '; + $xml = shell_exec($cmd.$infcmd.' 2>&1'); + if (!isset($this->StatMd5[$AdapterName][$infcmd])) + { + $this->StatMd5[$AdapterName][$infcmd] = NULL; + } + $XmlMd5 = md5($xml); + if ($this->StatMd5[$AdapterName][$infcmd] == $XmlMd5) + { + continue; + } + $this->StatMd5[$AdapterName][$infcmd] = $XmlMd5; + unset($SendData); + $SendData[$AdapterName][$infcmd] = $xml; + $this->SendEvent('updatestats', $SendData); + } + } + $this->usdlock = FALSE; + } + + protected function StartDvblast($name,$runcmd) + { + $this->wdlock = TRUE; + $descriptorspec = [['pipe', 'r'], ['pipe', 'w'], ['pipe', 'w']]; + echo "starting process '{$name}'..."; + $this->runcmd[$name] = $runcmd; + $this->errbuffer[$name] = []; + $this->dvbprc[$name] = proc_open('exec '.$runcmd, $descriptorspec, $this->PIPES[$name]); + foreach ($this->PIPES[$name] as $procpipe) + { + stream_set_blocking($procpipe,0); + } + $procstatus = proc_get_status($this->dvbprc[$name]); + if ($procstatus['running']) + { + echo "OK\n"; + } + else + { + echo "FAIL\n"; + $this->StopDvblast($name); + } + $this->wdlock = FALSE; + new Timer(3, [$this, 'WatchdogDvblast'], NULL, NULL); + } + protected function StopDvblast($name) + { + $this->wdlock = TRUE; + echo "shutdown process '{$name}'..."; + proc_terminate ($this->dvbprc[$name]); + for ($i=0;$i<10;$i++) + { + $procstatus = proc_get_status($this->dvbprc[$name]); + if (!$procstatus['running']) + { + break; + } + sleep(1); + echo '.'; + } + if ($procstatus['running']) + { + proc_terminate ($this->dvbprc[$name],SIGTERM); + echo "FAIL\nWARNING: The process '{$name}' did not complete normally.\n"; + } + else + { + echo "DONE\n"; + } + stream_get_contents($this->PIPES[$name][1]); + stream_get_contents($this->PIPES[$name][2]); + foreach ($this->PIPES[$name] as $procpipe) + { + fclose($procpipe); + } + proc_close($this->dvbprc[$name]); + unset($this->PIPES[$name], $this->dvbprc[$name], $this->runcmd[$name], $this->errbuffer[$name]); + $this->wdlock = FALSE; + } + + public function UpdateMsgBuffer() + { + if ($this->wdlock) + { + return; + } + foreach ($this->PIPES as $name => $PIPE) + { + do + { + $str = fgets($PIPE[2]); + $ParsedStr = explode(':', $str, 2); + if ($ParsedStr[0] == 'error') + { + if (isset($ParsedStr[1])) + $this->errbuffer[$name][] = ltrim (rtrim ($ParsedStr[1])); + } + + } + while ($str !== FALSE); + } + } + + protected function GetMsgBuffer($name) + { + $messages = $this->errbuffer[$name]; + $this->errbuffer[$name] = []; + return $messages; + } + + public function ResetRestartFlag($name) + { + unset ($this->RestartFlag[$name]); + } + + public function WatchdogDvblast() + { + if ($this->wdlock) + { + return; + } + foreach ($this->dvbprc as $name => $dvbprcres) + { + $procstatus = proc_get_status($dvbprcres); + if (!$procstatus['running']) + { + $this->UpdateMsgBuffer(); + $errbuff = $this->GetMsgBuffer($name); + if (isset($this->RestartFlag[$name])) + { + echo "WARNING: The process '{$name}' unexpectedly crashed repeatedly! Abort respawn procedure.\n"; + $this->StopDvblast($name); + } + else + { + $this->UpdateMsgBuffer(); + $this->GetMsgBuffer($name); + echo "WARNING: The process '{$name}' unexpectedly crashed. Try to respawn...\n"; + $runcmd = $this->runcmd[$name]; + $this->StopDvblast($name); + $this->StartDvblast($name, $runcmd); + $this->RestartFlag[$name] = TRUE; + new Timer(8, [$this, 'ResetRestartFlag'],[$name], NULL); + new Timer(5, [$this, 'WatchdogDvblast'], NULL, NULL); + } + if (count($errbuff) > 0) + { + echo "The process '{$name}' returns the following error messages:\n"; + echo implode("\n", $errbuff),"\n"; + } + } + } + } + + protected function loop() + { + + $this->EventProcessor(); + } + + protected function PrepareDvblastParams ($_CONFIG) + { + $shellcmd = []; + $commonparams = ''; + foreach ($_CONFIG['WorkCommonParams'] as $option => $value) + { + switch ($option) + { + case 'es_timeout': + $commonparams .= '-7 '.(integer)$value.' '; + break; + case 'provider_name': + $commonparams .= '-B '.$value.' '; + break; + case 'network_id': + $commonparams .= '-N '.(integer)$value.' '; + break; + case 'network_name': + $commonparams .= '-M '.$value.' '; + break; + case 'ttl': + if ($value > 1 && $value <256) + { + $commonparams .= '-t '.(integer)$value.' '; + } + else + { + echo "ERROR: Invalid 'ttl' options value in config, default value will be used.\n"; + } + break; + case 'pidmap': + $commonparams .= '-0 '.$value.' '; + break; + case 'use_rtp': + if ($value === FALSE) + { + $commonparams .= '-U '; + } + break; + case 'epg_passthrough': + if ($value === TRUE) + { + $commonparams .= '-e '; + } + break; + } + } + foreach ($_CONFIG['WorkAdaptersCfg'] as $AdapterName => $AdapterCfg) + { + if ($AdapterCfg['MUX'] === FALSE) + { + continue; + } + $shellcmd[$AdapterName] = $_CONFIG['WorkCommonParams']['dvblast_path'].' '; + foreach ($AdapterCfg as $option => $value) + { + switch ($option) + { + case 'ADAPTER_NUM': + $shellcmd[$AdapterName] .= '-a '.(integer)$value.' '; + break; + case 'FRONTEND_NUM': + $shellcmd[$AdapterName] .= '-n '.(integer)$value.' '; + break; + } + } + foreach ($_CONFIG['Multiplexes'][$AdapterCfg['MUX']] as $option => $value) + { + switch ($option) + { + case 'delivery_system': + $shellcmd[$AdapterName] .= '-5 '.$value.' '; + break; + case 'frequency': + $shellcmd[$AdapterName] .= '-f '.(integer)$value.' '; + break; + case 'symbol_rate': + $shellcmd[$AdapterName] .= '-s '.(integer)$value.' '; + break; + case 'modulation': + $shellcmd[$AdapterName] .= '-m '.$value.' '; + break; + case 'plp_id': + $shellcmd[$AdapterName] .= '-9 '.(integer)$value.' '; + break; + case 'symbol_rate': + $shellcmd[$AdapterName] .= '-s '.(integer)$value.' '; + break; + case 'out': + $filecfgname = '/tmp/'.$AdapterName.'.dvbmcfg'; + $filecfgdata = implode("\n", $value)."\n"; + file_put_contents($filecfgname, $filecfgdata); + $shellcmd[$AdapterName] .= '-c '.$filecfgname.' '; + break; + } + } + $shellcmd[$AdapterName] .= $commonparams.'-q -r /tmp/dvb-'.$AdapterName.'.sock'; + } + return $shellcmd; + } +} + + +$PRG = new dvbmaster(); diff --git a/dvblastmaster/lib/mplib.php b/dvblastmaster/lib/mplib.php new file mode 100644 index 0000000..871965c --- /dev/null +++ b/dvblastmaster/lib/mplib.php @@ -0,0 +1,271 @@ + 0) + { + exit; + } + self::$origin_pid = posix_getpid(); + umask(0); + chdir('/'); + if (posix_setsid() == -1) + { + return FALSE; + } + + fclose(STDIN); + fclose(STDOUT); + fclose(STDERR); + $GLOBALS['STDIN'] = fopen('/dev/null', 'r'); + $GLOBALS['STDOUT']= fopen('/dev/null', 'w'); + $GLOBALS['STDERR'] = fopen('/dev/null', 'w'); + + return TRUE; + } + + public static function is_unique($pidfilename) + { + $mypid = posix_getpid(); + if (is_readable($pidfilename)) + { + $pid = (int) rtrim(file_get_contents($pidfilename)); + if ($pid == $mypid) + { + return TRUE; + } + if ($pid > 0 && posix_kill($pid, 0)) + { + return FALSE; + } + } + return TRUE; + + } + + public static function no_unique($pidfilename) + { + if (!@unlink($pidfilename)) + { + return FALSE; + } + else + { + return TRUE; + } + } + + public static function do_unique($pidfilename) + { + if (!self::is_unique($pidfilename)) + { + return FALSE; + } + + $mypid = posix_getpid(); + if (!@file_put_contents($pidfilename, $mypid.PHP_EOL)) + { + return FALSE; + } + register_shutdown_function(['self','shutdown']); + return TRUE; + } +} + +abstract class Children +{ + protected $PIPE; + protected $ROLE; + protected static $CHILDREN; + protected $CHILD; + protected $PARENT; + protected $IPCRXBUFFER = []; + + + public function __construct($data = NULL) + { + self::set_sig_handlers(); + $this->create_child(); + switch ($this->ROLE) + { + case MPRole_ERROR: + return FALSE; + case MPRole_PARENT: + return TRUE; + case MPRole_CHILD: + $this->ChildBody($data); + exit(); + } + + } + + public function __destruct() + { + if ($this->ROLE == MPRole_PARENT) + { + posix_kill($this->CHILD, SIGTERM); + } + } + + abstract protected function ChildBody($data); + + static function set_sig_handlers() + { + pcntl_signal(SIGCHLD, [__CLASS__, 'handler_sigchld']); + } + + public function SendUnixSignal($sig) + { + return posix_kill($this->CHILD, $sig); + } + + public function IsAlive() + { + if ($this->ROLE == MPRole_CHILD) + { + return TRUE; + } + if (isset(self::$CHILDREN[$this->CHILD])) + { + return TRUE; + } + else + { + return FALSE; + } + } + + public static function handler_sigchld() + { + $pid = pcntl_waitpid(0, $status, WNOHANG); + if($pid > 0 && isset(self::$CHILDREN[$pid])) + { + unset(self::$CHILDREN[$pid]); + } + } + + protected function create_child() + { + $sockets = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP); + stream_set_blocking ($sockets[0] , 0); + stream_set_blocking ($sockets[1] , 0); + $pid = pcntl_fork(); + if ($pid == -1) + { + $this->ROLE = MPRole_ERROR; + return FALSE; + } + elseif ($pid > 0) + { + // код для родителя + $this->CHILD = $pid; + self::$CHILDREN[$pid] = $pid; + $this->PARENT = FALSE; + $this->ROLE = MPRole_PARENT; + $this->PIPE = &$sockets[0]; + unset($sockets); + usleep(5000); + } + elseif ($pid == 0) + { + // код для ребёнка + $this->CHILD = FALSE; + $this->PARENT = posix_getppid(); + $this->ROLE = MPRole_CHILD; + $this->PIPE = &$sockets[1]; + unset($sockets); + } + return TRUE; + } + + public function SendEvent($eventname, $data) + { + if (!is_resource($this->PIPE)) + { + return FALSE; + } + $eventpack = base64_encode($eventname).chr(255).chr(0).chr(255).base64_encode(serialize($data)).chr(0).chr(15).chr(240).chr(255); + + $res = @stream_socket_sendto($this->PIPE, $eventpack); + if ($res == -1) + { + return TRUE; + } + else + { + return FALSE; + } + } + + public function WaitEvent($wait = TRUE) + { + if (count($this->IPCRXBUFFER) == 0) + { + if (!is_resource($this->PIPE)) + { + return FALSE; + } + + $r = [$this->PIPE]; + if ($wait) + { + while (stream_select($r, $w, $x, 0) == 0) + { + usleep(10000); + $r = [$this->PIPE]; + } + } + elseif (stream_select($r, $w, $x, 0) == 0) + { + return NULL; + } + $ipc_msg = ''; + while (substr($ipc_msg , -4) != chr(0).chr(15).chr(240).chr(255)) + { + $rcv_buf = stream_socket_recvfrom($this->PIPE, 1500); + if ($rcv_buf == '') + { + return NULL; + } + $ipc_msg .= $rcv_buf; + } + $ipc_msg = explode(chr(0).chr(15).chr(240).chr(255), $ipc_msg); + array_pop($ipc_msg); + $this->IPCRXBUFFER = array_merge($this->IPCRXBUFFER, $ipc_msg); + } + $ipc_msg = array_shift($this->IPCRXBUFFER); + $ipc_msg = explode(chr(255).chr(0).chr(255), $ipc_msg); + + $retval['eventname'] = base64_decode($ipc_msg[0]); + $retval['data'] = unserialize(base64_decode($ipc_msg[1])); + + return $retval; + + } +} diff --git a/dvblastmaster/lib/sts.php b/dvblastmaster/lib/sts.php new file mode 100644 index 0000000..9c7b8a5 --- /dev/null +++ b/dvblastmaster/lib/sts.php @@ -0,0 +1,135 @@ + $sectiondata) + { + if(!is_array($sectiondata)) + { + return FALSE; + } + $_RETVAL .= '['.$sectionname.']'.PHP_EOL; + foreach ($sectiondata as $param => $data) + { + if (is_array($data)) + { + $data = ''; + } + $_RETVAL .= $param.' = '.$data.PHP_EOL; + } + $_RETVAL .= PHP_EOL; + } + } + else + { + foreach ($ini_array as $param => $data) + { + $_RETVAL .= $param.' = '.$data.PHP_EOL; + } + } + return $_RETVAL; + } + private static function GetSignalDescription() + { + if (self::$SigArray === FALSE) + { + self::$SigArray = explode("\n", shell_exec('kill -l')); + } + } + + public static function GetSignalMnemonicByNumber($signo) + { + self::GetSignalDescription(); + if (isset(self::$SigArray[$signo])) + { + return self::$SigArray[$signo]; + } + else + { + return FALSE; + } + } + + public static function GetSignalNumberByMnemonic($sigmnemo) + { + self::GetSignalDescription(); + return array_search($sigmnemo, self::$SigArray); + } + + public static function stdout_prefix($prefix) + { + if (!self::$IsPrefixed) + { + self::$StdPrefix = $prefix; + ob_start(['self','ob_callback'],1); + self::$IsPrefixed = TRUE; + return TRUE; + } + else + { + return FALSE; + } + + } + + public static function stdout_unprefix() + { + if (self::$IsPrefixed) + { + ob_end_clean(); + self::$IsPrefixed = FALSE; + return TRUE; + } + else + { + return FALSE; + } + + } + + private static function ob_callback($buffer) + { + if (self::$IsLastEol) + { + $prefix = self::$StdPrefix; + } + else + { + $prefix = ''; + } + self::$IsLastEol = substr($buffer, -1) == PHP_EOL; + return $prefix.$buffer; + + } + +} + diff --git a/dvblastmaster/lib/timer.php b/dvblastmaster/lib/timer.php new file mode 100644 index 0000000..dc577cd --- /dev/null +++ b/dvblastmaster/lib/timer.php @@ -0,0 +1,119 @@ +id = uniqid(); + $this->time = $time; + $this->UserCall = $callable; + $this->UserCallArg = $args; + $this->type = $type; + if (!is_callable($this->UserCall, TRUE, $callablename)) + { + throw new Exception("parameter 2 must be callable, \$callable=". $callablename); + } + else + { + $this->start(); + self::$timers[$this->id] = &$this; + } + } + + public function __destruct() + { + unset(self::$timers[$this->id]); + } + + private function getId() + { + return $this->id; + } + + public function getTimeLeft() + { + return $this->ltime; + } + + public function setTimeLeft($time) + { + $this->time = $time; + } + + + public function reset() + { + $this->StartTime = microtime(true); + $this->IsStop = FALSE; + } + + public function start() + { + $this->reset(); + $this->IsStop = FALSE; + } + + public function stop() + { + $this->IsStop = TRUE; + } + + public static function poll() + { + foreach (self::$timers as $timer) + { + if ($timer->IsStop == FALSE) + { + $timer->update(); + } + } + } + + private function update() + { + $this->ltime = $this->StartTime - microtime(true) + $this->time; + if ($this->ltime <= 0) + { + $this->ltime = 0; + $this->task(); + if ($this->type === FALSE) + { + $this->stop(); + } + elseif ($this->type === TRUE) + { + $this->reset(); + } + elseif ($this->type === NULL) + { + $this->stop(); + $this->__destruct(); + } + } + } + + private function task() + { + call_user_func_array ($this->UserCall, $this->UserCallArg); + } +} diff --git a/dvblastmaster/sigtest.php b/dvblastmaster/sigtest.php new file mode 100644 index 0000000..2fd38fc --- /dev/null +++ b/dvblastmaster/sigtest.php @@ -0,0 +1,67 @@ + 1, 'b' => 2, 'c' => $tarr1]; +$array2 = ['a' => 1, 'b' => 2, 'c' => $tarr2]; +//var_dump($tarr1 == $array2['c']); +//var_dump($array1 == $array2); + +$result = array_udiff_assoc($array1, $array2, function ($a, $b) {return (int)!($a === $b);}); + +function cmpre($param1, $param2) +{ + var_dump($param1,$param2); + echo '------',PHP_EOL; + return 1; +} + +var_dump($result); +exit(); +var_dump($a); +if (($a = 5) < 1) +{ + echo 'TRUE',PHP_EOL; +} +else +{ + echo 'FALSE',PHP_EOL; +} +var_dump($a); +exit(); +// Обязательно +declare(ticks = 1); + +// функция обработки сигнала +function sig_handler($signo,$signinfo) +{ + + + file_put_contents('/tmp/sigtest.txt', "PID:".posix_getpid()." GOT SIGNAL {$signo} ".print_r($signinfo,true)."\n", FILE_APPEND); + + + +} + +echo "Установка обработчиков сигналов...\n"; + +// Установка обработчиков сигналов +pcntl_signal(SIGTERM, "sig_handler"); +pcntl_signal(SIGHUP, "sig_handler"); +pcntl_signal(SIGABRT, "sig_handler"); +pcntl_signal(SIGINT, "sig_handler"); +pcntl_signal(SIGQUIT, "sig_handler"); +pcntl_signal(SIGINT, "sig_handler"); +//pcntl_signal(SIGSTOP, "sig_handler"); + +sleep(3); +sleep(3); + +//exit(); +// или можете использовать объект +// pcntl_signal(SIGUSR1, array($obj, "do_something")); + +while (1) +{ + echo '*'; + sleep(1); +} \ No newline at end of file diff --git a/term/lowterm.php b/term/lowterm.php new file mode 100644 index 0000000..dfe7465 --- /dev/null +++ b/term/lowterm.php @@ -0,0 +1,22 @@ +