Получение снимка
This commit is contained in:
parent
8631c65e39
commit
024f37cb3b
3 changed files with 103 additions and 86 deletions
|
@ -8,6 +8,12 @@ import std.format : format;
|
||||||
|
|
||||||
import zstd;
|
import zstd;
|
||||||
|
|
||||||
|
import std.exception : enforce;
|
||||||
|
import std.stdio : writeln;
|
||||||
|
import std.conv : to;
|
||||||
|
|
||||||
|
import std.file : write;
|
||||||
|
|
||||||
// CAS-хранилище (Content-Addressable Storage) со снапшотами
|
// CAS-хранилище (Content-Addressable Storage) со снапшотами
|
||||||
final class CAS
|
final class CAS
|
||||||
{
|
{
|
||||||
|
@ -26,7 +32,6 @@ public:
|
||||||
ubyte[32] hashSource = digest!SHA256(data);
|
ubyte[32] hashSource = digest!SHA256(data);
|
||||||
// Сделать запрос в БД по filePath и сверить хеш файлов
|
// Сделать запрос в БД по filePath и сверить хеш файлов
|
||||||
|
|
||||||
import std.stdio : writeln;
|
|
||||||
// writeln(hashSource.length);
|
// writeln(hashSource.length);
|
||||||
|
|
||||||
|
|
||||||
|
@ -86,4 +91,31 @@ public:
|
||||||
// Вернуть ID манифеста
|
// Вернуть ID манифеста
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void restoreSnapshot()
|
||||||
|
{
|
||||||
|
string restoreFile = "/tmp/restore.d";
|
||||||
|
|
||||||
|
foreach (Snapshot snapshot; _db.getSnapshots("/tmp/text")) {
|
||||||
|
auto dataChunks = _db.getChunks(snapshot.id);
|
||||||
|
ubyte[] content;
|
||||||
|
|
||||||
|
foreach (SnapshotDataChunk chunk; dataChunks) {
|
||||||
|
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, "Оригинальный размер не соответствует ожидаемому");
|
||||||
|
|
||||||
|
content ~= bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
enforce(snapshot.fileSha256 == digest!SHA256(content), "Хеш-сумма файла не совпадает");
|
||||||
|
|
||||||
|
write(snapshot.filePath ~ snapshot.id.to!string, content);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -187,97 +187,71 @@ public:
|
||||||
|
|
||||||
// // --- чтение ---
|
// // --- чтение ---
|
||||||
|
|
||||||
// Snapshot getSnapshot(long id)
|
Snapshot[] getSnapshots(string filePath)
|
||||||
// {
|
{
|
||||||
// auto queryResult = sql(
|
auto queryResult = sql(
|
||||||
// q{
|
q{
|
||||||
// SELECT id, file_path, file_sha256, label, created_utc, source_length,
|
SELECT id, file_path, file_sha256, label, created_utc, source_length,
|
||||||
// algo_min, algo_normal, algo_max, mask_s, mask_l, status
|
algo_min, algo_normal, algo_max, mask_s, mask_l, status
|
||||||
// FROM snapshots WHERE id = ?
|
FROM snapshots WHERE file_path = ?
|
||||||
// }, id);
|
}, filePath
|
||||||
|
);
|
||||||
|
|
||||||
// Snapshot s;
|
Snapshot[] snapshots;
|
||||||
// bool found = false;
|
// bool found = false;
|
||||||
// foreach (row; queryResult)
|
foreach (row; queryResult)
|
||||||
// {
|
{
|
||||||
// s.id = row[0].to!long;
|
Snapshot snapshot;
|
||||||
// s.file_path = row[1].to!string;
|
|
||||||
// s.label = row[2].to!string;
|
snapshot.id = row["id"].to!long;
|
||||||
// s.created_utc = row[3].to!string;
|
snapshot.filePath = row["file_path"].to!string;
|
||||||
// s.source_length = row[4].to!long;
|
snapshot.fileSha256 = cast(ubyte[]) row["file_sha256"].dup;
|
||||||
// s.algo_min = row[5].to!long;
|
snapshot.label = row["label"].to!string;
|
||||||
// s.algo_normal = row[6].to!long;
|
snapshot.createdUtc = row["created_utc"].to!string;
|
||||||
// s.algo_max = row[7].to!long;
|
snapshot.sourceLength = row["source_length"].to!long;
|
||||||
// s.mask_s = row[8].to!long;
|
snapshot.algoMin = row["algo_min"].to!long;
|
||||||
// s.mask_l = row[9].to!long;
|
snapshot.algoNormal = row["algo_normal"].to!long;
|
||||||
// s.status = cast(SnapshotStatus) row[10].to!int;
|
snapshot.algoMax = row["algo_max"].to!long;
|
||||||
|
snapshot.maskS = row["mask_s"].to!long;
|
||||||
|
snapshot.maskL = row["mask_l"].to!long;
|
||||||
|
snapshot.status = cast(SnapshotStatus)row["status"].to!int;
|
||||||
// found = true;
|
// found = true;
|
||||||
// break;
|
snapshots ~= snapshot;
|
||||||
// }
|
}
|
||||||
// enforce(found, "getSnapshot: not found");
|
// enforce(found, "getSnapshot: not found");
|
||||||
// return s;
|
return snapshots;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// SnapshotChunk[] getSnapshotChunks(long snapshotId)
|
SnapshotDataChunk[] getChunks(long snapshotId) {
|
||||||
// {
|
auto queryResult = sql(
|
||||||
// auto r = sql(q{
|
q{
|
||||||
// SELECT snapshot_id,chunk_index,COALESCE(offset,0),size,sha256
|
SELECT sc.chunk_index, sc.offset, sc.size,
|
||||||
// FROM snapshot_chunks
|
b.content, b.zstd, b.z_size, b.sha256, b.z_sha256
|
||||||
// WHERE snapshot_id=? ORDER BY chunk_index
|
FROM snapshot_chunks sc
|
||||||
// }, snapshotId);
|
JOIN blobs b ON b.sha256 = sc.sha256
|
||||||
|
WHERE sc.snapshot_id = ?
|
||||||
|
ORDER BY sc.chunk_index
|
||||||
|
}, snapshotId
|
||||||
|
);
|
||||||
|
|
||||||
// auto acc = appender!SnapshotChunk[];
|
SnapshotDataChunk[] sdchs;
|
||||||
// foreach (row; r)
|
|
||||||
// {
|
|
||||||
// SnapshotChunk ch;
|
|
||||||
// ch.snapshot_id = row[0].to!long;
|
|
||||||
// ch.chunk_index = row[1].to!long;
|
|
||||||
// ch.offset = row[2].to!long;
|
|
||||||
// ch.size = row[3].to!long;
|
|
||||||
|
|
||||||
// const(ubyte)[] sha = cast(const(ubyte)[]) row[4];
|
foreach (row; queryResult)
|
||||||
// enforce(sha.length == 32, "getSnapshotChunks: sha256 blob length != 32");
|
{
|
||||||
// ch.sha256[] = sha[];
|
SnapshotDataChunk sdch;
|
||||||
|
|
||||||
// acc.put(ch);
|
sdch.chunkIndex = row["chunk_index"].to!long;
|
||||||
// }
|
sdch.offset = row["offset"].to!long;
|
||||||
// return acc.data;
|
sdch.size = row["size"].to!long;
|
||||||
// }
|
sdch.content = cast(ubyte[]) row["content"].dup;
|
||||||
|
sdch.zstd = cast(bool) row["zstd"].to!int;
|
||||||
|
sdch.zSize = row["z_size"].to!long;
|
||||||
|
sdch.sha256 = cast(ubyte[]) row["sha256"].dup;
|
||||||
|
sdch.zSha256 = cast(ubyte[]) row["z_sha256"].dup;
|
||||||
|
|
||||||
// /// Вариант без `out`: вернуть Nullable
|
sdchs ~= sdch;
|
||||||
// Nullable!Snapshot maybeGetSnapshotByLabel(string label)
|
}
|
||||||
// {
|
|
||||||
// auto r = sql(q{
|
|
||||||
// SELECT id,file_path,label,created_utc,source_length,
|
|
||||||
// algo_min,algo_normal,algo_max,mask_s,mask_l,status
|
|
||||||
// FROM snapshots
|
|
||||||
// WHERE label=? ORDER BY id DESC LIMIT 1
|
|
||||||
// }, label);
|
|
||||||
|
|
||||||
// foreach (row; r)
|
return sdchs;
|
||||||
// {
|
}
|
||||||
// Snapshot s;
|
|
||||||
// s.id = row[0].to!long;
|
|
||||||
// s.file_path = row[1].to!string;
|
|
||||||
// s.label = row[2].to!string;
|
|
||||||
// s.created_utc = row[3].to!string;
|
|
||||||
// s.source_length = row[4].to!long;
|
|
||||||
// s.algo_min = row[5].to!long;
|
|
||||||
// s.algo_normal = row[6].to!long;
|
|
||||||
// s.algo_max = row[7].to!long;
|
|
||||||
// s.mask_s = row[8].to!long;
|
|
||||||
// s.mask_l = row[9].to!long;
|
|
||||||
// s.status = cast(SnapshotStatus) row[10].to!int;
|
|
||||||
// return typeof(return)(s); // Nullable!Snapshot(s)
|
|
||||||
// }
|
|
||||||
// return typeof(return).init; // null/empty
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /// Или жёсткий вариант: вернуть/кинуть
|
|
||||||
// Snapshot getSnapshotByLabel(string label)
|
|
||||||
// {
|
|
||||||
// auto m = maybeGetSnapshotByLabel(label);
|
|
||||||
// enforce(!m.isNull, "getSnapshotByLabel: not found");
|
|
||||||
// return m.get;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,3 +43,14 @@ struct SnapshotChunk
|
||||||
long size;
|
long size;
|
||||||
ubyte[32] sha256; // BLOB(32)
|
ubyte[32] sha256; // BLOB(32)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct SnapshotDataChunk {
|
||||||
|
long chunkIndex;
|
||||||
|
long offset;
|
||||||
|
long size;
|
||||||
|
ubyte[] content;
|
||||||
|
bool zstd;
|
||||||
|
long zSize;
|
||||||
|
ubyte[32] sha256;
|
||||||
|
ubyte[32] zSha256;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue