Some work for threaded extraction
This commit is contained in:
+1
-2
@@ -62,8 +62,7 @@ pub fn init(alloc: std.mem.Allocator, fil: File) !Archive {
|
|||||||
/// Create the Archive dictating the amount of threads & memory used.
|
/// Create the Archive dictating the amount of threads & memory used.
|
||||||
/// If trying to extract a full archive, a large memory size & thread count could help.
|
/// If trying to extract a full archive, a large memory size & thread count could help.
|
||||||
/// If you're planning on only interacting with a small number of files, it should be fine to use few threads and a small memory size.
|
/// If you're planning on only interacting with a small number of files, it should be fine to use few threads and a small memory size.
|
||||||
pub fn initAdvanced(alloc: std.mem.Allocator, fil: File, offset: u64, threads: usize, mem: usize) !Archive {
|
pub fn initAdvanced(alloc: std.mem.Allocator, fil: File, offset: u64, threads: usize) !Archive {
|
||||||
_ = mem;
|
|
||||||
var super: Superblock = undefined;
|
var super: Superblock = undefined;
|
||||||
const red = try fil.pread(@ptrCast(&super), offset);
|
const red = try fil.pread(@ptrCast(&super), offset);
|
||||||
std.debug.assert(red == @sizeOf(Superblock));
|
std.debug.assert(red == @sizeOf(Superblock));
|
||||||
|
|||||||
+41
-17
@@ -91,6 +91,12 @@ pub fn read(alloc: std.mem.Allocator, rdr: *Reader, block_size: u32) !Inode {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
pub fn readFromEntry(alloc: std.mem.Allocator, archive: *Archive, entry: DirEntry) !Inode {
|
||||||
|
var rdr = try archive.fil.readerAt(archive.super.inode_start + entry.block_start, &[0]u8{});
|
||||||
|
var meta: MetadataReader = .init(alloc, &rdr.interface, archive.decomp);
|
||||||
|
try meta.interface.discardAll(entry.block_offset);
|
||||||
|
return read(alloc, &meta.interface, archive.super.block_size);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn deinit(self: Inode, alloc: std.mem.Allocator) void {
|
pub fn deinit(self: Inode, alloc: std.mem.Allocator) void {
|
||||||
switch (self.data) {
|
switch (self.data) {
|
||||||
@@ -118,16 +124,15 @@ fn readerFromData(archive: *Archive, data: anytype) !DataReader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the directory entries for a directory inode.
|
/// Get the directory entries for a directory inode.
|
||||||
pub fn dirEntries(self: Inode, archive: *Archive) ![]DirEntry {
|
pub fn dirEntries(self: Inode, alloc: std.mem.Allocator, archive: *Archive) ![]DirEntry {
|
||||||
return switch (self.hdr.inode_type) {
|
return switch (self.hdr.inode_type) {
|
||||||
.dir => entriesFromData(archive, self.data.dir),
|
.dir => entriesFromData(alloc, archive, self.data.dir),
|
||||||
.ext_dir => entriesFromData(archive, self.data.ext_dir),
|
.ext_dir => entriesFromData(alloc, archive, self.data.ext_dir),
|
||||||
else => error.NotDirectory,
|
else => error.NotDirectory,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
fn entriesFromData(archive: *Archive, data: anytype) ![]DirEntry {
|
fn entriesFromData(alloc: std.mem.Allocator, archive: *Archive, data: anytype) ![]DirEntry {
|
||||||
var rdr = try archive.fil.readerAt(archive.super.dir_start + data.block_start, &[0]u8{});
|
var rdr = try archive.fil.readerAt(archive.super.dir_start + data.block_start, &[0]u8{});
|
||||||
const alloc = archive.allocator();
|
|
||||||
var meta: MetadataReader = .init(alloc, &rdr.interface, archive.decomp);
|
var meta: MetadataReader = .init(alloc, &rdr.interface, archive.decomp);
|
||||||
try meta.interface.discardAll(data.block_offset);
|
try meta.interface.discardAll(data.block_offset);
|
||||||
return DirEntry.readDir(alloc, &meta.interface, data.size);
|
return DirEntry.readDir(alloc, &meta.interface, data.size);
|
||||||
@@ -155,10 +160,7 @@ pub fn extractTo(self: Inode, archive: *Archive, path: []const u8, options: Extr
|
|||||||
new_path[path.len] = '/';
|
new_path[path.len] = '/';
|
||||||
defer alloc.free(new_path);
|
defer alloc.free(new_path);
|
||||||
|
|
||||||
var rdr = try archive.fil.readerAt(archive.super.inode_start + entry.block_start, &[0]u8{});
|
var inode: Inode = try readFromEntry(archive, entry);
|
||||||
var meta: MetadataReader = .init(alloc, &rdr.interface, archive.decomp);
|
|
||||||
try meta.interface.discardAll(entry.block_offset);
|
|
||||||
var inode: Inode = try read(alloc, &meta.interface, archive.super.block_size);
|
|
||||||
defer inode.deinit(alloc);
|
defer inode.deinit(alloc);
|
||||||
try inode.extractTo(archive, new_path, options);
|
try inode.extractTo(archive, new_path, options);
|
||||||
}
|
}
|
||||||
@@ -171,9 +173,9 @@ pub fn extractTo(self: Inode, archive: *Archive, path: []const u8, options: Extr
|
|||||||
|
|
||||||
const Perms = struct {
|
const Perms = struct {
|
||||||
path: []const u8,
|
path: []const u8,
|
||||||
owner: u16,
|
uid: u16,
|
||||||
|
gid: u16,
|
||||||
perm: u16,
|
perm: u16,
|
||||||
mod_time: u32,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Extract the inode to the given path. Multi-threaded.
|
/// Extract the inode to the given path. Multi-threaded.
|
||||||
@@ -182,12 +184,34 @@ const Perms = struct {
|
|||||||
/// If threads <= 1, then this just calls extractTo.
|
/// If threads <= 1, then this just calls extractTo.
|
||||||
pub fn extractToThreaded(self: Inode, archive: *Archive, path: []const u8, options: ExtractionOptions, threads: usize) !void {
|
pub fn extractToThreaded(self: Inode, archive: *Archive, path: []const u8, options: ExtractionOptions, threads: usize) !void {
|
||||||
if (threads <= 1) return self.extractTo(archive, path, options);
|
if (threads <= 1) return self.extractTo(archive, path, options);
|
||||||
std.debug.print("{}\n", .{threads});
|
|
||||||
@constCast(&threads).* = try std.Thread.getCpuCount();
|
|
||||||
std.debug.print("{}\n", .{threads});
|
|
||||||
switch (self.hdr.inode_type) {
|
switch (self.hdr.inode_type) {
|
||||||
.dir, .ext_dir => {},
|
.dir, .ext_dir => {
|
||||||
.file, .ext_file => {},
|
var arena_alloc: std.heap.ArenaAllocator = .init(archive.allocator());
|
||||||
|
defer arena_alloc.deinit();
|
||||||
|
var alloc = arena_alloc.allocator();
|
||||||
|
|
||||||
|
var wg: WaitGroup = .{};
|
||||||
|
var perms: ?std.ArrayList(Perms) = if (options.ignore_permissions) null else try .initCapacity(alloc, 100);
|
||||||
|
// defer if(!options.ignore_permissions) perms.?.deinit(alloc); We don't need to do this due to ArenaAllocator
|
||||||
|
var pool: Pool = undefined;
|
||||||
|
try pool.init(.{ .n_jobs = threads });
|
||||||
|
|
||||||
|
const entries = try self.dirEntries(archive);
|
||||||
|
var files: std.ArrayList(*DirEntry) = try .initCapacity(alloc, 100);
|
||||||
|
// defer files.deinit(alloc); We don't need to do this due to ArenaAllocator
|
||||||
|
try self.extractThread(alloc, archive, path, options, &wg, &pool, if (perms == null) null else &perms);
|
||||||
|
wg.wait();
|
||||||
|
if (perms != null) {
|
||||||
|
for (perms.items) |p| {
|
||||||
|
var fil = try std.fs.cwd().openFile(p.path, .{});
|
||||||
|
try fil.chmod(p.perm);
|
||||||
|
try fil.chown(p.uid, p.gid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.file, .ext_file => {
|
||||||
|
return error.TODO;
|
||||||
|
},
|
||||||
.symlink, .ext_symlink => try self.extractSymlink(path),
|
.symlink, .ext_symlink => try self.extractSymlink(path),
|
||||||
else => try self.extractDevice(archive, path, options),
|
else => try self.extractDevice(archive, path, options),
|
||||||
}
|
}
|
||||||
@@ -195,7 +219,7 @@ pub fn extractToThreaded(self: Inode, archive: *Archive, path: []const u8, optio
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Extract threadedly the inode to the path.
|
/// Extract threadedly the inode to the path.
|
||||||
fn extractThread(self: Inode, archive: *Archive, path: []const u8, options: ExtractionOptions, wg: *WaitGroup, pool: *Pool, perms: ?*std.ArrayList(Perms)) !void {
|
fn extractThread(self: Inode, alloc: std.mem.Allocator, archive: *Archive, path: []const u8, options: ExtractionOptions, wg: *WaitGroup, pool: *Pool, perms: ?*std.ArrayList(Perms)) !void {
|
||||||
_ = pool;
|
_ = pool;
|
||||||
_ = perms;
|
_ = perms;
|
||||||
_ = archive;
|
_ = archive;
|
||||||
|
|||||||
Reference in New Issue
Block a user