Completed
Push — master ( 4541a4...2fe9dd )
by Maxence
01:49
created

Runner::sourceIsCommandLine()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
rs 10
cc 1
nc 1
nop 2
1
<?php
2
/**
3
 * FullTextSearch - Full text search framework for Nextcloud
4
 *
5
 * This file is licensed under the Affero General Public License version 3 or
6
 * later. See the COPYING file.
7
 *
8
 * @author Maxence Lange <[email protected]>
9
 * @copyright 2018
10
 * @license GNU AGPL version 3 or any later version
11
 *
12
 * This program is free software: you can redistribute it and/or modify
13
 * it under the terms of the GNU Affero General Public License as
14
 * published by the Free Software Foundation, either version 3 of the
15
 * License, or (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU Affero General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU Affero General Public License
23
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
24
 *
25
 */
26
27
28
namespace OCA\FullTextSearch\Model;
29
30
use OCA\FullTextSearch\Exceptions\RunnerAlreadyUpException;
31
use OCA\FullTextSearch\Exceptions\TickDoesNotExistException;
32
use OCA\FullTextSearch\Exceptions\TickIsNotAliveException;
33
use OCA\FullTextSearch\Service\MiscService;
34
use OCA\FullTextSearch\Service\RunningService;
35
use Symfony\Component\Console\Output\OutputInterface;
36
37
38
class Runner {
39
40
41
	const TICK_TTL = 300;
42
	const TICK_MINIMUM = 2;
43
	const MEMORY_INFO_UPDATE = 5;
44
45
	const RESULT_TYPE_SUCCESS = 1;
46
	const RESULT_TYPE_WARNING = 4;
47
	const RESULT_TYPE_FAIL = 9;
48
49
	/** @var RunningService */
50
	private $runningService;
51
52
	/** @var string */
53
	private $source;
54
55
//	/** @var bool */
56
//	private $strict = false;
57
58
	/** @var int */
59
	private $tickId;
60
61
	/** @var ExtendedBase */
62
	private $commandBase = null;
63
64
	/** @var OutputInterface */
65
	private $outputInterface = null;
66
67
	/** @var array */
68
	private $info = [];
69
70
	/** @var int */
71
	private $oldTick = 0;
72
73
	/** @var string */
74
	private $oldAction = '';
75
76
	/** @var int */
77
	private $ramTick = 0;
78
79
	/** @var array */
80
	private $methodOnKeyPress = [];
81
82
	/** @var array */
83
	private $methodOnInfoUpdate = [];
84
85
	/** @var array */
86
	private $methodOnIndexError = [];
87
88
	/** @var array */
89
	private $methodOnIndexResult = [];
90
91
	/** @var bool */
92
	private $paused = false;
93
94
	/** @var bool */
95
	private $pauseRunning = false;
96
97
	/** @var array */
98
	private $keys = ['nextStep' => 'n'];
99
100
101
	/**
102
	 * Runner constructor.
103
	 *
104
	 * @param RunningService $runningService
105
	 * @param string $source
106
	 * @param array $keys
107
	 */
108
	public function __construct(RunningService $runningService, $source, $keys = []) {
109
		$this->runningService = $runningService;
110
		$this->source = $source;
111
112
		if (sizeof($keys) > 0) {
113
			$this->keys = $keys;
114
		}
115
	}
116
117
118
	/**
119
	 * @throws RunnerAlreadyUpException
120
	 */
121
	public function start() {
122
//		$this->strict = $strict;
123
		$this->tickId = $this->runningService->start($this->source);
124
	}
125
126
127
	/**
128
	 * @param string $action
129
	 * @param bool $force
130
	 *
131
	 * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be string|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
132
	 * @throws \Exception
133
	 */
134
	public function updateAction($action = '', $force = false) {
135
		$n = '';
136
		if (sizeof($this->methodOnKeyPress) > 0) {
137
			$n = fread(STDIN, 9999);
138
			if ($n !== '') {
139
				$n = substr($n, 0, 1);
140
				$this->keyPressed($n);
141
			}
142
		}
143
144
		if ($action === '') {
145
			return $n;
146
		}
147
148
		$tick = time();
149
//		try {
150
//			$this->hasBeenInterrupted();
151
//		} catch (InterruptException $e) {
152
//			$this->stop();
153
//			throw $e;
154
//		}
155
156
		if ($this->oldAction !== $action || $force) {
157
			while (true) {
158
				if (!$this->isPaused()) {
159
					break;
160
				}
161
162
				$this->pauseRunning(true);
163
				$pressed = strtolower($this->updateAction(''));
164
				if ($pressed === $this->keys['nextStep']) {
165
					break;
166
				}
167
				usleep(300000);
168
			}
169
170
			$this->pauseRunning(false);
171
		}
172
173
		if ($this->oldAction === $action && ($this->oldTick + self::TICK_MINIMUM > $tick)) {
174
			return '';
175
		}
176
177
		$this->setInfo('action', $action);
178
		try {
179
			$this->runningService->update($this->tickId, $action);
180
		} catch (TickIsNotAliveException $e) {
181
			$this->output('Force Quit');
182
			exit();
183
		}
184
185
		$this->updateTick($tick);
186
		$this->oldAction = $action;
187
		$this->oldTick = $tick;
188
189
		return '';
190
	}
191
192
193
	/**
194
	 * @param string $info
195
	 * @param string $value
196
	 * @param int $type
197
	 */
198
	public function setInfo($info, $value, $type = 0) {
199
		$this->info[$info] = $value;
200
		$this->setInfoColored($info, $type);
201
		$this->infoUpdated();
202
	}
203
204
	/**
205
	 * @param array $data
206
	 */
207
	public function setInfoArray($data) {
208
		$keys = array_keys($data);
209
		//$this->info['info'] = '';
210
		foreach ($keys as $k) {
211
			$this->info[$k] = $data[$k];
212
		}
213
214
		$this->infoUpdated();
215
	}
216
217
218
	/**
219
	 * @param string $info
220
	 * @param int $level
221
	 */
222
	public function setInfoColored($info, $level) {
223
224
		$value = $this->getInfo($info);
225
		if ($value === '') {
226
			return;
227
		}
228
229
		$color = '';
230
		switch ($level) {
231
			case self::RESULT_TYPE_SUCCESS:
232
				$color = 'info';
233
				break;
234
235
			case self::RESULT_TYPE_WARNING:
236
				$color = 'comment';
237
				break;
238
239
			case self::RESULT_TYPE_FAIL:
240
				$color = 'error';
241
				break;
242
		}
243
244
		if ($color !== '') {
245
			$this->info[$info . 'Colored'] = '<' . $color . '>' . $value . '</' . $color . '>';
246
		}
247
248
249
	}
250
251
	/**
252
	 * @return array
253
	 */
254
	public function getInfoAll() {
255
		return $this->info;
256
	}
257
258
259
	/**
260
	 * @param string $k
261
	 *
262
	 * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be array|string|integer? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
263
	 */
264
	public function getInfo($k) {
265
		return MiscService::get($k, $this->info, '');
266
	}
267
268
269
	/**
270
	 * @param array $method
271
	 */
272
	public function onKeyPress($method) {
273
		$this->methodOnKeyPress[] = $method;
274
	}
275
276
	/**
277
	 * @param $key
278
	 */
279
	public function keyPressed($key) {
280
		foreach ($this->methodOnKeyPress as $method) {
281
			call_user_func($method, $key);
282
		}
283
	}
284
285
286
	/**
287
	 * @param array $method
288
	 */
289
	public function onInfoUpdate($method) {
290
		$this->methodOnInfoUpdate[] = $method;
291
	}
292
293
	/**
294
	 * @param $key
295
	 */
296
	public function infoUpdated() {
297
		foreach ($this->methodOnInfoUpdate as $method) {
298
			call_user_func($method, $this->info);
299
		}
300
	}
301
302
303
	/**
304
	 * @param array $method
305
	 */
306
	public function onNewIndexError($method) {
307
		$this->methodOnIndexError[] = $method;
308
	}
309
310
	/**
311
	 * @param Index $index
312
	 * @param string $message
313
	 * @param string $class
314
	 * @param int $sev
315
	 */
316
	public function newIndexError($index, $message, $class = '', $sev = 3) {
317
		$error = [
318
			'index'     => $index,
319
			'message'   => $message,
320
			'exception' => $class,
321
			'severity'  => $sev
322
		];
323
324
		foreach ($this->methodOnIndexError as $method) {
325
			call_user_func($method, $error);
326
		}
327
	}
328
329
330
	/**
331
	 * @param array $method
332
	 */
333
	public function onNewIndexResult($method) {
334
		$this->methodOnIndexResult[] = $method;
335
	}
336
337
338
	/**
339
	 * @param Index $index
340
	 * @param string $message
341
	 * @param string $status
342
	 * @param int $type
343
	 */
344
	public function newIndexResult($index, $message, $status, $type) {
345
		$result = [
346
			'index'   => $index,
347
			'message' => $message,
348
			'status'  => $status,
349
			'type'    => $type
350
		];
351
352
		foreach ($this->methodOnIndexResult as $method) {
353
			call_user_func($method, $result);
354
		}
355
	}
356
357
358
//	/**
359
//	 * @throws InterruptException
360
//	 */
361
//	private function hasBeenInterrupted() {
362
//		if ($this->commandBase === null) {
363
//			return;
364
//		}
365
//		$this->commandBase->hasBeenInterrupted();
366
//	}
367
368
369
	/**
370
	 * @param $tick
371
	 */
372
	private function updateTick($tick) {
373
		if (($this->ramTick + self::MEMORY_INFO_UPDATE) > $tick) {
374
			return;
375
		}
376
377
		$this->setInfo('_memory', round((memory_get_usage() / 1024 / 1024)) . ' MB');
378
		$this->ramTick = $tick;
379
	}
380
381
382
	/**
383
	 * @deprecated - verifier l'interet !?
384
	 *
385
	 * @param $reason
386
	 * @param $stop
387
	 */
388
	public function exception($reason, $stop) {
389
		if (!$stop) {
390
			$this->output('Exception: ' . $reason);
391
			// TODO: feed an array of exceptions for log;
392
		}
393
		$this->runningService->exception($this->tickId, $reason, $stop);
0 ignored issues
show
Deprecated Code introduced by
The method OCA\FullTextSearch\Servi...ingService::exception() has been deprecated with message: - verifier l'interet !

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
394
	}
395
396
397
	/**
398
	 * @throws TickDoesNotExistException
399
	 */
400
	public function stop() {
401
		$this->runningService->stop($this->tickId);
402
	}
403
404
405
	/**
406
	 * @param ExtendedBase $base
407
	 * @param OutputInterface $output
408
	 */
409
	public function sourceIsCommandLine(ExtendedBase $base, OutputInterface $output) {
410
		$this->outputInterface = $output;
411
		$this->commandBase = $base;
412
	}
413
414
415
	/**
416
	 * @param bool $pause
417
	 */
418
	public function pause($pause) {
419
		$this->paused = $pause;
420
		$this->infoUpdated();
421
	}
422
423
	/**
424
	 * @return bool
425
	 */
426
	public function isPaused() {
427
		return $this->paused;
428
	}
429
430
431
	/**
432
	 * @param bool $running
433
	 */
434
	public function pauseRunning($running) {
435
		$this->pauseRunning = $running;
436
		$this->infoUpdated();
437
	}
438
439
440
	public function isPauseRunning() {
441
		return $this->pauseRunning;
442
	}
443
444
445
//	/**
446
//	 * @return bool
447
//	 */
448
//	public function isStrict() {
449
//		return $this->strict;
450
//	}
451
452
	/**
453
	 * @param string $line
454
	 */
455
	public function output($line) {
456
		if ($this->outputInterface === null) {
457
			return;
458
		}
459
460
		$this->outputInterface->writeln($line);
461
	}
462
463
464
}