More work on the data decompilation

This commit is contained in:
Caleb J. Gardner
2025-08-01 20:04:09 -05:00
parent ebaacf57a3
commit b3f4a02b72
+47 -21
View File
@@ -10,19 +10,48 @@ const Compression = @import("../superblock.zig").Compression;
const DataReaderError = error{ const DataReaderError = error{
EOF, EOF,
InvalidIndex, InvalidIndex,
ExtractionActive,
}; };
const CompletionMap = struct{ const DecompCompletion = struct {
errs: std.ArrayList(anyerror), errs: std.ArrayList(anyerror),
map: std.ArrayHashMap(usize, []u8), map: std.ArrayHashMap(usize, []u8),
mut: std.Thread.Mutex = .{}, mut: std.Thread.Mutex = .{},
cond: std.Thread.Condition = .{}, cond: std.Thread.Condition = .{},
fn init(alloc: std.mem.Allocator) CompletionMap{ fn init(alloc: std.mem.Allocator) DecompCompletion {
return .{ return .{
.errs = .init(alloc), .errs = .init(alloc),
.map = .init(alloc) .map = .init(alloc),
};
} }
fn deinit(self: *DecompCompletion) !void {
self.active = false;
self.errs.deinit();
self.map.deinit();
}
fn clear(self: *DecompCompletion) void {
self.errs.clearAndFree();
self.map.clearAndFree();
}
fn add(self: *DecompCompletion, idx: usize, data: []u8) !void {
self.mut.lock();
defer self.mut.unlock();
try self.map.put(idx, data);
}
fn addErr(self: *DecompCompletion, err: anyerror) void {
self.errs.append(err) catch {};
}
fn getBlock(self: *DecompCompletion, idx: usize) ?[]u8 {
const res = self.map.fetchSwapRemove(idx);
if(res == null) return null;
return res.?.value;
}
fn hasErrs(self: DecompCompletion) bool{
return self.errs.items.len > 0;
} }
}; };
@@ -41,7 +70,7 @@ pub fn DataReader(comptime T: type) type {
frag: ?[]u8 = null, frag: ?[]u8 = null,
mut: std.Thread.Mutex = .{}, completion: DecompCompletion,
pub fn init(rdr: *SfsReader(T), inode: Inode) !Self { pub fn init(rdr: *SfsReader(T), inode: Inode) !Self {
var sizes: []BlockSize = undefined; var sizes: []BlockSize = undefined;
@@ -73,46 +102,43 @@ pub fn DataReader(comptime T: type) type {
.sizes = sizes, .sizes = sizes,
.offsets = offsets, .offsets = offsets,
.files_size = file_size, .files_size = file_size,
.completion = .init(rdr.alloc),
}; };
} }
pub fn deinit(self: Self) void { pub fn deinit(self: *Self) void {
self.alloc.free(self.offsets); self.alloc.free(self.offsets);
self.completion.deinit();
} }
pub fn addFragment(self: Self, data: []u8) void { pub fn addFragment(self: *Self, data: []u8) void {
self.frag = data; self.frag = data;
} }
pub fn writeTo(self: Self, wrt: anytype) !void { pub fn writeTo(self: *Self, wrt: anytype) !void {
comptime std.debug.assert(std.meta.hasFn(@TypeOf(wrt), "write") or std.meta.hasFn(@TypeOf(wrt), "pwrite")); comptime std.debug.assert(std.meta.hasFn(@TypeOf(wrt), "write") or std.meta.hasFn(@TypeOf(wrt), "pwrite"));
var map: CompletionMap = .init(self.alloc);
defer map.deinit();
var mut: std.Thread.Mutex = .{};
var cond: std.Thread.Condition = .{};
var errs: std.ArrayList(anyerror) = .init(self.alloc);
defer errs.deinit();
var write_thr = try std.Thread.spawn( var write_thr = try std.Thread.spawn(
.{ .allocator = self.alloc }, .{ .allocator = self.alloc },
writeThread, writeThread,
.{ self, wrt, &errs, &map, &mut, &cond, null, null }, .{ self, wrt, null, null },
); );
defer self.completion.clear();
for (0..self.numBlocks()) |i| { for (0..self.numBlocks()) |i| {
var thr = std.Thread.spawn( var thr = std.Thread.spawn(
.{ .allocator = self.alloc }, .{ .allocator = self.alloc },
decompThread, decompThread,
.{ self, i, &errs, &map, &mut, &cond }, .{ self, i },
) catch |err| { ) catch |err| {
errs.append(err) catch {}; self.completion.addErr(err);
}; };
thr.detach(); thr.detach();
} }
write_thr.join(); write_thr.join();
if (errs.items.len > 0) return errs.items[0]; if () return errs.items[0];
} }
pub fn writeToNoBlock(self: Self, wrt: anytype, comptime finish: anytype, finish_args: anytype) !void { pub fn writeToNoBlock(self: Self, wrt: anytype, comptime finish: anytype, finish_args: anytype) !void {
comptime std.debug.assert(std.meta.hasFn(@TypeOf(wrt), "write") or std.meta.hasFn(@TypeOf(wrt), "pwrite")); comptime std.debug.assert(std.meta.hasFn(@TypeOf(wrt), "write") or std.meta.hasFn(@TypeOf(wrt), "pwrite"));
var map: CompletionMap = .init(self.alloc); var map: DecompCompletion = .init(self.alloc);
errdefer map.deinit(); errdefer map.deinit();
var mut = try self.alloc.create(std.Thread.Mutex); var mut = try self.alloc.create(std.Thread.Mutex);
errdefer self.alloc.destroy(mut); errdefer self.alloc.destroy(mut);
@@ -139,7 +165,6 @@ pub fn DataReader(comptime T: type) type {
thr.detach(); thr.detach();
} }
} }
fn writeToNoBlockFinish(comptime finish: anytype, finish_args: anytype) void {}
fn numBlocks(self: Self) usize { fn numBlocks(self: Self) usize {
var out = self.sizes.len; var out = self.sizes.len;
@@ -177,7 +202,7 @@ pub fn DataReader(comptime T: type) type {
self: Self, self: Self,
wrt: anytype, wrt: anytype,
errs: *std.ArrayList(anyerror), errs: *std.ArrayList(anyerror),
map: *CompletionMap, map: *DecompCompletion,
mut: *std.Thread.Mutex, mut: *std.Thread.Mutex,
cond: *std.Thread.Condition, cond: *std.Thread.Condition,
comptime finish: anytype, comptime finish: anytype,
@@ -188,6 +213,7 @@ pub fn DataReader(comptime T: type) type {
defer mut.unlock(); defer mut.unlock();
while (cur_idx < self.numBlocks() and errs.items.len == 0) { while (cur_idx < self.numBlocks() and errs.items.len == 0) {
cond.wait(mut); cond.wait(mut);
if (errs.items.len > 0) break;
if (comptime std.meta.hasFn(@TypeOf(wrt), "pwrite")) { if (comptime std.meta.hasFn(@TypeOf(wrt), "pwrite")) {
for (map.keys()) |k| { for (map.keys()) |k| {
const blk = map.fetchSwapRemove(k).?.value; const blk = map.fetchSwapRemove(k).?.value;
@@ -231,7 +257,7 @@ pub fn DataReader(comptime T: type) type {
self: Self, self: Self,
idx: usize, idx: usize,
errs: *std.ArrayList(anyerror), errs: *std.ArrayList(anyerror),
map: *CompletionMap, map: *DecompCompletion,
mut: *std.Thread.Mutex, mut: *std.Thread.Mutex,
cond: *std.Thread.Condition, cond: *std.Thread.Condition,
) void { ) void {