|
@@ -0,0 +1,122 @@
|
|
|
|
+<?php
|
|
|
|
+
|
|
|
|
+namespace WorkflowBundle\Command;
|
|
|
|
+
|
|
|
|
+use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
|
|
|
|
+use Symfony\Component\Console\Input\InputInterface;
|
|
|
|
+use Symfony\Component\Console\Input\InputOption;
|
|
|
|
+use Symfony\Component\Console\Output\OutputInterface;
|
|
|
|
+use WorkflowBundle\Services\TaskLoggerService;
|
|
|
|
+
|
|
|
|
+class LockWaitCommand extends ContainerAwareCommand
|
|
|
|
+{
|
|
|
|
+
|
|
|
|
+ protected function configure()
|
|
|
|
+ {
|
|
|
|
+ $this
|
|
|
|
+ ->setName('lock:wait')
|
|
|
|
+ ->setDescription('Lock wait command')
|
|
|
|
+ ->setHelp('Lock wait command. Wait for lock a file. The lock can be either exclusive or shared')
|
|
|
|
+ ->addArgument('filename', InputOption::VALUE_REQUIRED, 'Filename')
|
|
|
|
+ ->addOption('command', 'c', InputOption::VALUE_REQUIRED, 'Command to execute')
|
|
|
|
+ ->addOption('dir', null, InputOption::VALUE_REQUIRED, 'Directory path file', '/tmp')
|
|
|
|
+ ->addOption('timeout', null, InputOption::VALUE_REQUIRED, 'Timeout execution (ms)', 600)
|
|
|
|
+ ->addOption('no-exclusive', 'no-e', InputOption::VALUE_NONE, 'No exclusive lock')
|
|
|
|
+ ;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * @param InputInterface $input
|
|
|
|
+ * @param OutputInterface $output
|
|
|
|
+ */
|
|
|
|
+ protected function execute(InputInterface $input, OutputInterface $output)
|
|
|
|
+ {
|
|
|
|
+ $filename = $input->getArgument('filename');
|
|
|
|
+ $command = $input->getOption('command');
|
|
|
|
+ $dir = $input->getOption('dir');
|
|
|
|
+ $timeout = $input->getOption('timeout');
|
|
|
|
+ $no_exclusive = $input->getOption('no-exclusive');
|
|
|
|
+ if ($filename && $command) {
|
|
|
|
+ $handle = $this->fopen($filename, $dir);
|
|
|
|
+ $this->flock($handle, $command, $timeout, $no_exclusive);
|
|
|
|
+ } else {
|
|
|
|
+ $output->writeln('<error>Enter a valid filename and command</error>');
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * @param string $filename
|
|
|
|
+ * @param string $dir
|
|
|
|
+ *
|
|
|
|
+ * @return resource
|
|
|
|
+ */
|
|
|
|
+ protected function fopen($filename, $dir)
|
|
|
|
+ {
|
|
|
|
+ // limpio el filename completo
|
|
|
|
+ $invalid_chars = array(" ", '"', "'", "&", "\\", "?", "#", "$", "//");
|
|
|
|
+ $delimiter = DIRECTORY_SEPARATOR;
|
|
|
|
+ $dir_pieces = explode($delimiter, str_replace($invalid_chars, '', $dir));
|
|
|
|
+ $filename_pieces = explode($delimiter, str_replace($invalid_chars, '', $filename));
|
|
|
|
+ $last_filename_piece = array_pop($filename_pieces);
|
|
|
|
+
|
|
|
|
+ $dir = $delimiter . implode($delimiter, array_filter(array_merge($dir_pieces, $filename_pieces)));
|
|
|
|
+ $filename = $dir . $delimiter . $last_filename_piece;
|
|
|
|
+
|
|
|
|
+ if (!file_exists($dir)) {
|
|
|
|
+ mkdir($dir, 0777, true);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return fopen($filename, "w+");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * @param resource $handle
|
|
|
|
+ * @param string $command
|
|
|
|
+ * @param int $timeout
|
|
|
|
+ * @param boolean $no_exclusive
|
|
|
|
+ *
|
|
|
|
+ * @return boolean
|
|
|
|
+ */
|
|
|
|
+ protected function flock($handle, $command, $timeout = 600, $no_exclusive = false)
|
|
|
|
+ {
|
|
|
|
+ pcntl_signal(SIGALRM, function() {
|
|
|
|
+ exit(1);
|
|
|
|
+ });
|
|
|
|
+ pcntl_alarm($timeout);
|
|
|
|
+
|
|
|
|
+ $operation = LOCK_EX;
|
|
|
|
+ if ($no_exclusive) {
|
|
|
|
+ $operation = LOCK_SH;
|
|
|
|
+ }
|
|
|
|
+ if (flock($handle, $operation)) {
|
|
|
|
+ $exit_code = $this->runProcess($command)['exit_code'];
|
|
|
|
+ } else {
|
|
|
|
+ echo 'No se pudo obtener el lock' . PHP_EOL;
|
|
|
|
+ $exit_code = 1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pcntl_alarm(0);
|
|
|
|
+ pcntl_signal_dispatch();
|
|
|
|
+ pcntl_signal(SIGALRM, SIG_DFL);
|
|
|
|
+
|
|
|
|
+ flock($handle, LOCK_UN);
|
|
|
|
+ fclose($handle);
|
|
|
|
+
|
|
|
|
+ exit($exit_code);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * @param string $filename
|
|
|
|
+ *
|
|
|
|
+ * @return array
|
|
|
|
+ */
|
|
|
|
+ protected function runProcess($filename)
|
|
|
|
+ {
|
|
|
|
+ /* @var $taskloggerService TaskLoggerService */
|
|
|
|
+ $taskloggerService = $this->getContainer()->get('flowdat_tasklogger_service');
|
|
|
|
+
|
|
|
|
+ return $taskloggerService->runProcess($filename);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+}
|