@@ -8,10 +8,45 @@ const Self = @This();
8
8
9
9
pub const IndexRef = struct {
10
10
index : Index ,
11
+ name : []const u8 ,
11
12
references : usize = 0 ,
12
13
last_used_at : i64 = std .math .minInt (i64 ),
13
14
is_open : bool = false ,
14
15
lock : std.Thread.Mutex = .{},
16
+
17
+ pub fn deinit (self : * IndexRef , allocator : std.mem.Allocator ) void {
18
+ allocator .free (self .name );
19
+ self .index .deinit ();
20
+ }
21
+
22
+ pub fn incRef (self : * IndexRef ) void {
23
+ self .lock .lock ();
24
+ defer self .lock .unlock ();
25
+
26
+ self .references += 1 ;
27
+ self .last_used_at = std .time .milliTimestamp ();
28
+ }
29
+
30
+ pub fn decRef (self : * IndexRef ) bool {
31
+ self .lock .lock ();
32
+ defer self .lock .unlock ();
33
+
34
+ assert (self .references > 0 );
35
+ self .references -= 1 ;
36
+ self .last_used_at = std .time .timestamp ();
37
+
38
+ return self .references == 0 ;
39
+ }
40
+
41
+ pub fn ensureOpen (self : * IndexRef , create : bool ) ! void {
42
+ self .lock .lock ();
43
+ defer self .lock .unlock ();
44
+
45
+ if (self .is_open ) return ;
46
+
47
+ try self .index .open (create );
48
+ self .is_open = true ;
49
+ }
15
50
};
16
51
17
52
lock : std.Thread.Mutex = .{},
@@ -64,13 +99,32 @@ pub fn deinit(self: *Self) void {
64
99
self .indexes .deinit ();
65
100
}
66
101
67
- pub fn releaseIndex (self : * Self , index_data : * IndexRef ) void {
68
- self .lock .lock ();
69
- defer self .lock .unlock ();
102
+ fn deleteIndexFiles (self : * Self , name : []const u8 ) ! void {
103
+ const tmp_name = try std .mem .concat (self .allocator , u8 , &[_ ][]const u8 { name , ".delete" });
104
+ defer self .allocator .free (tmp_name );
105
+ try self .dir .rename (name , tmp_name );
106
+ try self .dir .deleteTree (tmp_name );
107
+ }
108
+
109
+ fn removeIndex (self : * Self , name : []const u8 ) void {
110
+ if (self .indexes .getEntry (name )) | entry | {
111
+ entry .value_ptr .deinit (self .allocator );
112
+ self .indexes .removeByPtr (entry .key_ptr );
113
+ }
114
+ }
70
115
71
- assert (index_data .references > 0 );
72
- index_data .references -= 1 ;
73
- index_data .last_used_at = std .time .timestamp ();
116
+ pub fn releaseIndex (self : * Self , index_ref : * IndexRef ) void {
117
+ if (index_ref .decRef ()) {
118
+ self .lock .lock ();
119
+ defer self .lock .unlock ();
120
+
121
+ index_ref .lock .lock ();
122
+ defer index_ref .lock .unlock ();
123
+
124
+ if (! index_ref .is_open ) {
125
+ self .removeIndex (index_ref .name );
126
+ }
127
+ }
74
128
}
75
129
76
130
pub fn acquireIndex (self : * Self , name : []const u8 ) ! * IndexRef {
@@ -83,53 +137,38 @@ pub fn acquireIndex(self: *Self, name: []const u8) !*IndexRef {
83
137
84
138
var result = try self .indexes .getOrPutAdapted (name , self .indexes .ctx );
85
139
if (result .found_existing ) {
86
- result .value_ptr .references += 1 ;
87
- result .value_ptr .last_used_at = std .time .timestamp ();
140
+ result .value_ptr .incRef ();
88
141
return result .value_ptr ;
89
142
}
90
-
91
143
errdefer self .indexes .removeByPtr (result .key_ptr );
92
144
93
145
result .key_ptr .* = try self .allocator .dupe (u8 , name );
94
146
errdefer self .allocator .free (result .key_ptr .* );
95
147
96
- result .value_ptr .index = try Index .init (self .allocator , self .dir , name , .{});
148
+ result .value_ptr .* = .{
149
+ .index = try Index .init (self .allocator , self .dir , name , .{}),
150
+ .name = result .key_ptr .* ,
151
+ };
97
152
errdefer result .value_ptr .index .deinit ();
98
153
99
- result .value_ptr .is_open = false ;
100
- result .value_ptr .references = 1 ;
101
- result .value_ptr .last_used_at = std .time .timestamp ();
154
+ result .value_ptr .incRef ();
102
155
return result .value_ptr ;
103
156
}
104
157
105
- fn ensureOpen (index_ref : * IndexRef , create : bool ) ! void {
106
- index_ref .lock .lock ();
107
- defer index_ref .lock .unlock ();
108
-
109
- if (index_ref .is_open ) return ;
110
-
111
- try index_ref .index .open (create );
112
- index_ref .is_open = true ;
113
- }
114
-
115
158
pub fn getIndex (self : * Self , name : []const u8 ) ! * IndexRef {
116
- if (! isValidName (name )) {
117
- return error .InvalidIndexName ;
118
- }
119
-
120
159
const index_ref = try self .acquireIndex (name );
121
- try ensureOpen (index_ref , false );
160
+ errdefer self .releaseIndex (index_ref );
161
+
162
+ try index_ref .ensureOpen (false );
163
+
122
164
return index_ref ;
123
165
}
124
166
125
167
pub fn createIndex (self : * Self , name : []const u8 ) ! void {
126
- if (! isValidName (name )) {
127
- return error .InvalidIndexName ;
128
- }
129
-
130
168
const index_ref = try self .acquireIndex (name );
131
- try ensureOpen (index_ref , true );
132
169
defer self .releaseIndex (index_ref );
170
+
171
+ try index_ref .ensureOpen (true );
133
172
}
134
173
135
174
pub fn deleteIndex (self : * Self , name : []const u8 ) ! void {
@@ -140,11 +179,6 @@ pub fn deleteIndex(self: *Self, name: []const u8) !void {
140
179
self .lock .lock ();
141
180
defer self .lock .unlock ();
142
181
143
- if (self .indexes .getEntry (name )) | entry | {
144
- self .allocator .free (entry .key_ptr .* );
145
- entry .value_ptr .index .deinit ();
146
- self .indexes .removeByPtr (entry .key_ptr );
147
- }
148
-
149
- try self .dir .deleteTree (name );
182
+ self .removeIndex (name );
183
+ try self .deleteIndexFiles (name );
150
184
}
0 commit comments