111 lines
		
	
	
	
		
			2.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			111 lines
		
	
	
	
		
			2.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
| This file is part of Telegram Desktop,
 | |
| the official desktop application for the Telegram messaging service.
 | |
| 
 | |
| For license and copyright information please follow this link:
 | |
| https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 | |
| */
 | |
| #include "storage/cache/storage_cache_cleaner.h"
 | |
| 
 | |
| #include <crl/crl.h>
 | |
| #include <QtCore/QDir>
 | |
| #include <QtCore/QFile>
 | |
| #include <unordered_map>
 | |
| #include <set>
 | |
| 
 | |
| namespace Storage {
 | |
| namespace Cache {
 | |
| namespace details {
 | |
| 
 | |
| class CleanerObject {
 | |
| public:
 | |
| 	CleanerObject(
 | |
| 		crl::weak_on_queue<CleanerObject> weak,
 | |
| 		const QString &base,
 | |
| 		base::binary_guard &&guard,
 | |
| 		FnMut<void(Error)> done);
 | |
| 
 | |
| private:
 | |
| 	void start();
 | |
| 	void scheduleNext();
 | |
| 	void cleanNext();
 | |
| 	void done();
 | |
| 
 | |
| 	crl::weak_on_queue<CleanerObject> _weak;
 | |
| 	QString _base, _errorPath;
 | |
| 	std::vector<QString> _queue;
 | |
| 	base::binary_guard _guard;
 | |
| 	FnMut<void(Error)> _done;
 | |
| 
 | |
| };
 | |
| 
 | |
| CleanerObject::CleanerObject(
 | |
| 	crl::weak_on_queue<CleanerObject> weak,
 | |
| 	const QString &base,
 | |
| 	base::binary_guard &&guard,
 | |
| 	FnMut<void(Error)> done)
 | |
| : _weak(std::move(weak))
 | |
| , _base(base)
 | |
| , _guard(std::move(guard))
 | |
| , _done(std::move(done)) {
 | |
| 	start();
 | |
| }
 | |
| 
 | |
| void CleanerObject::start() {
 | |
| 	const auto entries = QDir(_base).entryList(
 | |
| 		QDir::Dirs | QDir::NoDotAndDotDot);
 | |
| 	for (const auto entry : entries) {
 | |
| 		_queue.push_back(entry);
 | |
| 	}
 | |
| 	if (const auto version = ReadVersionValue(_base)) {
 | |
| 		_queue.erase(
 | |
| 			ranges::remove(_queue, QString::number(*version)),
 | |
| 			end(_queue));
 | |
| 		scheduleNext();
 | |
| 	} else {
 | |
| 		_errorPath = VersionFilePath(_base);
 | |
| 		done();
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void CleanerObject::scheduleNext() {
 | |
| 	if (_queue.empty()) {
 | |
| 		done();
 | |
| 		return;
 | |
| 	}
 | |
| 	_weak.with([](CleanerObject &that) {
 | |
| 		if (that._guard) {
 | |
| 			that.cleanNext();
 | |
| 		}
 | |
| 	});
 | |
| }
 | |
| 
 | |
| void CleanerObject::cleanNext() {
 | |
| 	const auto path = _base + _queue.back();
 | |
| 	_queue.pop_back();
 | |
| 	if (!QDir(path).removeRecursively()) {
 | |
| 		_errorPath = path;
 | |
| 	}
 | |
| 	scheduleNext();
 | |
| }
 | |
| 
 | |
| void CleanerObject::done() {
 | |
| 	if (_done) {
 | |
| 		_done(_errorPath.isEmpty()
 | |
| 			? Error::NoError()
 | |
| 			: Error{ Error::Type::IO, _errorPath });
 | |
| 	}
 | |
| }
 | |
| 
 | |
| Cleaner::Cleaner(
 | |
| 	const QString &base,
 | |
| 	base::binary_guard &&guard,
 | |
| 	FnMut<void(Error)> done)
 | |
| : _wrapped(base, std::move(guard), std::move(done)) {
 | |
| }
 | |
| 
 | |
| Cleaner::~Cleaner() = default;
 | |
| 
 | |
| } // namespace details
 | |
| } // namespace Cache
 | |
| } // namespace Storage
 | 
