From 17b1d459687ec068dd5bd968196f8afc8660b14d Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 9 Sep 2015 22:42:31 +0200
Subject: [PATCH] Worker: New method for running background processes

---
 boot.php                | 22 +++++++++++--
 include/dbstructure.php | 14 +++++++++
 include/worker.php      | 68 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 101 insertions(+), 3 deletions(-)
 create mode 100755 include/worker.php

diff --git a/boot.php b/boot.php
index 7451891fe..7f3238013 100644
--- a/boot.php
+++ b/boot.php
@@ -1432,8 +1432,25 @@ if(! function_exists('proc_run')) {
 		if(! $arr['run_cmd'])
 			return;
 
-		if(count($args) && $args[0] === 'php')
+		if(count($args) && $args[0] === 'php') {
+			$argv = $args;
+			array_shift($argv);
+
+			$parameters = json_encode($argv);
+			$found = q("SELECT `id` FROM `workerqueue` WHERE `parameter` = '%s'",
+					dbesc($parameters));
+
+			if (!$found)
+				q("INSERT INTO `workerqueue` (`parameter`, `created`, `priority`)
+							VALUES ('%s', '%s', %d)",
+					dbesc($parameters),
+					dbesc(datetime_convert()),
+					intval(0));
+
+			// return;
+
 			$args[0] = ((x($a->config,'php_path')) && (strlen($a->config['php_path'])) ? $a->config['php_path'] : 'php');
+		}
 
 		// add baseurl to args. cli scripts can't construct it
 		$args[] = $a->get_baseurl();
@@ -1441,9 +1458,8 @@ if(! function_exists('proc_run')) {
 		for($x = 0; $x < count($args); $x ++)
 			$args[$x] = escapeshellarg($args[$x]);
 
-
-
 		$cmdline = implode($args," ");
+
 		if(get_config('system','proc_windows'))
 			proc_close(proc_open('cmd /c start /b ' . $cmdline,array(),$foo,dirname(__FILE__)));
 		else
diff --git a/include/dbstructure.php b/include/dbstructure.php
index 2b1ee84fd..deb6ddf53 100644
--- a/include/dbstructure.php
+++ b/include/dbstructure.php
@@ -1382,6 +1382,20 @@ function db_definition() {
 					"username" => array("username"),
 					)
 			);
+	$database["workerqueue"] = array(
+			"fields" => array(
+					"id" => array("type" => "int(11)", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
+					"parameter" => array("type" => "text", "not null" => "1"),
+					"priority" => array("type" => "tinyint(3) unsigned", "not null" => "1", "default" => "0"),
+					"created" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
+					"pid" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
+					"executed" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
+					),
+			"indexes" => array(
+					"PRIMARY" => array("id"),
+					"created" => array("created"),
+					)
+			);
 
 	return($database);
 }
diff --git a/include/worker.php b/include/worker.php
new file mode 100755
index 000000000..e1eee388c
--- /dev/null
+++ b/include/worker.php
@@ -0,0 +1,68 @@
+#!/usr/bin/php
+<?php
+if (sizeof($_SERVER["argv"]) == 0)
+	die();
+
+$directory = dirname($_SERVER["argv"][0]);
+
+if (substr($directory, 0, 1) != "/")
+	$directory = $_SERVER["PWD"]."/".$directory;
+
+$directory = realpath($directory."/..");
+
+chdir($directory);
+require_once("boot.php");
+
+global $a, $db;
+
+if(is_null($a)) {
+	$a = new App;
+}
+
+if(is_null($db)) {
+	@include(".htconfig.php");
+	require_once("include/dba.php");
+	$db = new dba($db_host, $db_user, $db_pass, $db_data);
+	unset($db_host, $db_user, $db_pass, $db_data);
+};
+
+// Cleaning killed processes
+$r = q("SELECT DISTINCT(`pid`) FROM `workerqueue` WHERE `executed` != '0000-00-00 00:00:00'");
+foreach($r AS $pid)
+	if (!posix_kill($pid["pid"], 0))
+		q("UPDATE `workerqueue` SET `executed` = '0000-00-00 00:00:00', `pid` = 0 WHERE `pid` = %d",
+			intval($pid["pid"]));
+
+// Checking number of workers
+$workers = q("SELECT COUNT(*) AS `workers` FROM `workerqueue` WHERE `executed` != '0000-00-00 00:00:00'");
+
+$threads = 3;
+
+if ($workers[0]["workers"] >= $threads)
+	return;
+
+while ($r = q("SELECT * FROM `workerqueue` WHERE `executed` = '0000-00-00 00:00:00' ORDER BY `created` LIMIT 1")) {
+	q("UPDATE `workerqueue` SET `executed` = '%s', `pid` = %d WHERE `id` = %d",
+		dbesc(datetime_convert()),
+		intval(getmypid()),
+		intval($r[0]["id"]));
+
+	$argv = json_decode($r[0]["parameter"]);
+
+	$argc = count($argv);
+
+	// To-Do: Check for existance
+	require_once(basename($argv[0]));
+
+	$funcname=str_replace(".php", "", basename($argv[0]))."_run";
+
+	if (function_exists($funcname)) {
+		logger("Process ".getmypid().": ".$funcname." ".$r[0]["parameter"]);
+		//$funcname($argv, $argc);
+		sleep(10);
+		logger("Process ".getmypid().": ".$funcname." - done");
+
+		q("DELETE FROM `workerqueue` WHERE `id` = %d", intval($r[0]["id"]));
+	}
+}
+?>