Skip to content

Commit

Permalink
remove chunks and parts at the end of process
Browse files Browse the repository at this point in the history
  • Loading branch information
ArtificialOwl committed Oct 20, 2021
1 parent a456fbe commit 6afd3c6
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 17 deletions.
37 changes: 37 additions & 0 deletions lib/Exceptions/RestoringPointLockException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);


/**
* Nextcloud - Backup now. Restore later.
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2021, Maxence Lange <maxence@artificial-owl.com>
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/


namespace OCA\Backup\Exceptions;

use Exception;

class RestoringPointLockException extends Exception {
}
2 changes: 1 addition & 1 deletion lib/Model/RestoringPoint.php
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ public function getLock(): int {
* @return bool
*/
public function isLocked(): bool {
return ($this->getLock() < (time() - self::LOCK_TIMEOUT));
return ($this->getLock() > (time() - self::LOCK_TIMEOUT));
}


Expand Down
15 changes: 15 additions & 0 deletions lib/Service/ChunkService.php
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,7 @@ private function generateChunk(

if ($zipSize > 0 && ($zipSize + $fileSize) > $chunkSize) {
$this->finalizeZip($zip, $chunk->setCount()->setSize($zipSize));
$this->finalizeChunk($point, $chunk);
array_unshift($files, $filename);

return $chunk;
Expand All @@ -447,6 +448,7 @@ private function generateChunk(
}

$this->finalizeZip($zip, $chunk->setCount()->setSize($zipSize));
$this->finalizeChunk($point, $chunk);

return $chunk;
}
Expand Down Expand Up @@ -496,6 +498,19 @@ public function finalizeZip(ZipStreamer $zip, RestoringChunk $archive): void {
}


/**
* @param RestoringPoint $point
* @param RestoringChunk $chunk
*/
private function finalizeChunk(RestoringPoint $point, RestoringChunk $chunk) {
try {
$folder = $this->getChunkFolder($point, $chunk);
$folder->newFile('.backup.' . $chunk->getName() . '.json', json_encode($chunk->getResume(), JSON_PRETTY_PRINT));
} catch (Exception $e) {
}
}


/**
* @param RestoringPoint $point
* @param RestoringChunk $chunk
Expand Down
5 changes: 3 additions & 2 deletions lib/Service/MetadataService.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@

use OCA\Backup\Db\PointRequest;
use OCA\Backup\Exceptions\RestoringPointException;
use OCA\Backup\Exceptions\RestoringPointLockException;
use OCA\Backup\Exceptions\RestoringPointNotFoundException;
use OCA\Backup\Model\RestoringPoint;
use OCP\Files\NotFoundException;
Expand Down Expand Up @@ -133,7 +134,7 @@ public function unlock(RestoringPoint $point): void {
/**
* @param RestoringPoint $point
*
* @throws RestoringPointException
* @throws RestoringPointLockException
*/
public function isLock(RestoringPoint $point): void {
try {
Expand All @@ -145,7 +146,7 @@ public function isLock(RestoringPoint $point): void {
$point->setLock($stored->getLock());

if ($point->isLocked()) {
throw new RestoringPointException('point is locked');
throw new RestoringPointLockException('point is locked');
}
}

Expand Down
72 changes: 58 additions & 14 deletions lib/Service/PackService.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
use OCA\Backup\Exceptions\EncryptionKeyException;
use OCA\Backup\Exceptions\RestoringChunkNotFoundException;
use OCA\Backup\Exceptions\RestoringChunkPartNotFoundException;
use OCA\Backup\Exceptions\RestoringPointException;
use OCA\Backup\Exceptions\RestoringPointLockException;
use OCA\Backup\Exceptions\RestoringPointNotInitiatedException;
use OCA\Backup\Exceptions\RestoringPointPackException;
use OCA\Backup\Model\RestoringChunk;
Expand Down Expand Up @@ -127,20 +127,23 @@ public function __construct(
* @param bool $force
*
* @throws RestoringPointPackException
* @throws RestoringPointLockException
*/
public function packPoint(RestoringPoint $point, bool $force = false): void {
if ($point->isStatus(RestoringPoint::STATUS_PACKED)) {
throw new RestoringPointPackException('restoring point is already packed');
}

$this->metadataService->isLock($point);
$this->metadataService->lock($point);

if ($point->isStatus(RestoringPoint::STATUS_ISSUE)) {
if (!$force && $point->getNotes()->gInt('pack_date') > time() - 3600 * 6) {
throw new RestoringPointPackException('restoring point already failed few hours ago');
}
}

$oldChunks = [];
foreach ($point->getRestoringData() as $data) {
foreach ($data->getChunks() as $chunk) {
try {
Expand All @@ -149,6 +152,7 @@ public function packPoint(RestoringPoint $point, bool $force = false): void {
$chunkPart->setChecksum($this->chunkService->getChecksum($point, $chunk));
$chunk->addPart($chunkPart);
} else {
$oldChunks[] = clone $chunk;
$this->packChunk($point, $chunk);
}
} catch (Throwable $t) {
Expand All @@ -165,6 +169,8 @@ public function packPoint(RestoringPoint $point, bool $force = false): void {
}
}

$this->removeOldChunkFiles($point, $oldChunks);

$point->addStatus(RestoringPoint::STATUS_PACKED)
->getNotes()
->u('pack_error')
Expand All @@ -187,6 +193,8 @@ public function packPoint(RestoringPoint $point, bool $force = false): void {
]
);
}

$this->metadataService->unlock($point);
}


Expand All @@ -207,8 +215,6 @@ public function packChunk(RestoringPoint $point, RestoringChunk $chunk): void {
$parts = $this->wrapPackExplode($temp);
$parts = $this->wrapPackEncrypt($point, $parts);
$this->wrapStoreParts($point, $chunk, $parts);

$this->chunkService->removeChunkFile($point, $chunk);
}


Expand Down Expand Up @@ -434,7 +440,10 @@ private function wrapStoreParts(RestoringPoint $point, RestoringChunk $chunk, ar
}

foreach ($parts as $item) {
unlink($item->getName());
try {
unlink($item->getName());
} catch (Throwable $t) {
}
}
}

Expand All @@ -448,7 +457,8 @@ private function wrapStoreParts(RestoringPoint $point, RestoringChunk $chunk, ar
*/
private function storeParts(RestoringPoint $point, RestoringChunk $chunk, array $parts): void {
$folder = $this->getPackFolder($point, $chunk);
foreach ($parts as $item) {
foreach ($parts as $temp) {
$item = clone $temp;
$prefix = str_pad((string)$item->getOrder(), 5, '0', STR_PAD_LEFT) . '-';
$filename = $prefix . $this->token();
$file = $folder->newFile($filename);
Expand Down Expand Up @@ -586,29 +596,43 @@ public function unpackPoint(RestoringPoint $point): void {
throw new RestoringPointPackException('restoring point is not packed');
}

$this->metadataService->isLock($point);
$this->metadataService->lock($point);

$oldChunks = [];
foreach ($point->getRestoringData() as $data) {
if ($data->getType() === RestoringData::INTERNAL_DATA) {
continue;
}

foreach ($data->getChunks() as $chunk) {
$oldChunks[] = clone $chunk;
$this->unpackChunk($point, $chunk);
}
}

$this->removeOldChunkPartFiles($point, $oldChunks);
$point->setStatus(RestoringPoint::STATUS_UNPACKED)
->unsetNotes();

$this->remoteStreamService->signPoint($point);
$this->pointRequest->update($point, true);
$this->metadataService->saveMetadata($point);

$this->metadataService->unlock($point);
}


/**
* @param RestoringPoint $point
* @param RestoringChunk $chunk
*
* @return void
* @throws ArchiveNotFoundException
* @throws EncryptionKeyException
* @throws NotPermittedException
* @throws RestoringPointNotInitiatedException
* @throws SodiumException
* @throws Throwable
*/
public function unpackChunk(RestoringPoint $point, RestoringChunk $chunk): void {
Expand All @@ -618,8 +642,11 @@ public function unpackChunk(RestoringPoint $point, RestoringChunk $chunk): void
$temp = $this->wrapPackChunkExtract($point, $temp);
$this->wrapRecreateChunk($point, $chunk, $temp);

$this->removeChunkPartFiles($point, $chunk);
// $parts = $chunk->getParts();
$chunk->setParts([]);

// $this->removeChunkPartFiles($point, $chunk);
// return $parts;
}


Expand Down Expand Up @@ -830,7 +857,8 @@ public function getPackFolder(

$folder = $point->getBaseFolder();
if ($chunk->getPath() !== '') {
$path = '/' . $folder->getName() . '/' . $chunk->getPath() . '/' . $chunk->getName();
$path = '/' . $folder->getName() . '/' . $chunk->getPath();
// $path = '/' . $folder->getName() . '/' . $chunk->getPath() . '/' . $chunk->getName();
$root = $point->getRootFolder();
try {
$folder = $root->getFolder($path);
Expand Down Expand Up @@ -891,18 +919,34 @@ private function recreateChunk(RestoringPoint $point, RestoringChunk $chunk, str

/**
* @param RestoringPoint $point
* @param RestoringChunk $chunk
* @param RestoringChunk[] $chunks
*
* @throws NotPermittedException
* @throws RestoringPointNotInitiatedException
*/
private function removeChunkPartFiles(RestoringPoint $point, RestoringChunk $chunk): void {
$folder = $this->getPackFolder($point, $chunk);
foreach ($chunk->getParts() as $part) {
private function removeOldChunkPartFiles(RestoringPoint $point, array $chunks): void {
foreach ($chunks as $chunk) {
$folder = $this->getPackFolder($point, $chunk);
foreach ($chunk->getParts() as $part) {
try {
$file = $folder->getFile($part->getName());
$file->delete();
} catch (Exception $e) {
}
}
}
}


/**
* @param RestoringPoint $point
* @param RestoringChunk[] $chunks
*/
private function removeOldChunkFiles(RestoringPoint $point, array $chunks): void {
foreach ($chunks as $chunk) {
try {
$file = $folder->getFile($part->getName());
$file->delete();
} catch (NotFoundException $e) {
$this->chunkService->removeChunkFile($point, $chunk);
} catch (Exception $e) {
continue;
}
}
Expand Down
2 changes: 2 additions & 0 deletions lib/Service/PointService.php
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,8 @@ public function initBaseFolder(RestoringPoint $point): void {
$folder = $this->appData->getFolder('/' . $point->getId());
}

$folder->newFile(PointService::NOBACKUP_FILE, '');

$point->setRootFolder($this->appData);
$point->setBaseFolder($folder);
}
Expand Down

0 comments on commit 6afd3c6

Please sign in to comment.