diff options
Diffstat (limited to 'src/9p_io.zig')
| -rw-r--r-- | src/9p_io.zig | 28 |
1 files changed, 23 insertions, 5 deletions
diff --git a/src/9p_io.zig b/src/9p_io.zig index 9a38b438..57df0c5f 100644 --- a/src/9p_io.zig +++ b/src/9p_io.zig @@ -266,6 +266,7 @@ pub const Listener = struct { const restores = pardes.turn.restores; // Asked first: a release that runs a held line has none after. const changes = pardes.ctlfs.changesPane(core, req); + const fills = pardes.ctlfs.holdsPage(core, req); const reply = core.serveFs(req); if (req.op == .release and quiet) l.collectOs(); // A read with nothing yet stays parked in the engine, and the core @@ -299,6 +300,13 @@ pub const Listener = struct { // file written. A change carries no payload, so the reply is still // whole after the wait. l.kick(); + // A read that put a /pager open's text in (ctl.fillPager), or a + // close that handed it to the editor's step, waits on nothing the + // editor performs: its answer goes now, while the turn still keeps + // a read's payload whole. Waiting would hang a close through a + // mount: 9ns answers nothing else on it while a clunk is out, and + // the editor's step may be out opening a file through that mount. + if (fills) return conn.reply(&reply, core.fsPayload(reply)); // A refusal answers at once: its text may be in the core's one // buffer for it, which a request run while this one waited would // write over. @@ -2341,10 +2349,12 @@ pub const Client = struct { gpa.destroy(s); } - /// Writes `request` to `path` and reads the answer on the same open, - /// as /pane/new answers its own open: a session's last answer, from - /// another client, can never be what comes back. `exec 3<>file`. - pub fn ask(gpa: std.mem.Allocator, dial: []const u8, path: []const u8, request: []const u8) ![]u8 { + /// Writes `request`, then `more`, to `path` and reads the answer on the + /// same open, as /pane/new answers its own open: a session's last + /// answer, from another client, can never be what comes back. `exec + /// 3<>file`. `more` (`pardes -`'s text after its /pager line) goes in + /// Twrites at rising offsets, each answer giving the next its budget. + pub fn ask(gpa: std.mem.Allocator, dial: []const u8, path: []const u8, request: []const u8, more: []const u8) ![]u8 { if (comptime !supported) return error.Unsupported; var names: [max_depth][]const u8 = undefined; const n = try elements(path, &names); @@ -2356,7 +2366,15 @@ pub const Client = struct { defer endSession(gpa, s); const fid = (try walkTo(s, names[0..n], &remote)).fid; _ = try s.ask(.{ .open = .{ .fid = fid, .mode = ninep.ordwr } }, &remote); - _ = try s.ask(.{ .write = .{ .fid = fid, .offset = 0, .data = request } }, &remote); + var written: usize = 0; + while (written < request.len + more.len) { + const from = if (written < request.len) request[written..] else more[written - request.len ..]; + const chunk = from[0..@min(from.len, s.cl.maxWrite())]; + const count = (try s.ask(.{ .write = .{ .fid = fid, .offset = written, .data = chunk } }, &remote)).write; + if (count == 0 or count > chunk.len) return Error.Botch; + written += count; + s.deadline = nowMs() +| write_budget_ms; + } var out: std.ArrayList(u8) = .empty; errdefer out.deinit(gpa); while (true) { |
