Passed
Push — master ( bd9af4...c364b0 )
by Roeland
56:00 queued 44:23
created
core/Command/Preview/Repair.php 2 patches
Indentation   +244 added lines, -244 removed lines patch added patch discarded remove patch
@@ -43,248 +43,248 @@
 block discarded – undo
43 43
 use Symfony\Component\Console\Question\ConfirmationQuestion;
44 44
 
45 45
 class Repair extends Command {
46
-	/** @var IConfig */
47
-	protected $config;
48
-	/** @var IRootFolder */
49
-	private $rootFolder;
50
-	/** @var ILogger */
51
-	private $logger;
52
-
53
-	/** @var bool */
54
-	private $stopSignalReceived = false;
55
-	/** @var int */
56
-	private $memoryLimit;
57
-	/** @var int */
58
-	private $memoryTreshold;
59
-	/** @var ILockingProvider */
60
-	private $lockingProvider;
61
-
62
-	public function __construct(IConfig $config, IRootFolder $rootFolder, ILogger $logger, IniGetWrapper $phpIni, ILockingProvider $lockingProvider) {
63
-		$this->config = $config;
64
-		$this->rootFolder = $rootFolder;
65
-		$this->logger = $logger;
66
-		$this->lockingProvider = $lockingProvider;
67
-
68
-		$this->memoryLimit = $phpIni->getBytes('memory_limit');
69
-		$this->memoryTreshold = $this->memoryLimit - 25 * 1024 * 1024;
70
-
71
-		parent::__construct();
72
-	}
73
-
74
-	protected function configure() {
75
-		$this
76
-			->setName('preview:repair')
77
-			->setDescription('distributes the existing previews into subfolders')
78
-			->addOption('batch', 'b', InputOption::VALUE_NONE, 'Batch mode - will not ask to start the migration and start it right away.')
79
-			->addOption('dry', 'd', InputOption::VALUE_NONE, 'Dry mode - will not create, move or delete any files - in combination with the verbose mode one could check the operations.');
80
-	}
81
-
82
-	protected function execute(InputInterface $input, OutputInterface $output): int {
83
-		if ($this->memoryLimit !== -1) {
84
-			$limitInMiB = round($this->memoryLimit / 1024 /1024, 1);
85
-			$thresholdInMiB = round($this->memoryTreshold / 1024 /1024, 1);
86
-			$output->writeln("Memory limit is $limitInMiB MiB");
87
-			$output->writeln("Memory threshold is $thresholdInMiB MiB");
88
-			$output->writeln("");
89
-			$memoryCheckEnabled = true;
90
-		} else {
91
-			$output->writeln("No memory limit in place - disabled memory check. Set a PHP memory limit to automatically stop the execution of this migration script once memory consumption is close to this limit.");
92
-			$output->writeln("");
93
-			$memoryCheckEnabled = false;
94
-		}
95
-
96
-		$dryMode = $input->getOption('dry');
97
-
98
-		if ($dryMode) {
99
-			$output->writeln("INFO: The migration is run in dry mode and will not modify anything.");
100
-			$output->writeln("");
101
-		}
102
-
103
-		$instanceId = $this->config->getSystemValueString('instanceid');
104
-
105
-		$output->writeln("This will migrate all previews from the old preview location to the new one.");
106
-		$output->writeln('');
107
-
108
-		$output->writeln('Fetching previews that need to be migrated …');
109
-		/** @var \OCP\Files\Folder $currentPreviewFolder */
110
-		$currentPreviewFolder = $this->rootFolder->get("appdata_$instanceId/preview");
111
-
112
-		$directoryListing = $currentPreviewFolder->getDirectoryListing();
113
-
114
-		$total = count($directoryListing);
115
-		/**
116
-		 * by default there could be 0-9 a-f and the old-multibucket folder which are all fine
117
-		 */
118
-		if ($total < 18) {
119
-			$directoryListing = array_filter($directoryListing, function ($dir) {
120
-				if ($dir->getName() === 'old-multibucket') {
121
-					return false;
122
-				}
123
-
124
-				// a-f can't be a file ID -> removing from migration
125
-				if (preg_match('!^[a-f]$!', $dir->getName())) {
126
-					return false;
127
-				}
128
-
129
-				if (preg_match('!^[0-9]$!', $dir->getName())) {
130
-					// ignore folders that only has folders in them
131
-					if ($dir instanceof Folder) {
132
-						foreach ($dir->getDirectoryListing() as $entry) {
133
-							if (!$entry instanceof Folder) {
134
-								return true;
135
-							}
136
-						}
137
-						return false;
138
-					}
139
-				}
140
-				return true;
141
-			});
142
-			$total = count($directoryListing);
143
-		}
144
-
145
-		if ($total === 0) {
146
-			$output->writeln("All previews are already migrated.");
147
-			return 0;
148
-		}
149
-
150
-		$output->writeln("A total of $total preview files need to be migrated.");
151
-		$output->writeln("");
152
-		$output->writeln("The migration will always migrate all previews of a single file in a batch. After each batch the process can be canceled by pressing CTRL-C. This fill finish the current batch and then stop the migration. This migration can then just be started and it will continue.");
153
-
154
-		if ($input->getOption('batch')) {
155
-			$output->writeln('Batch mode active: migration is started right away.');
156
-		} else {
157
-			$helper = $this->getHelper('question');
158
-			$question = new ConfirmationQuestion('<info>Should the migration be started? (y/[n]) </info>', false);
159
-
160
-			if (!$helper->ask($input, $output, $question)) {
161
-				return 0;
162
-			}
163
-		}
164
-
165
-		// register the SIGINT listener late in here to be able to exit in the early process of this command
166
-		pcntl_signal(SIGINT, [$this, 'sigIntHandler']);
167
-
168
-		$output->writeln("");
169
-		$output->writeln("");
170
-		$section1 = $output->section();
171
-		$section2 = $output->section();
172
-		$progressBar = new ProgressBar($section2, $total);
173
-		$progressBar->setFormat("%current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% Used Memory: %memory:6s%");
174
-		$time = (new \DateTime())->format('H:i:s');
175
-		$progressBar->setMessage("$time Starting …");
176
-		$progressBar->maxSecondsBetweenRedraws(0.2);
177
-		$progressBar->start();
178
-
179
-		foreach ($directoryListing as $oldPreviewFolder) {
180
-			pcntl_signal_dispatch();
181
-			$name = $oldPreviewFolder->getName();
182
-			$time = (new \DateTime())->format('H:i:s');
183
-			$section1->writeln("$time Migrating previews of file with fileId $name …");
184
-			$progressBar->display();
185
-
186
-			if ($this->stopSignalReceived) {
187
-				$section1->writeln("$time Stopping migration …");
188
-				return 0;
189
-			}
190
-			if (!$oldPreviewFolder instanceof Folder) {
191
-				$section1->writeln("         Skipping non-folder $name …");
192
-				$progressBar->advance();
193
-				continue;
194
-			}
195
-			if ($name === 'old-multibucket') {
196
-				$section1->writeln("         Skipping fallback mount point $name …");
197
-				$progressBar->advance();
198
-				continue;
199
-			}
200
-			if (in_array($name, ['a', 'b', 'c', 'd', 'e', 'f'])) {
201
-				$section1->writeln("         Skipping hex-digit folder $name …");
202
-				$progressBar->advance();
203
-				continue;
204
-			}
205
-			if (!preg_match('!^\d+$!', $name)) {
206
-				$section1->writeln("         Skipping non-numeric folder $name …");
207
-				$progressBar->advance();
208
-				continue;
209
-			}
210
-
211
-			$newFoldername = Root::getInternalFolder($name);
212
-
213
-			$memoryUsage = memory_get_usage();
214
-			if ($memoryCheckEnabled && $memoryUsage > $this->memoryTreshold) {
215
-				$section1->writeln("");
216
-				$section1->writeln("");
217
-				$section1->writeln("");
218
-				$section1->writeln("         Stopped process 25 MB before reaching the memory limit to avoid a hard crash.");
219
-				$time = (new \DateTime())->format('H:i:s');
220
-				$section1->writeln("$time Reached memory limit and stopped to avoid hard crash.");
221
-				return 1;
222
-			}
223
-
224
-			$lockName = 'occ preview:repair lock ' . $oldPreviewFolder->getId();
225
-			try {
226
-				$section1->writeln("         Locking \"$lockName\" …", OutputInterface::VERBOSITY_VERBOSE);
227
-				$this->lockingProvider->acquireLock($lockName, ILockingProvider::LOCK_EXCLUSIVE);
228
-			} catch (LockedException $e) {
229
-				$section1->writeln("         Skipping because it is locked - another process seems to work on this …");
230
-				continue;
231
-			}
232
-
233
-			$previews = $oldPreviewFolder->getDirectoryListing();
234
-			if ($previews !== []) {
235
-				try {
236
-					$this->rootFolder->get("appdata_$instanceId/preview/$newFoldername");
237
-				} catch (NotFoundException $e) {
238
-					$section1->writeln("         Create folder preview/$newFoldername", OutputInterface::VERBOSITY_VERBOSE);
239
-					if (!$dryMode) {
240
-						$this->rootFolder->newFolder("appdata_$instanceId/preview/$newFoldername");
241
-					}
242
-				}
243
-
244
-				foreach ($previews as $preview) {
245
-					pcntl_signal_dispatch();
246
-					$previewName = $preview->getName();
247
-
248
-					if ($preview instanceof Folder) {
249
-						$section1->writeln("         Skipping folder $name/$previewName …");
250
-						$progressBar->advance();
251
-						continue;
252
-					}
253
-					$section1->writeln("         Move preview/$name/$previewName to preview/$newFoldername", OutputInterface::VERBOSITY_VERBOSE);
254
-					if (!$dryMode) {
255
-						try {
256
-							$preview->move("appdata_$instanceId/preview/$newFoldername/$previewName");
257
-						} catch (\Exception $e) {
258
-							$this->logger->logException($e, ['app' => 'core', 'message' => "Failed to move preview from preview/$name/$previewName to preview/$newFoldername"]);
259
-						}
260
-					}
261
-				}
262
-			}
263
-			if ($oldPreviewFolder->getDirectoryListing() === []) {
264
-				$section1->writeln("         Delete empty folder preview/$name", OutputInterface::VERBOSITY_VERBOSE);
265
-				if (!$dryMode) {
266
-					try {
267
-						$oldPreviewFolder->delete();
268
-					} catch (\Exception $e) {
269
-						$this->logger->logException($e, ['app' => 'core', 'message' => "Failed to delete empty folder preview/$name"]);
270
-					}
271
-				}
272
-			}
273
-
274
-			$this->lockingProvider->releaseLock($lockName, ILockingProvider::LOCK_EXCLUSIVE);
275
-			$section1->writeln("         Unlocked", OutputInterface::VERBOSITY_VERBOSE);
276
-
277
-			$section1->writeln("         Finished migrating previews of file with fileId $name …");
278
-			$progressBar->advance();
279
-		}
280
-
281
-		$progressBar->finish();
282
-		$output->writeln("");
283
-		return 0;
284
-	}
285
-
286
-	protected function sigIntHandler() {
287
-		echo "\nSignal received - will finish the step and then stop the migration.\n\n\n";
288
-		$this->stopSignalReceived = true;
289
-	}
46
+    /** @var IConfig */
47
+    protected $config;
48
+    /** @var IRootFolder */
49
+    private $rootFolder;
50
+    /** @var ILogger */
51
+    private $logger;
52
+
53
+    /** @var bool */
54
+    private $stopSignalReceived = false;
55
+    /** @var int */
56
+    private $memoryLimit;
57
+    /** @var int */
58
+    private $memoryTreshold;
59
+    /** @var ILockingProvider */
60
+    private $lockingProvider;
61
+
62
+    public function __construct(IConfig $config, IRootFolder $rootFolder, ILogger $logger, IniGetWrapper $phpIni, ILockingProvider $lockingProvider) {
63
+        $this->config = $config;
64
+        $this->rootFolder = $rootFolder;
65
+        $this->logger = $logger;
66
+        $this->lockingProvider = $lockingProvider;
67
+
68
+        $this->memoryLimit = $phpIni->getBytes('memory_limit');
69
+        $this->memoryTreshold = $this->memoryLimit - 25 * 1024 * 1024;
70
+
71
+        parent::__construct();
72
+    }
73
+
74
+    protected function configure() {
75
+        $this
76
+            ->setName('preview:repair')
77
+            ->setDescription('distributes the existing previews into subfolders')
78
+            ->addOption('batch', 'b', InputOption::VALUE_NONE, 'Batch mode - will not ask to start the migration and start it right away.')
79
+            ->addOption('dry', 'd', InputOption::VALUE_NONE, 'Dry mode - will not create, move or delete any files - in combination with the verbose mode one could check the operations.');
80
+    }
81
+
82
+    protected function execute(InputInterface $input, OutputInterface $output): int {
83
+        if ($this->memoryLimit !== -1) {
84
+            $limitInMiB = round($this->memoryLimit / 1024 /1024, 1);
85
+            $thresholdInMiB = round($this->memoryTreshold / 1024 /1024, 1);
86
+            $output->writeln("Memory limit is $limitInMiB MiB");
87
+            $output->writeln("Memory threshold is $thresholdInMiB MiB");
88
+            $output->writeln("");
89
+            $memoryCheckEnabled = true;
90
+        } else {
91
+            $output->writeln("No memory limit in place - disabled memory check. Set a PHP memory limit to automatically stop the execution of this migration script once memory consumption is close to this limit.");
92
+            $output->writeln("");
93
+            $memoryCheckEnabled = false;
94
+        }
95
+
96
+        $dryMode = $input->getOption('dry');
97
+
98
+        if ($dryMode) {
99
+            $output->writeln("INFO: The migration is run in dry mode and will not modify anything.");
100
+            $output->writeln("");
101
+        }
102
+
103
+        $instanceId = $this->config->getSystemValueString('instanceid');
104
+
105
+        $output->writeln("This will migrate all previews from the old preview location to the new one.");
106
+        $output->writeln('');
107
+
108
+        $output->writeln('Fetching previews that need to be migrated …');
109
+        /** @var \OCP\Files\Folder $currentPreviewFolder */
110
+        $currentPreviewFolder = $this->rootFolder->get("appdata_$instanceId/preview");
111
+
112
+        $directoryListing = $currentPreviewFolder->getDirectoryListing();
113
+
114
+        $total = count($directoryListing);
115
+        /**
116
+         * by default there could be 0-9 a-f and the old-multibucket folder which are all fine
117
+         */
118
+        if ($total < 18) {
119
+            $directoryListing = array_filter($directoryListing, function ($dir) {
120
+                if ($dir->getName() === 'old-multibucket') {
121
+                    return false;
122
+                }
123
+
124
+                // a-f can't be a file ID -> removing from migration
125
+                if (preg_match('!^[a-f]$!', $dir->getName())) {
126
+                    return false;
127
+                }
128
+
129
+                if (preg_match('!^[0-9]$!', $dir->getName())) {
130
+                    // ignore folders that only has folders in them
131
+                    if ($dir instanceof Folder) {
132
+                        foreach ($dir->getDirectoryListing() as $entry) {
133
+                            if (!$entry instanceof Folder) {
134
+                                return true;
135
+                            }
136
+                        }
137
+                        return false;
138
+                    }
139
+                }
140
+                return true;
141
+            });
142
+            $total = count($directoryListing);
143
+        }
144
+
145
+        if ($total === 0) {
146
+            $output->writeln("All previews are already migrated.");
147
+            return 0;
148
+        }
149
+
150
+        $output->writeln("A total of $total preview files need to be migrated.");
151
+        $output->writeln("");
152
+        $output->writeln("The migration will always migrate all previews of a single file in a batch. After each batch the process can be canceled by pressing CTRL-C. This fill finish the current batch and then stop the migration. This migration can then just be started and it will continue.");
153
+
154
+        if ($input->getOption('batch')) {
155
+            $output->writeln('Batch mode active: migration is started right away.');
156
+        } else {
157
+            $helper = $this->getHelper('question');
158
+            $question = new ConfirmationQuestion('<info>Should the migration be started? (y/[n]) </info>', false);
159
+
160
+            if (!$helper->ask($input, $output, $question)) {
161
+                return 0;
162
+            }
163
+        }
164
+
165
+        // register the SIGINT listener late in here to be able to exit in the early process of this command
166
+        pcntl_signal(SIGINT, [$this, 'sigIntHandler']);
167
+
168
+        $output->writeln("");
169
+        $output->writeln("");
170
+        $section1 = $output->section();
171
+        $section2 = $output->section();
172
+        $progressBar = new ProgressBar($section2, $total);
173
+        $progressBar->setFormat("%current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% Used Memory: %memory:6s%");
174
+        $time = (new \DateTime())->format('H:i:s');
175
+        $progressBar->setMessage("$time Starting …");
176
+        $progressBar->maxSecondsBetweenRedraws(0.2);
177
+        $progressBar->start();
178
+
179
+        foreach ($directoryListing as $oldPreviewFolder) {
180
+            pcntl_signal_dispatch();
181
+            $name = $oldPreviewFolder->getName();
182
+            $time = (new \DateTime())->format('H:i:s');
183
+            $section1->writeln("$time Migrating previews of file with fileId $name …");
184
+            $progressBar->display();
185
+
186
+            if ($this->stopSignalReceived) {
187
+                $section1->writeln("$time Stopping migration …");
188
+                return 0;
189
+            }
190
+            if (!$oldPreviewFolder instanceof Folder) {
191
+                $section1->writeln("         Skipping non-folder $name …");
192
+                $progressBar->advance();
193
+                continue;
194
+            }
195
+            if ($name === 'old-multibucket') {
196
+                $section1->writeln("         Skipping fallback mount point $name …");
197
+                $progressBar->advance();
198
+                continue;
199
+            }
200
+            if (in_array($name, ['a', 'b', 'c', 'd', 'e', 'f'])) {
201
+                $section1->writeln("         Skipping hex-digit folder $name …");
202
+                $progressBar->advance();
203
+                continue;
204
+            }
205
+            if (!preg_match('!^\d+$!', $name)) {
206
+                $section1->writeln("         Skipping non-numeric folder $name …");
207
+                $progressBar->advance();
208
+                continue;
209
+            }
210
+
211
+            $newFoldername = Root::getInternalFolder($name);
212
+
213
+            $memoryUsage = memory_get_usage();
214
+            if ($memoryCheckEnabled && $memoryUsage > $this->memoryTreshold) {
215
+                $section1->writeln("");
216
+                $section1->writeln("");
217
+                $section1->writeln("");
218
+                $section1->writeln("         Stopped process 25 MB before reaching the memory limit to avoid a hard crash.");
219
+                $time = (new \DateTime())->format('H:i:s');
220
+                $section1->writeln("$time Reached memory limit and stopped to avoid hard crash.");
221
+                return 1;
222
+            }
223
+
224
+            $lockName = 'occ preview:repair lock ' . $oldPreviewFolder->getId();
225
+            try {
226
+                $section1->writeln("         Locking \"$lockName\" …", OutputInterface::VERBOSITY_VERBOSE);
227
+                $this->lockingProvider->acquireLock($lockName, ILockingProvider::LOCK_EXCLUSIVE);
228
+            } catch (LockedException $e) {
229
+                $section1->writeln("         Skipping because it is locked - another process seems to work on this …");
230
+                continue;
231
+            }
232
+
233
+            $previews = $oldPreviewFolder->getDirectoryListing();
234
+            if ($previews !== []) {
235
+                try {
236
+                    $this->rootFolder->get("appdata_$instanceId/preview/$newFoldername");
237
+                } catch (NotFoundException $e) {
238
+                    $section1->writeln("         Create folder preview/$newFoldername", OutputInterface::VERBOSITY_VERBOSE);
239
+                    if (!$dryMode) {
240
+                        $this->rootFolder->newFolder("appdata_$instanceId/preview/$newFoldername");
241
+                    }
242
+                }
243
+
244
+                foreach ($previews as $preview) {
245
+                    pcntl_signal_dispatch();
246
+                    $previewName = $preview->getName();
247
+
248
+                    if ($preview instanceof Folder) {
249
+                        $section1->writeln("         Skipping folder $name/$previewName …");
250
+                        $progressBar->advance();
251
+                        continue;
252
+                    }
253
+                    $section1->writeln("         Move preview/$name/$previewName to preview/$newFoldername", OutputInterface::VERBOSITY_VERBOSE);
254
+                    if (!$dryMode) {
255
+                        try {
256
+                            $preview->move("appdata_$instanceId/preview/$newFoldername/$previewName");
257
+                        } catch (\Exception $e) {
258
+                            $this->logger->logException($e, ['app' => 'core', 'message' => "Failed to move preview from preview/$name/$previewName to preview/$newFoldername"]);
259
+                        }
260
+                    }
261
+                }
262
+            }
263
+            if ($oldPreviewFolder->getDirectoryListing() === []) {
264
+                $section1->writeln("         Delete empty folder preview/$name", OutputInterface::VERBOSITY_VERBOSE);
265
+                if (!$dryMode) {
266
+                    try {
267
+                        $oldPreviewFolder->delete();
268
+                    } catch (\Exception $e) {
269
+                        $this->logger->logException($e, ['app' => 'core', 'message' => "Failed to delete empty folder preview/$name"]);
270
+                    }
271
+                }
272
+            }
273
+
274
+            $this->lockingProvider->releaseLock($lockName, ILockingProvider::LOCK_EXCLUSIVE);
275
+            $section1->writeln("         Unlocked", OutputInterface::VERBOSITY_VERBOSE);
276
+
277
+            $section1->writeln("         Finished migrating previews of file with fileId $name …");
278
+            $progressBar->advance();
279
+        }
280
+
281
+        $progressBar->finish();
282
+        $output->writeln("");
283
+        return 0;
284
+    }
285
+
286
+    protected function sigIntHandler() {
287
+        echo "\nSignal received - will finish the step and then stop the migration.\n\n\n";
288
+        $this->stopSignalReceived = true;
289
+    }
290 290
 }
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -81,8 +81,8 @@  discard block
 block discarded – undo
81 81
 
82 82
 	protected function execute(InputInterface $input, OutputInterface $output): int {
83 83
 		if ($this->memoryLimit !== -1) {
84
-			$limitInMiB = round($this->memoryLimit / 1024 /1024, 1);
85
-			$thresholdInMiB = round($this->memoryTreshold / 1024 /1024, 1);
84
+			$limitInMiB = round($this->memoryLimit / 1024 / 1024, 1);
85
+			$thresholdInMiB = round($this->memoryTreshold / 1024 / 1024, 1);
86 86
 			$output->writeln("Memory limit is $limitInMiB MiB");
87 87
 			$output->writeln("Memory threshold is $thresholdInMiB MiB");
88 88
 			$output->writeln("");
@@ -116,7 +116,7 @@  discard block
 block discarded – undo
116 116
 		 * by default there could be 0-9 a-f and the old-multibucket folder which are all fine
117 117
 		 */
118 118
 		if ($total < 18) {
119
-			$directoryListing = array_filter($directoryListing, function ($dir) {
119
+			$directoryListing = array_filter($directoryListing, function($dir) {
120 120
 				if ($dir->getName() === 'old-multibucket') {
121 121
 					return false;
122 122
 				}
@@ -221,7 +221,7 @@  discard block
 block discarded – undo
221 221
 				return 1;
222 222
 			}
223 223
 
224
-			$lockName = 'occ preview:repair lock ' . $oldPreviewFolder->getId();
224
+			$lockName = 'occ preview:repair lock '.$oldPreviewFolder->getId();
225 225
 			try {
226 226
 				$section1->writeln("         Locking \"$lockName\" …", OutputInterface::VERBOSITY_VERBOSE);
227 227
 				$this->lockingProvider->acquireLock($lockName, ILockingProvider::LOCK_EXCLUSIVE);
Please login to merge, or discard this patch.