Completed
Push — master ( 70e253...9c6500 )
by Maxence
04:58
created

Runner::updateRamInfo()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
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
	const TICK_TTL = 1800;
41
42
	const TICK_MINIMUM = 2;
43
	const TICK_UPDATE = 10;
44
	const MEMORY_UPDATE = 5;
45
46
	const RESULT_TYPE_SUCCESS = 1;
47
	const RESULT_TYPE_WARNING = 4;
48
	const RESULT_TYPE_FAIL = 9;
49
50
	/** @var RunningService */
51
	private $runningService;
52
53
	/** @var string */
54
	private $source;
55
56
//	/** @var bool */
57
//	private $strict = false;
58
59
	/** @var int */
60
	private $tickId;
61
62
	/** @var ExtendedBase */
63
	private $commandBase = null;
64
65
	/** @var OutputInterface */
66
	private $outputInterface = null;
67
68
	/** @var array */
69
	private $info = [];
70
71
	/** @var int */
72
	private $oldTick = 0;
73
74
	/** @var string */
75
	private $oldAction = '';
76
77
	/** @var int */
78
	private $ramUpdate = 0;
79
80
	/** @var int */
81
	private $tickUpdate = 0;
82
83
	/** @var array */
84
	private $methodOnKeyPress = [];
85
86
	/** @var array */
87
	private $methodOnInfoUpdate = [];
88
89
	/** @var array */
90
	private $methodOnIndexError = [];
91
92
	/** @var array */
93
	private $methodOnIndexResult = [];
94
95
	/** @var bool */
96
	private $paused = false;
97
98
	/** @var bool */
99
	private $pauseRunning = false;
100
101
	/** @var array */
102
	private $keys = ['nextStep' => 'n'];
103
104
105
	/**
106
	 * Runner constructor.
107
	 *
108
	 * @param RunningService $runningService
109
	 * @param string $source
110
	 * @param array $keys
111
	 */
112
	public function __construct(RunningService $runningService, $source, $keys = []) {
113
		$this->runningService = $runningService;
114
		$this->source = $source;
115
116
		if (sizeof($keys) > 0) {
117
			$this->keys = $keys;
118
		}
119
	}
120
121
122
	/**
123
	 * @throws RunnerAlreadyUpException
124
	 */
125
	public function start() {
126
//		$this->strict = $strict;
127
		$this->tickId = $this->runningService->start($this->source);
128
	}
129
130
131
	/**
132
	 * @param string $action
133
	 * @param bool $force
134
	 *
135
	 * @return string
136
	 * @throws \Exception
137
	 */
138
	public function updateAction($action = '', $force = false) {
139
		$n = '';
140
		if (sizeof($this->methodOnKeyPress) > 0) {
141
			$n = fread(STDIN, 9999);
142
			if ($n !== '') {
143
				$n = substr($n, 0, 1);
144
				$this->keyPressed($n);
145
			}
146
		}
147
148
		if ($action === '') {
149
			return $n;
150
		}
151
152
		$tick = time();
153
//		try {
154
//			$this->hasBeenInterrupted();
155
//		} catch (InterruptException $e) {
156
//			$this->stop();
157
//			throw $e;
158
//		}
159
160
		if ($this->oldAction !== $action || $force) {
161
			while (true) {
162
				if (!$this->isPaused()) {
163
					break;
164
				}
165
166
				$this->pauseRunning(true);
167
				$pressed = strtolower($this->updateAction(''));
168
				if ($pressed === $this->keys['nextStep']) {
169
					break;
170
				}
171
				usleep(300000);
172
			}
173
174
			$this->pauseRunning(false);
175
		}
176
177
		if ($this->oldAction === $action && ($this->oldTick + self::TICK_MINIMUM > $tick)) {
178
			return '';
179
		}
180
181
		$this->setInfo('action', $action);
182
183
		$this->updateTick($tick, $action);
184
		$this->updateRamInfo($tick);
185
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
	public function infoUpdated() {
295
		foreach ($this->methodOnInfoUpdate as $method) {
296
			call_user_func($method, $this->info);
297
		}
298
	}
299
300
301
	/**
302
	 * @param array $method
303
	 */
304
	public function onNewIndexError($method) {
305
		$this->methodOnIndexError[] = $method;
306
	}
307
308
	/**
309
	 * @param Index $index
310
	 * @param string $message
311
	 * @param string $class
312
	 * @param int $sev
313
	 */
314
	public function newIndexError($index, $message, $class = '', $sev = 3) {
315
		$error = [
316
			'index'     => $index,
317
			'message'   => $message,
318
			'exception' => $class,
319
			'severity'  => $sev
320
		];
321
322
		foreach ($this->methodOnIndexError as $method) {
323
			call_user_func($method, $error);
324
		}
325
	}
326
327
328
	/**
329
	 * @param array $method
330
	 */
331
	public function onNewIndexResult($method) {
332
		$this->methodOnIndexResult[] = $method;
333
	}
334
335
336
	/**
337
	 * @param Index $index
338
	 * @param string $message
339
	 * @param string $status
340
	 * @param int $type
341
	 */
342
	public function newIndexResult($index, $message, $status, $type) {
343
		$result = [
344
			'index'   => $index,
345
			'message' => $message,
346
			'status'  => $status,
347
			'type'    => $type
348
		];
349
350
		foreach ($this->methodOnIndexResult as $method) {
351
			call_user_func($method, $result);
352
		}
353
	}
354
355
356
//	/**
357
//	 * @throws InterruptException
358
//	 */
359
//	private function hasBeenInterrupted() {
360
//		if ($this->commandBase === null) {
361
//			return;
362
//		}
363
//		$this->commandBase->hasBeenInterrupted();
364
//	}
365
366
367
	/**
368
	 * @param int $tick
369
	 * @param string $action
370
	 *
371
	 * @throws TickDoesNotExistException
372
	 */
373
	private function updateTick($tick, $action) {
374
		if ($this->oldAction === $action && ($this->tickUpdate + self::TICK_UPDATE > $tick)) {
375
			return;
376
		}
377
378
		try {
379
			$this->runningService->update($this->tickId, $action);
380
		} catch (TickIsNotAliveException $e) {
381
			$this->output('Force Quit');
382
			exit();
383
		}
384
385
		$this->tickUpdate = $tick;
386
	}
387
388
389
	/**
390
	 * @param $tick
391
	 */
392
	private function updateRamInfo($tick) {
393
		if (($this->ramUpdate + self::MEMORY_UPDATE) > $tick) {
394
			return;
395
		}
396
397
		$this->setInfo('_memory', round((memory_get_usage() / 1024 / 1024)) . ' MB');
398
		$this->ramUpdate = $tick;
399
	}
400
401
402
	/**
403
	 * @deprecated - verifier l'interet !?
404
	 *
405
	 * @param $reason
406
	 * @param $stop
407
	 */
408
	public function exception($reason, $stop) {
409
		if (!$stop) {
410
			$this->output('Exception: ' . $reason);
411
			// TODO: feed an array of exceptions for log;
412
		}
413
		$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...
414
	}
415
416
417
	/**
418
	 * @throws TickDoesNotExistException
419
	 */
420
	public function stop() {
421
		$this->runningService->stop($this->tickId);
422
	}
423
424
425
	/**
426
	 * @param ExtendedBase $base
427
	 * @param OutputInterface $output
428
	 */
429
	public function sourceIsCommandLine(ExtendedBase $base, OutputInterface $output) {
430
		$this->outputInterface = $output;
431
		$this->commandBase = $base;
432
	}
433
434
435
	/**
436
	 * @param bool $pause
437
	 */
438
	public function pause($pause) {
439
		$this->paused = $pause;
440
		$this->infoUpdated();
441
	}
442
443
	/**
444
	 * @return bool
445
	 */
446
	public function isPaused() {
447
		return $this->paused;
448
	}
449
450
451
	/**
452
	 * @param bool $running
453
	 */
454
	public function pauseRunning($running) {
455
		$this->pauseRunning = $running;
456
		$this->infoUpdated();
457
	}
458
459
460
	public function isPauseRunning() {
461
		return $this->pauseRunning;
462
	}
463
464
465
//	/**
466
//	 * @return bool
467
//	 */
468
//	public function isStrict() {
469
//		return $this->strict;
470
//	}
471
472
	/**
473
	 * @param string $line
474
	 */
475
	public function output($line) {
476
		if ($this->outputInterface === null) {
477
			return;
478
		}
479
480
		$this->outputInterface->writeln($line);
481
	}
482
483
484
}
485