forked from dlang/cdcdb
		
	Сжатие для БД вынесено в параметр
This commit is contained in:
		
							parent
							
								
									8a9142234e
								
							
						
					
					
						commit
						d93dc4d81b
					
				
					 3 changed files with 103 additions and 24 deletions
				
			
		| 
						 | 
				
			
			@ -2,49 +2,87 @@ module cdcdb.snapshot;
 | 
			
		|||
 | 
			
		||||
import cdcdb.dblite;
 | 
			
		||||
 | 
			
		||||
import zstd : uncompress;
 | 
			
		||||
 | 
			
		||||
import std.digest.sha : SHA256, digest, SHA256Digest;
 | 
			
		||||
import std.datetime : DateTime;
 | 
			
		||||
import std.exception : enforce;
 | 
			
		||||
 | 
			
		||||
final class Snapshot {
 | 
			
		||||
final class Snapshot
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
	DBLite _db;
 | 
			
		||||
	DBSnapshot _snapshot;
 | 
			
		||||
public:
 | 
			
		||||
	this(DBLite dblite, DBSnapshot dbSnapshot) {
 | 
			
		||||
	this(DBLite dblite, DBSnapshot dbSnapshot)
 | 
			
		||||
	{
 | 
			
		||||
		_db = dblite;
 | 
			
		||||
		_snapshot = dbSnapshot;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this(DBLite dblite, long idSnapshot) {
 | 
			
		||||
	this(DBLite dblite, long idSnapshot)
 | 
			
		||||
	{
 | 
			
		||||
		_db = dblite;
 | 
			
		||||
		_snapshot = _db.getSnapshot(idSnapshot);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ubyte[] data() {
 | 
			
		||||
		auto dataChunks = _db.getChunks(_snapshot.id);
 | 
			
		||||
	ubyte[] data()
 | 
			
		||||
	{
 | 
			
		||||
		auto chunks = _db.getChunks(_snapshot.id);
 | 
			
		||||
		ubyte[] content;
 | 
			
		||||
 | 
			
		||||
		import zstd : uncompress;
 | 
			
		||||
 | 
			
		||||
		foreach (chunk; dataChunks) {
 | 
			
		||||
		foreach (chunk; chunks)
 | 
			
		||||
		{
 | 
			
		||||
			ubyte[] bytes;
 | 
			
		||||
			if (chunk.zstd) {
 | 
			
		||||
			if (chunk.zstd)
 | 
			
		||||
			{
 | 
			
		||||
				enforce(chunk.zSize == chunk.content.length, "Размер сжатого фрагмента не соответствует ожидаемому");
 | 
			
		||||
				bytes = cast(ubyte[]) uncompress(chunk.content);
 | 
			
		||||
			} else {
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				bytes = chunk.content;
 | 
			
		||||
			}
 | 
			
		||||
			enforce(chunk.size == bytes.length, "Оригинальный размер не соответствует ожидаемому");
 | 
			
		||||
			enforce(chunk.sha256 == digest!SHA256(bytes), "Хеш-сумма фрагмента не совпадает");
 | 
			
		||||
			content ~= bytes;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		import std.digest.sha : SHA256, digest;
 | 
			
		||||
 | 
			
		||||
		enforce(_snapshot.sha256 == digest!SHA256(content), "Хеш-сумма файла не совпадает");
 | 
			
		||||
 | 
			
		||||
		return content;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool remove() {
 | 
			
		||||
	void data(void delegate(const(ubyte)[]) sink)
 | 
			
		||||
	{
 | 
			
		||||
		auto chunks = _db.getChunks(_snapshot.id);
 | 
			
		||||
		auto fctx = new SHA256Digest();
 | 
			
		||||
 | 
			
		||||
		foreach (chunk; chunks)
 | 
			
		||||
		{
 | 
			
		||||
			ubyte[] bytes;
 | 
			
		||||
			if (chunk.zstd)
 | 
			
		||||
			{
 | 
			
		||||
				enforce(chunk.zSize == chunk.content.length, "Размер сжатого фрагмента не соответствует ожидаемому");
 | 
			
		||||
				bytes = cast(ubyte[]) uncompress(chunk.content);
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				bytes = chunk.content;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			enforce(chunk.size == bytes.length, "Оригинальный размер не соответствует ожидаемому");
 | 
			
		||||
			enforce(chunk.sha256 == digest!SHA256(bytes), "Хеш-сумма фрагмента не совпадает");
 | 
			
		||||
 | 
			
		||||
			sink(bytes);
 | 
			
		||||
			fctx.put(bytes);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		enforce(_snapshot.sha256 = fctx.finish(), "Хеш-сумма файла не совпадает");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool remove()
 | 
			
		||||
	{
 | 
			
		||||
		_db.beginImmediate();
 | 
			
		||||
 | 
			
		||||
		bool ok;
 | 
			
		||||
| 
						 | 
				
			
			@ -65,4 +103,40 @@ public:
 | 
			
		|||
 | 
			
		||||
		return _snapshot.id == idDeleted;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@property long id() const nothrow @safe
 | 
			
		||||
	{
 | 
			
		||||
		return _snapshot.id;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@property string label() const @safe
 | 
			
		||||
	{
 | 
			
		||||
		return _snapshot.label;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@property DateTime created() const @safe
 | 
			
		||||
	{
 | 
			
		||||
		return _snapshot.createdUtc;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@property long length() const nothrow @safe
 | 
			
		||||
	{
 | 
			
		||||
		return _snapshot.sourceLength;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@property ubyte[32] sha256() const nothrow @safe
 | 
			
		||||
	{
 | 
			
		||||
		return _snapshot.sha256;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@property string status() const
 | 
			
		||||
	{
 | 
			
		||||
		import std.conv : to;
 | 
			
		||||
		return _snapshot.status.to!string;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@property string description() const nothrow @safe
 | 
			
		||||
	{
 | 
			
		||||
		return _snapshot.description;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,12 +4,15 @@ import cdcdb.dblite;
 | 
			
		|||
import cdcdb.core;
 | 
			
		||||
import cdcdb.snapshot;
 | 
			
		||||
 | 
			
		||||
import zstd : compress, Level;
 | 
			
		||||
 | 
			
		||||
final class Storage
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
	// Параметры работы с базой данных
 | 
			
		||||
	DBLite _db;
 | 
			
		||||
	bool _zstd;
 | 
			
		||||
	int _level;
 | 
			
		||||
	// Настройки CDC механизма
 | 
			
		||||
	CDC _cdc;
 | 
			
		||||
	size_t _minSize;
 | 
			
		||||
| 
						 | 
				
			
			@ -31,10 +34,11 @@ private:
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	this(string database, bool zstd = false, size_t busyTimeout = 3000, size_t maxRetries = 3)
 | 
			
		||||
	this(string database, bool zstd = false, int level = Level.base, size_t busyTimeout = 3000, size_t maxRetries = 3)
 | 
			
		||||
	{
 | 
			
		||||
		_db = new DBLite(database, busyTimeout, maxRetries);
 | 
			
		||||
		_zstd = zstd;
 | 
			
		||||
		_level = level;
 | 
			
		||||
		initCDC();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -94,8 +98,6 @@ public:
 | 
			
		|||
		// Разбить на фрагменты
 | 
			
		||||
		Chunk[] chunks = _cdc.split(data);
 | 
			
		||||
 | 
			
		||||
		import zstd : compress;
 | 
			
		||||
 | 
			
		||||
		// Запись фрагментов в БД
 | 
			
		||||
		foreach (chunk; chunks)
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			@ -105,7 +107,7 @@ public:
 | 
			
		|||
			auto content = data[chunk.offset .. chunk.offset + chunk.size];
 | 
			
		||||
 | 
			
		||||
			if (_zstd) {
 | 
			
		||||
				ubyte[] zBytes = compress(content, 22);
 | 
			
		||||
				ubyte[] zBytes = compress(content, _level);
 | 
			
		||||
				size_t zSize = zBytes.length;
 | 
			
		||||
				ubyte[32] zHash = digest!SHA256(zBytes);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										17
									
								
								test/app.d
									
										
									
									
									
								
							
							
						
						
									
										17
									
								
								test/app.d
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -2,11 +2,14 @@ import std.stdio;
 | 
			
		|||
 | 
			
		||||
import cdcdb;
 | 
			
		||||
 | 
			
		||||
import std.file : read;
 | 
			
		||||
import std.file : read, write;
 | 
			
		||||
import std.stdio : File, writeln;
 | 
			
		||||
import std.conv : to;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
	auto storage = new Storage("/tmp/base.db", true);
 | 
			
		||||
	auto storage = new Storage("/tmp/base.db", true, 22);
 | 
			
		||||
	storage.newSnapshot("/tmp/text", cast(ubyte[]) read("/tmp/text"));
 | 
			
		||||
 | 
			
		||||
	// if (snapshot !is null) {
 | 
			
		||||
| 
						 | 
				
			
			@ -14,11 +17,11 @@ void main()
 | 
			
		|||
	// 	snapshot.remove();
 | 
			
		||||
	// }
 | 
			
		||||
 | 
			
		||||
	import std.stdio : writeln;
 | 
			
		||||
 | 
			
		||||
	foreach (snapshot; storage.getSnapshots()) {
 | 
			
		||||
		writeln(cast(string) snapshot.data);
 | 
			
		||||
		auto file = File("/tmp/restore" ~ snapshot.id.to!string, "wb");
 | 
			
		||||
		snapshot.data((const(ubyte)[] content) {
 | 
			
		||||
			file.rawWrite(content);
 | 
			
		||||
		});
 | 
			
		||||
		file.close();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// writeln(cas.getVersion);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue