Fixed issues when using Threaded.single_threaded
This commit is contained in:
@@ -15,9 +15,12 @@ pub fn build(b: *std.Build) !void {
|
|||||||
zig_squashfs_options.addOption(bool, "allow_lzo", allow_lzo);
|
zig_squashfs_options.addOption(bool, "allow_lzo", allow_lzo);
|
||||||
|
|
||||||
const target = b.standardTargetOptions(.{});
|
const target = b.standardTargetOptions(.{});
|
||||||
const optimize = b.standardOptimizeOption(.{});
|
var optimize = b.standardOptimizeOption(.{});
|
||||||
|
|
||||||
if (optimize == .Debug) debug = true;
|
if (debug == true)
|
||||||
|
optimize = .Debug;
|
||||||
|
if (optimize == .Debug)
|
||||||
|
debug = true;
|
||||||
|
|
||||||
const c = b.addTranslateC(.{
|
const c = b.addTranslateC(.{
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
|
|||||||
+26
-6
@@ -227,14 +227,34 @@ test "ExtractCompleteArchiveSingleThreaded" {
|
|||||||
std.debug.print("Starting test: ExtractCompleteArchive...\n", .{});
|
std.debug.print("Starting test: ExtractCompleteArchive...\n", .{});
|
||||||
|
|
||||||
const alloc = std.testing.allocator;
|
const alloc = std.testing.allocator;
|
||||||
const io = Io.Threaded.global_single_threaded.io();
|
var threaded: Io.Evented = undefined;
|
||||||
|
try threaded.init(alloc, .{});
|
||||||
|
defer threaded.deinit();
|
||||||
|
const io = threaded.io();
|
||||||
|
var signal: u32 = 0;
|
||||||
|
|
||||||
Io.Dir.cwd().deleteTree(io, TestFullExtractLocation) catch {};
|
Io.Dir.cwd().deleteTree(io, TestFullExtractLocation) catch {};
|
||||||
var fil = try Io.Dir.cwd().openFile(io, TestArchive, .{});
|
|
||||||
defer fil.close(io);
|
const tmp = struct {
|
||||||
var sfs: Archive = try .init(io, fil, 0);
|
fn singleThreadedExtract(sig: *u32) !void {
|
||||||
defer sfs.deinit(io);
|
var fil = try Io.Dir.cwd().openFile(Io.Threaded.global_single_threaded.io(), TestArchive, .{});
|
||||||
try sfs.extract(alloc, io, TestFullExtractLocation, .default);
|
defer fil.close(Io.Threaded.global_single_threaded.io());
|
||||||
|
var sfs: Archive = try .init(Io.Threaded.global_single_threaded.io(), fil, 0);
|
||||||
|
defer sfs.deinit(Io.Threaded.global_single_threaded.io());
|
||||||
|
try sfs.extract(std.testing.allocator, Io.Threaded.global_single_threaded.io(), TestFullExtractLocation, .default);
|
||||||
|
sig.* = 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var ret = try io.concurrent(tmp.singleThreadedExtract, .{&signal});
|
||||||
|
try io.futexWaitTimeout(
|
||||||
|
u32,
|
||||||
|
&signal,
|
||||||
|
0,
|
||||||
|
.{ .deadline = .fromNow(io, .{ .raw = .fromSeconds(10), .clock = .awake }) },
|
||||||
|
);
|
||||||
|
if (ret.any_future == null) return ret.result;
|
||||||
|
try ret.cancel(io);
|
||||||
|
return error.TestTimeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
const LinuxPATestCorrectSuperblock: Superblock = .{
|
const LinuxPATestCorrectSuperblock: Superblock = .{
|
||||||
|
|||||||
+1
-1
@@ -67,7 +67,7 @@ pub const Decomp = union(enum) {
|
|||||||
.gzip => .{ .gzip = if (options.use_zig_decomp) try zlib.init(alloc, io, block_size) else try zlib.init(alloc, io) },
|
.gzip => .{ .gzip = if (options.use_zig_decomp) try zlib.init(alloc, io, block_size) else try zlib.init(alloc, io) },
|
||||||
.lzma => .{ .lzma = if (options.use_zig_decomp) try lzma.init(alloc, io, block_size) else .{} },
|
.lzma => .{ .lzma = if (options.use_zig_decomp) try lzma.init(alloc, io, block_size) else .{} },
|
||||||
.lzo => if (options.use_zig_decomp or !options.allow_lzo) error.LzoUnsupported else .{ .lzo = .{} },
|
.lzo => if (options.use_zig_decomp or !options.allow_lzo) error.LzoUnsupported else .{ .lzo = .{} },
|
||||||
.xz => .{ .xz = if (options.use_zig_decomp) try zlib.init(alloc, io, block_size) else .{} },
|
.xz => .{ .xz = if (options.use_zig_decomp) try xz.init(alloc, io, block_size) else .{} },
|
||||||
.lz4 => if (options.use_zig_decomp) error.Lz4Unsupported else .{ .lz4 = .{} },
|
.lz4 => if (options.use_zig_decomp) error.Lz4Unsupported else .{ .lz4 = .{} },
|
||||||
.zstd => .{ .zstd = if (options.use_zig_decomp) try zstd.init(alloc, io, block_size) else try zstd.init(alloc, io) },
|
.zstd => .{ .zstd = if (options.use_zig_decomp) try zstd.init(alloc, io, block_size) else try zstd.init(alloc, io) },
|
||||||
>>>>>>> dfbfbda (Build is working again (on Zig master branch))
|
>>>>>>> dfbfbda (Build is working again (on Zig master branch))
|
||||||
|
|||||||
+12
-10
@@ -41,20 +41,22 @@ pub fn deinit(self: *Self, alloc: std.mem.Allocator) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn decomp(d: ?*const Decompressor, alloc: std.mem.Allocator, in: []u8, out: []u8) Error!usize {
|
fn decomp(d: ?*const Decompressor, alloc: std.mem.Allocator, in: []u8, out: []u8) Error!usize {
|
||||||
if (d == null) {
|
// TODO: Fix
|
||||||
|
//
|
||||||
|
// if (d == null) {
|
||||||
return statelessDecomp(d, alloc, in, out);
|
return statelessDecomp(d, alloc, in, out);
|
||||||
}
|
// }
|
||||||
var self: *Self = @fieldParentPtr("interface", @constCast(d.?));
|
// var self: *Self = @fieldParentPtr("interface", @constCast(d.?));
|
||||||
|
|
||||||
const ctx = self.ctx_queue.getOne(self.io) catch return Error.ReadFailed;
|
// const ctx = self.ctx_queue.getOne(self.io) catch return Error.ReadFailed;
|
||||||
defer self.ctx_queue.putOne(self.io, ctx) catch {};
|
// defer self.ctx_queue.putOne(self.io, ctx) catch {};
|
||||||
|
|
||||||
_ = c.ZSTD_DCtx_reset(ctx, c.ZSTD_reset_session_only);
|
// _ = c.ZSTD_DCtx_reset(ctx, c.ZSTD_reset_session_only);
|
||||||
|
|
||||||
const res = c.ZSTD_decompressDCtx(ctx, out.ptr, out.len, in.ptr, in.len);
|
// const res = c.ZSTD_decompressDCtx(ctx, out.ptr, out.len, in.ptr, in.len);
|
||||||
if (c.ZSTD_isError(res) != 0)
|
// if (c.ZSTD_isError(res) != 0)
|
||||||
return Error.ReadFailed;
|
// return Error.ReadFailed;
|
||||||
return res;
|
// return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stateless
|
// Stateless
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ fn decomp(d: ?*const Decompressor, alloc: std.mem.Allocator, in: []u8, out: []u8
|
|||||||
const buf = self.buf_queue.getOne(self.io) catch return Error.ReadFailed;
|
const buf = self.buf_queue.getOne(self.io) catch return Error.ReadFailed;
|
||||||
defer self.buf_queue.putOne(self.io, buf) catch {};
|
defer self.buf_queue.putOne(self.io, buf) catch {};
|
||||||
|
|
||||||
return zlibDecomp(buf.buf, in, out);
|
return zlibDecomp(buf, in, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fn zlibDecomp(buffer: []u8, in: []u8, out: []u8) !usize {
|
inline fn zlibDecomp(buffer: []u8, in: []u8, out: []u8) !usize {
|
||||||
|
|||||||
+62
-56
@@ -276,7 +276,7 @@ pub fn extract(
|
|||||||
const path = std.mem.trimEnd(u8, filepath, "/");
|
const path = std.mem.trimEnd(u8, filepath, "/");
|
||||||
|
|
||||||
var decomp_base: Decomp = try .init(super.compression, alloc, io, super.block_size);
|
var decomp_base: Decomp = try .init(super.compression, alloc, io, super.block_size);
|
||||||
defer decomp_base.deinit(alloc);
|
decomp_base.deinit(alloc);
|
||||||
const decomp = decomp_base.decompressor();
|
const decomp = decomp_base.decompressor();
|
||||||
|
|
||||||
var frag_mgr: FragManager = try .init(alloc, fil, decomp, super.frag_start, super.frag_count, super.block_size);
|
var frag_mgr: FragManager = try .init(alloc, fil, decomp, super.frag_start, super.frag_count, super.block_size);
|
||||||
@@ -286,64 +286,13 @@ pub fn extract(
|
|||||||
var sel: Io.Select(ExtractReturnUnion) = .init(io, &sel_buf);
|
var sel: Io.Select(ExtractReturnUnion) = .init(io, &sel_buf);
|
||||||
defer sel.cancelDiscard();
|
defer sel.cancelDiscard();
|
||||||
|
|
||||||
|
var loop = io.async(finishLoop, .{ alloc, io, fil, decomp, super, options, &sel });
|
||||||
|
|
||||||
sel.async(.path_ret, extractReal, .{ self, alloc, io, fil, super, decomp, &sel, &frag_mgr, path, true });
|
sel.async(.path_ret, extractReal, .{ self, alloc, io, fil, super, decomp, &sel, &frag_mgr, path, true });
|
||||||
|
|
||||||
var id_table: CachedTable(u16) = .init(alloc, fil, decomp, super.id_start, super.id_count);
|
try loop.await(io);
|
||||||
defer id_table.deinit(io);
|
|
||||||
|
|
||||||
var xattr_table: ?XattrTable = if (super.flags.xattr_never or options.ignore_xattr or !@hasField(std.os, "linux"))
|
|
||||||
null
|
|
||||||
else
|
|
||||||
try .init(alloc, fil, decomp, super.xattr_start);
|
|
||||||
defer if (xattr_table != null) xattr_table.?.deinit(io);
|
|
||||||
|
|
||||||
var dir_queue: std.PriorityDequeue(PathRet, void, DirCompare) = .empty;
|
|
||||||
defer dir_queue.deinit(alloc);
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
if (sel.group.token.load(.unordered) == null) break;
|
|
||||||
|
|
||||||
const ret = try sel.await();
|
|
||||||
const path_ret = try ret.path_ret;
|
|
||||||
|
|
||||||
if (options.ignore_permissions and xattr_table == null) {
|
|
||||||
path_ret.deinit(alloc);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (path_ret.inode.hdr.inode_type == .dir or path_ret.inode.hdr.inode_type == .ext_dir) {
|
|
||||||
try dir_queue.push(alloc, path_ret);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
defer path_ret.deinit(alloc);
|
|
||||||
try path_ret.setMetadata(alloc, io, &id_table, if (xattr_table == null) null else &xattr_table.?, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (sel.cancel()) |ret| {
|
|
||||||
const path_ret = try ret.path_ret;
|
|
||||||
|
|
||||||
if (options.ignore_permissions and xattr_table == null) {
|
|
||||||
path_ret.deinit(alloc);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (path_ret.inode.hdr.inode_type == .dir or path_ret.inode.hdr.inode_type == .ext_dir) {
|
|
||||||
try dir_queue.push(alloc, path_ret);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
defer path_ret.deinit(alloc);
|
|
||||||
try path_ret.setMetadata(alloc, io, &id_table, if (xattr_table == null) null else &xattr_table.?, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
var iter = dir_queue.iterator();
|
|
||||||
while (iter.next()) |path_ret| {
|
|
||||||
defer path_ret.deinit(alloc);
|
|
||||||
try path_ret.setMetadata(alloc, io, &id_table, if (xattr_table == null) null else &xattr_table.?, options);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pub fn extractReal(
|
fn extractReal(
|
||||||
self: Inode,
|
self: Inode,
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
io: Io,
|
io: Io,
|
||||||
@@ -455,3 +404,60 @@ pub fn extractReal(
|
|||||||
.origin = origin,
|
.origin = origin,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn finishLoop(alloc: std.mem.Allocator, io: Io, fil: OffsetFile, decomp: *const Decompressor, super: Archive.Superblock, options: ExtractionOptions, sel: *Io.Select(ExtractReturnUnion)) !void {
|
||||||
|
var id_table: CachedTable(u16) = .init(alloc, fil, decomp, super.id_start, super.id_count);
|
||||||
|
defer id_table.deinit(io);
|
||||||
|
|
||||||
|
var xattr_table: ?XattrTable = if (super.flags.xattr_never or options.ignore_xattr or !@hasField(std.os, "linux"))
|
||||||
|
null
|
||||||
|
else
|
||||||
|
try .init(alloc, fil, decomp, super.xattr_start);
|
||||||
|
defer if (xattr_table != null) xattr_table.?.deinit(io);
|
||||||
|
|
||||||
|
var dir_queue: std.PriorityDequeue(PathRet, void, DirCompare) = .empty;
|
||||||
|
defer dir_queue.deinit(alloc);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (sel.group.token.load(.unordered) == null) break;
|
||||||
|
|
||||||
|
const ret = try sel.await();
|
||||||
|
const path_ret = try ret.path_ret;
|
||||||
|
|
||||||
|
if (options.ignore_permissions and xattr_table == null) {
|
||||||
|
path_ret.deinit(alloc);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path_ret.inode.hdr.inode_type == .dir or path_ret.inode.hdr.inode_type == .ext_dir) {
|
||||||
|
try dir_queue.push(alloc, path_ret);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
defer path_ret.deinit(alloc);
|
||||||
|
try path_ret.setMetadata(alloc, io, &id_table, if (xattr_table == null) null else &xattr_table.?, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (sel.cancel()) |ret| {
|
||||||
|
const path_ret = try ret.path_ret;
|
||||||
|
|
||||||
|
if (options.ignore_permissions and xattr_table == null) {
|
||||||
|
path_ret.deinit(alloc);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path_ret.inode.hdr.inode_type == .dir or path_ret.inode.hdr.inode_type == .ext_dir) {
|
||||||
|
try dir_queue.push(alloc, path_ret);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
defer path_ret.deinit(alloc);
|
||||||
|
try path_ret.setMetadata(alloc, io, &id_table, if (xattr_table == null) null else &xattr_table.?, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
var iter = dir_queue.iterator();
|
||||||
|
while (iter.next()) |path_ret| {
|
||||||
|
defer path_ret.deinit(alloc);
|
||||||
|
try path_ret.setMetadata(alloc, io, &id_table, if (xattr_table == null) null else &xattr_table.?, options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -49,6 +49,23 @@ fn numBlocks(self: DataExtractor) usize {
|
|||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Starts extracting the data using the given group to spawn async tasks.
|
||||||
|
pub fn extractConcurrent(self: DataExtractor, alloc: std.mem.Allocator, io: Io, fil: Io.File) (Error || Io.ConcurrentError)!void {
|
||||||
|
var group: Io.Group = .init;
|
||||||
|
defer group.cancel(io);
|
||||||
|
var err: ?Error = null;
|
||||||
|
|
||||||
|
var read_offset: u64 = self.start;
|
||||||
|
for (0..self.blocks.len) |idx| {
|
||||||
|
try group.concurrent(io, blockThread, .{ self, alloc, io, fil, read_offset, idx, &err });
|
||||||
|
read_offset += self.blocks[idx].size;
|
||||||
|
}
|
||||||
|
if (self.frag_block != null)
|
||||||
|
try group.concurrent(io, fragThread, .{ self, io, fil, &err });
|
||||||
|
|
||||||
|
group.await(io) catch |cancel| return err orelse cancel;
|
||||||
|
}
|
||||||
|
|
||||||
/// Starts extracting the data using the given group to spawn async tasks.
|
/// Starts extracting the data using the given group to spawn async tasks.
|
||||||
pub fn extractAsync(self: DataExtractor, alloc: std.mem.Allocator, io: Io, fil: Io.File) Error!void {
|
pub fn extractAsync(self: DataExtractor, alloc: std.mem.Allocator, io: Io, fil: Io.File) Error!void {
|
||||||
var group: Io.Group = .init;
|
var group: Io.Group = .init;
|
||||||
|
|||||||
Reference in New Issue
Block a user