Merge branch '3.8'

Conflicts:
	composer.json
	composer.lock
	lib/classes/task/Scheduler.php
This commit is contained in:
Romain Neutron
2013-10-21 19:05:37 +02:00
8 changed files with 101 additions and 64 deletions

View File

@@ -35,7 +35,7 @@
"silex/web-profiler" : "~1.0.0", "silex/web-profiler" : "~1.0.0",
"swiftmailer/swiftmailer" : "~4.3.0", "swiftmailer/swiftmailer" : "~4.3.0",
"symfony/symfony" : "2.4.x-dev@dev", "symfony/symfony" : "2.4.x-dev@dev",
"tecnick.com/tcpdf" : "~6.0", "alchemy-fr/tcpdf" : "~6.0",
"themattharris/tmhoauth" : "~0.7", "themattharris/tmhoauth" : "~0.7",
"twig/twig" : "~1.12", "twig/twig" : "~1.12",
"twig/extensions" : "~1.0", "twig/extensions" : "~1.0",
@@ -52,6 +52,12 @@
"behat/mink-selenium2-driver" : "~1.0", "behat/mink-selenium2-driver" : "~1.0",
"fabpot/goutte" : "~1.0" "fabpot/goutte" : "~1.0"
}, },
"repositories": [
{
"type": "git",
"url": "https://github.com/alchemy-fr/tcpdf-clone"
}
],
"autoload": { "autoload": {
"psr-0": { "psr-0": {
"" : "lib/classes", "" : "lib/classes",

View File

@@ -34,11 +34,14 @@ class task_Scheduler
private $method; private $method;
private $dependencyContainer; private $dependencyContainer;
private $schedstatus;
public function __construct(Application $application, Logger $logger) public function __construct(Application $application, Logger $logger)
{ {
declare(ticks = 1); declare(ticks = 1);
$this->dependencyContainer = $application; $this->dependencyContainer = $application;
$this->logger = $logger; $this->logger = $logger;
$this->schedstatus = '';
} }
protected function log($message) protected function log($message)
@@ -47,6 +50,7 @@ class task_Scheduler
return $this; return $this;
} }
protected function sleep($nsec) protected function sleep($nsec)
{ {
$nsec = (integer) $nsec; $nsec = (integer) $nsec;
@@ -66,10 +70,21 @@ class task_Scheduler
*/ */
public function sigHandler($signal) public function sigHandler($signal)
{ {
$status = null; switch ($signal) {
$pid = pcntl_wait($status); case SIGCHLD:
$exitstatus = pcntl_wexitstatus($status); $status = null;
$this->log(sprintf("sigchild %s received from pid=%s, status=%s, exitstatus=%s\n", $signal, $pid, var_export($status, true), $exitstatus)); $pid = pcntl_wait($status);
$exitstatus = pcntl_wexitstatus($status);
$this->log(sprintf("SIGCHLD (%s) received from pid=%s, status=%s, exitstatus=%s", $signal, $pid, var_export($status, true), $exitstatus));
break;
case SIGINT: // ctrl C
$this->log(sprintf("SIGINT (%s) Ctrl-C received, schedstatus='tostop'", $signal));
$this->schedstatus = 'tostop';
break;
case SIGTERM:
$this->log(sprintf("SIGTERM (%s) received but ignored, http timeout ?", $signal));
break;
}
} }
public function run() public function run()
@@ -99,6 +114,8 @@ class task_Scheduler
// pcntl_signal(SIGCHLD, SIG_IGN); // no zombies but no returnValue // pcntl_signal(SIGCHLD, SIG_IGN); // no zombies but no returnValue
// pcntl_signal(SIGCHLD, SIG_DFL); // with "declare(ticks=1)" returnValue ok but zombies // pcntl_signal(SIGCHLD, SIG_DFL); // with "declare(ticks=1)" returnValue ok but zombies
pcntl_signal(SIGCHLD, array($this, 'sigHandler')); // ok pcntl_signal(SIGCHLD, array($this, 'sigHandler')); // ok
pcntl_signal(SIGINT, array($this, 'sigHandler'));
pcntl_signal(SIGTERM, array($this, 'sigHandler'));
$this->method = self::METHOD_FORK; $this->method = self::METHOD_FORK;
} }
@@ -159,11 +176,11 @@ class task_Scheduler
} }
} }
$schedstatus = 'started'; $this->schedstatus = 'started';
$runningtask = 0; $runningtask = 0;
$connwaslost = false; $connwaslost = false;
while ($schedstatus == 'started' || $runningtask > 0) { while ($this->schedstatus == 'started' || $runningtask > 0) {
while (1) { while (1) {
try { try {
assert(is_object($conn)); assert(is_object($conn));
@@ -199,23 +216,25 @@ class task_Scheduler
$connwaslost = false; $connwaslost = false;
} }
$schedstatus = ''; if ($this->schedstatus == "started") {
$row = NULL; $this->schedstatus = '';
try { $row = NULL;
$sql = "SELECT schedstatus FROM sitepreff"; try {
$stmt = $conn->prepare($sql); $sql = "SELECT schedstatus FROM sitepreff";
$stmt->execute(); $stmt = $conn->prepare($sql);
$row = $stmt->fetch(PDO::FETCH_ASSOC); $stmt->execute();
$stmt->closeCursor(); $row = $stmt->fetch(PDO::FETCH_ASSOC);
} catch (ErrorException $e) { $stmt->closeCursor();
continue; } catch (ErrorException $e) {
continue;
}
if ($row) {
$this->schedstatus = $row["schedstatus"];
}
} }
if ($row) { if ($this->schedstatus == 'tostop') {
$schedstatus = $row["schedstatus"];
}
if ($schedstatus == 'tostop') {
$sql = 'UPDATE sitepreff SET schedstatus = "stopping"'; $sql = 'UPDATE sitepreff SET schedstatus = "stopping"';
$stmt = $conn->prepare($sql); $stmt = $conn->prepare($sql);
$stmt->execute(); $stmt->execute();
@@ -337,7 +356,7 @@ class task_Scheduler
} }
} }
if ($schedstatus == 'started') { if ($this->schedstatus == 'started') {
$taskPoll[$tkey]["task"]->setState(task_abstract::STATE_TOSTART); $taskPoll[$tkey]["task"]->setState(task_abstract::STATE_TOSTART);
} }
// trick to start the task immediatly : DON'T break if ending with 'tostart' // trick to start the task immediatly : DON'T break if ending with 'tostart'
@@ -348,7 +367,7 @@ class task_Scheduler
case task_abstract::STATE_TOSTART: case task_abstract::STATE_TOSTART:
// if scheduler is 'tostop', don't launch a new task ! // if scheduler is 'tostop', don't launch a new task !
if ($schedstatus != 'started') { if ($this->schedstatus != 'started') {
break; break;
} }
@@ -584,8 +603,16 @@ class task_Scheduler
break; break;
} }
} }
if(function_exists('pcntl_sigprocmask')) {
$this->sleep($sleeptime); @pcntl_sigprocmask(SIG_BLOCK, array(SIGCHLD));
}
$this->sleep(1);
for ($i = 0; $this->schedstatus=='started' && $i < $sleeptime; $i++) {
$this->sleep(1);
}
if(function_exists('pcntl_sigprocmask')) {
@pcntl_sigprocmask(SIG_UNBLOCK, array(SIGCHLD));
}
} }
$sql = "UPDATE sitepreff SET schedstatus='stopped', schedpid='0'"; $sql = "UPDATE sitepreff SET schedstatus='stopped', schedpid='0'";

View File

@@ -161,6 +161,13 @@ class task_manager
if (!in_array($status, $av_status)) if (!in_array($status, $av_status))
throw new Exception(sprintf('unknown status `%s` ', $status)); throw new Exception(sprintf('unknown status `%s` ', $status));
if ($status == self::STATE_TOSTOP && function_exists('posix_kill')) {
$gs = $this->getSchedulerState();
if ($gs['pid'] !== NULL) {
@posix_kill($gs['pid'], 2); // 2 = SIGINT
}
}
$sql = "UPDATE sitepreff SET schedstatus = :schedstatus, schedqtime=NOW()"; $sql = "UPDATE sitepreff SET schedstatus = :schedstatus, schedqtime=NOW()";
$stmt = $this->app['phraseanet.appbox']->get_connection()->prepare($sql); $stmt = $this->app['phraseanet.appbox']->get_connection()->prepare($sql);
$stmt->execute(array(':schedstatus' => $status)); $stmt->execute(array(':schedstatus' => $status));

View File

@@ -15,23 +15,6 @@
margin: 0px; margin: 0px;
padding: 0px; padding: 0px;
} }
.ui-content{
height: 85%;
width: 100%;
margin: 0px;
padding: 0px;
display:table;
}
#map {
height: 100%;
width: 100%;
padding: 0px;
display:table-cell;
vertical-align: middle;
text-align: center
}
</style> </style>
{% block stylesheet %}{% endblock %} {% block stylesheet %}{% endblock %}
{% block icon %}{% endblock %} {% block icon %}{% endblock %}

View File

@@ -72,7 +72,6 @@
{% macro format100percent(thumbnail, extraclass)%} {% macro format100percent(thumbnail, extraclass)%}
{% set record_type = thumbnail.get_type() %} {% set record_type = thumbnail.get_type() %}
<div id="map">
{% if record_type == 'VIDEO_MP4' or record_type == 'VIDEO_FLV' %} {% if record_type == 'VIDEO_MP4' or record_type == 'VIDEO_FLV' %}
{% set random = thumbnail.get_random() %} {% set random = thumbnail.get_random() %}
<div class="record record_video imgTips"> <div class="record record_video imgTips">
@@ -102,8 +101,7 @@
"{{thumbnail.get_width()}}", "{{thumbnail.get_height()}}", "9.0.0", false, false, "{{thumbnail.get_width()}}", "{{thumbnail.get_height()}}", "9.0.0", false, false,
{menu: "false",flashvars: "playerID=2&autostart=yes&noinfo=yes&animation=no&remaining=yes&soundFile={{thumbnail.get_url()}}", movie: "/include/jslibs/audio-player/player.swf", allowFullScreen :"true",wmode: "transparent"}, false);</script> {menu: "false",flashvars: "playerID=2&autostart=yes&noinfo=yes&animation=no&remaining=yes&soundFile={{thumbnail.get_url()}}", movie: "/include/jslibs/audio-player/player.swf", allowFullScreen :"true",wmode: "transparent"}, false);</script>
{% else %} {% else %}
<img style="height:100%;" class="record record_image imgTips zoomable thumb" oncontextMenu="return(false);" <img style="max-height: 100%;max-width:100%" class="record record_image imgTips zoomable thumb" oncontextMenu="return(false);"
src="{{thumbnail.get_url()}}" ondragstart="return false;"> src="{{thumbnail.get_url()}}" ondragstart="return false;" />
{% endif %} {% endif %}
</div>
{% endmacro %} {% endmacro %}

View File

@@ -8,17 +8,32 @@
{% block stylesheet %} {% block stylesheet %}
<link rel="stylesheet" href="{{ path('minifier', { 'f' : 'skins/lightbox/jquery.validator.mobile.css' }) }}" /> <link rel="stylesheet" href="{{ path('minifier', { 'f' : 'skins/lightbox/jquery.validator.mobile.css' }) }}" />
<style type="text/css">
div[data-role="page"] {
position: relative;
}
#content {
position:absolute;
top:50px;
bottom: 0;
right: 0;
left: 0;
text-align: center;
}
</style>
{% endblock %} {% endblock %}
{% block content %} {% block content %}
{% set record = basket_element.getRecord(app) %} {% set record = basket_element.getRecord(app) %}
<div data-role="page"> <div data-role="page" id="page">
<div data-role="header"> <div data-role="header">
<a href="{{ path('lightbox_validation', { 'ssel_id' : basket_element.getBasket().getId() }) }}" data-rel="back" data-icon="arrow-l">Back</a> <a href="{{ path('lightbox_validation', { 'ssel_id' : basket_element.getBasket().getId() }) }}" data-rel="back" data-icon="arrow-l">Back</a>
<h1>{{basket_element.getOrd()}} - {{record.get_title()}}</h1> <h1>{{basket_element.getOrd()}} - {{record.get_title()}}</h1>
<a rel="external" href="{{ path('lightbox') }}" data-icon="home" data-iconpos="notext" data-direction="reverse" class="ui-btn-right jqm-home">Home</a> <a rel="external" href="{{ path('lightbox') }}" data-icon="home" data-iconpos="notext" data-direction="reverse" class="ui-btn-right jqm-home">Home</a>
</div> </div>
<div data-role="content"> <div id="content" data-role="content">
{{ thumbnail.format100percent(record.get_preview()) }} {{ thumbnail.format100percent(record.get_preview()) }}
{% if basket_element.getBasket().getValidation() %} {% if basket_element.getBasket().getValidation() %}
{% if basket_element.getBasket().getValidation().getParticipant(app['authentication'].getUser(), app).getCanAgree() %} {% if basket_element.getBasket().getValidation().getParticipant(app['authentication'].getUser(), app).getCanAgree() %}
@@ -44,11 +59,5 @@
<div data-role="footer"> <div data-role="footer">
</div> </div>
<script type="text/javascript">
$( window ).on( "orientationchange", function( event ) {
$("#map").height($(window).height() - 50);
});
$( window ).orientationchange();
</script>
</div> </div>
{% endblock %} {% endblock %}

View File

@@ -8,6 +8,21 @@
{% block stylesheet %} {% block stylesheet %}
<link rel="stylesheet" href="{{ path('minifier', { 'f' : 'skins/lightbox/jquery.validator.mobile.css' }) }}" /> <link rel="stylesheet" href="{{ path('minifier', { 'f' : 'skins/lightbox/jquery.validator.mobile.css' }) }}" />
<style type="text/css">
div[data-role="page"] {
position: relative;
}
#content {
position:absolute;
top:50px;
bottom: 0;
right: 0;
left: 0;
text-align: center;
}
</style>
{% endblock %} {% endblock %}
{% block content %} {% block content %}
@@ -22,13 +37,5 @@
{{ thumbnail.format100percent(record.get_preview()) }} {{ thumbnail.format100percent(record.get_preview()) }}
</div> </div>
<div data-role="footer"> <div data-role="footer">
</div>
<script type="text/javascript">
$( window ).on( "orientationchange", function( event ) {
$("#map").height($(window).height() - 50);
});
$( window ).orientationchange();
</script>
</div> </div>
{% endblock %} {% endblock %}

View File

@@ -78,4 +78,4 @@
</div> </div>
{% endfor %} {% endfor %}
{% endfor %} {% endfor %}
{% endmacro %} {% endmacro %}