Skip to content

Commit 61ab171

Browse files
committed
Allow non-numeric index names
1 parent 20c8172 commit 61ab171

File tree

2 files changed

+54
-36
lines changed

2 files changed

+54
-36
lines changed

src/MultiIndex.zig

+48-17
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,24 @@ pub const IndexRef = struct {
1515
lock: std.Thread.Mutex = .{},
1616
allocator: std.mem.Allocator,
1717
dir: std.fs.Dir,
18-
indexes: std.AutoHashMap(u8, IndexRef),
18+
indexes: std.StringHashMap(IndexRef),
19+
20+
fn isValidName(name: []const u8) bool {
21+
for (name, 0) |c, i| {
22+
if (i == 0) {
23+
switch (c) {
24+
'0'...'9', 'A'...'Z', 'a'...'z' => {},
25+
else => return false,
26+
}
27+
} else {
28+
switch (c) {
29+
'0'...'9', 'A'...'Z', 'a'...'z', '_', '-' => {},
30+
else => return false,
31+
}
32+
}
33+
}
34+
return true;
35+
}
1936

2037
const max_sub_dir_name_size = 10;
2138
const sub_dir_name_fmt = "{x:0>2}";
@@ -24,7 +41,7 @@ pub fn init(allocator: std.mem.Allocator, dir: std.fs.Dir) Self {
2441
return .{
2542
.allocator = allocator,
2643
.dir = dir,
27-
.indexes = std.AutoHashMap(u8, IndexRef).init(allocator),
44+
.indexes = std.StringHashMap(IndexRef).init(allocator),
2845
};
2946
}
3047

@@ -45,11 +62,15 @@ pub fn releaseIndex(self: *Self, index_data: *IndexRef) void {
4562
index_data.last_used_at = std.time.timestamp();
4663
}
4764

48-
pub fn acquireIndex(self: *Self, id: u8, create: bool) !*IndexRef {
65+
pub fn acquireIndex(self: *Self, name: []const u8, create: bool) !*IndexRef {
66+
if (!isValidName(name)) {
67+
return error.InvalidIndexName;
68+
}
69+
4970
self.lock.lock();
5071
defer self.lock.unlock();
5172

52-
var result = try self.indexes.getOrPut(id);
73+
var result = try self.indexes.getOrPutAdapted(name, self.indexes.ctx);
5374
if (result.found_existing) {
5475
result.value_ptr.references += 1;
5576
result.value_ptr.last_used_at = std.time.timestamp();
@@ -58,10 +79,10 @@ pub fn acquireIndex(self: *Self, id: u8, create: bool) !*IndexRef {
5879

5980
errdefer self.indexes.removeByPtr(result.key_ptr);
6081

61-
var sub_dir_name_buf: [max_sub_dir_name_size]u8 = undefined;
62-
const sub_dir_name = try std.fmt.bufPrint(&sub_dir_name_buf, sub_dir_name_fmt, .{id});
82+
result.key_ptr.* = try self.allocator.dupe(u8, name);
83+
errdefer self.allocator.free(result.key_ptr.*);
6384

64-
result.value_ptr.index = try Index.init(self.allocator, self.dir, sub_dir_name, .{ .create = create });
85+
result.value_ptr.index = try Index.init(self.allocator, self.dir, name, .{ .create = create });
6586
errdefer result.value_ptr.index.deinit();
6687

6788
try result.value_ptr.index.open();
@@ -71,26 +92,36 @@ pub fn acquireIndex(self: *Self, id: u8, create: bool) !*IndexRef {
7192
return result.value_ptr;
7293
}
7394

74-
pub fn getIndex(self: *Self, id: u8) !*IndexRef {
75-
return try self.acquireIndex(id, false);
95+
pub fn getIndex(self: *Self, name: []const u8) !*IndexRef {
96+
if (!isValidName(name)) {
97+
return error.InvalidIndexName;
98+
}
99+
100+
return try self.acquireIndex(name, false);
76101
}
77102

78-
pub fn createIndex(self: *Self, id: u8) !void {
79-
const index_ref = try self.acquireIndex(id, true);
103+
pub fn createIndex(self: *Self, name: []const u8) !void {
104+
if (!isValidName(name)) {
105+
return error.InvalidIndexName;
106+
}
107+
108+
const index_ref = try self.acquireIndex(name, true);
80109
defer self.releaseIndex(index_ref);
81110
}
82111

83-
pub fn deleteIndex(self: *Self, id: u8) !void {
112+
pub fn deleteIndex(self: *Self, name: []const u8) !void {
113+
if (!isValidName(name)) {
114+
return error.InvalidIndexName;
115+
}
116+
84117
self.lock.lock();
85118
defer self.lock.unlock();
86119

87-
if (self.indexes.getEntry(id)) |entry| {
120+
if (self.indexes.getEntry(name)) |entry| {
121+
self.allocator.free(entry.key_ptr.*);
88122
entry.value_ptr.index.deinit();
89123
self.indexes.removeByPtr(entry.key_ptr);
90124
}
91125

92-
var sub_dir_name_buf: [max_sub_dir_name_size]u8 = undefined;
93-
const sub_dir_name = try std.fmt.bufPrint(&sub_dir_name_buf, sub_dir_name_fmt, .{id});
94-
95-
try self.dir.deleteTree(sub_dir_name);
126+
try self.dir.deleteTree(name);
96127
}

src/server.zig

+6-19
Original file line numberDiff line numberDiff line change
@@ -103,22 +103,9 @@ const SearchResultsJSON = struct {
103103
results: []SearchResultJSON,
104104
};
105105

106-
fn getIndexNo(ctx: *Context, req: *httpz.Request, res: *httpz.Response, send_body: bool) !?u8 {
107-
_ = ctx;
108-
const index_no_str = req.param("index") orelse "0";
109-
const index_no = std.fmt.parseInt(u8, index_no_str, 10) catch {
110-
res.status = 400;
111-
if (send_body) {
112-
try res.json(.{ .status = "invalid index number" }, .{});
113-
}
114-
return null;
115-
};
116-
return index_no;
117-
}
118-
119106
fn getIndex(ctx: *Context, req: *httpz.Request, res: *httpz.Response, send_body: bool) !?*IndexData {
120-
const index_no = try getIndexNo(ctx, req, res, send_body) orelse return null;
121-
const index = ctx.indexes.getIndex(index_no) catch |err| {
107+
const index_name = req.param("index") orelse return null;
108+
const index = ctx.indexes.getIndex(index_name) catch |err| {
122109
if (err == error.IndexNotFound) {
123110
res.status = 404;
124111
if (send_body) {
@@ -230,9 +217,9 @@ fn handleGetIndex(ctx: *Context, req: *httpz.Request, res: *httpz.Response) !voi
230217
}
231218

232219
fn handlePutIndex(ctx: *Context, req: *httpz.Request, res: *httpz.Response) !void {
233-
const index_no = try getIndexNo(ctx, req, res, true) orelse return;
220+
const index_name = req.param("index") orelse return;
234221

235-
ctx.indexes.createIndex(index_no) catch |err| {
222+
ctx.indexes.createIndex(index_name) catch |err| {
236223
log.err("index create error: {}", .{err});
237224
res.status = 500;
238225
return res.json(.{ .status = "internal error" }, .{});
@@ -242,9 +229,9 @@ fn handlePutIndex(ctx: *Context, req: *httpz.Request, res: *httpz.Response) !voi
242229
}
243230

244231
fn handleDeleteIndex(ctx: *Context, req: *httpz.Request, res: *httpz.Response) !void {
245-
const index_no = try getIndexNo(ctx, req, res, true) orelse return;
232+
const index_name = req.param("index") orelse return;
246233

247-
ctx.indexes.deleteIndex(index_no) catch |err| {
234+
ctx.indexes.deleteIndex(index_name) catch |err| {
248235
log.err("index delete error: {}", .{err});
249236
res.status = 500;
250237
return res.json(.{ .status = "internal error" }, .{});

0 commit comments

Comments
 (0)