ferret 0.9.1 → 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +6 -5
- data/Rakefile +34 -13
- data/TODO +1 -0
- data/TUTORIAL +1 -1
- data/ext/analysis.c +87 -70
- data/ext/analysis.h +18 -6
- data/ext/array.c +1 -2
- data/ext/array.h +1 -1
- data/ext/bitvector.c +10 -6
- data/ext/bitvector.h +2 -2
- data/ext/compound_io.c +30 -27
- data/ext/document.c +15 -15
- data/ext/document.h +5 -5
- data/ext/except.c +2 -0
- data/ext/except.h +25 -23
- data/ext/extconf.rb +1 -0
- data/ext/ferret.c +10 -8
- data/ext/ferret.h +9 -8
- data/ext/field.c +29 -25
- data/ext/filter.c +52 -14
- data/ext/frtio.h +13 -0
- data/ext/fs_store.c +115 -170
- data/ext/global.c +9 -8
- data/ext/global.h +17 -13
- data/ext/hash.c +13 -19
- data/ext/hash.h +11 -11
- data/ext/hashset.c +5 -7
- data/ext/hashset.h +9 -8
- data/ext/helper.c +1 -1
- data/ext/helper.h +2 -1
- data/ext/inc/except.h +25 -23
- data/ext/inc/lang.h +11 -1
- data/ext/ind.c +33 -21
- data/ext/index.h +44 -39
- data/ext/index_io.c +61 -57
- data/ext/index_rw.c +418 -361
- data/ext/lang.c +10 -0
- data/ext/lang.h +11 -1
- data/ext/nix_io.c +135 -0
- data/ext/priorityqueue.c +16 -16
- data/ext/priorityqueue.h +9 -6
- data/ext/q_boolean.c +128 -76
- data/ext/q_const_score.c +20 -20
- data/ext/q_filtered_query.c +20 -20
- data/ext/q_fuzzy.c +37 -23
- data/ext/q_match_all.c +15 -19
- data/ext/q_multi_phrase.c +87 -46
- data/ext/q_parser.c +247 -119
- data/ext/q_phrase.c +86 -52
- data/ext/q_prefix.c +25 -14
- data/ext/q_range.c +59 -14
- data/ext/q_span.c +263 -172
- data/ext/q_term.c +62 -51
- data/ext/q_wildcard.c +24 -13
- data/ext/r_analysis.c +328 -80
- data/ext/r_doc.c +11 -6
- data/ext/r_index_io.c +40 -32
- data/ext/r_qparser.c +15 -14
- data/ext/r_search.c +270 -152
- data/ext/r_store.c +32 -17
- data/ext/ram_store.c +38 -22
- data/ext/search.c +617 -87
- data/ext/search.h +227 -163
- data/ext/similarity.c +54 -45
- data/ext/similarity.h +3 -3
- data/ext/sort.c +132 -53
- data/ext/store.c +21 -2
- data/ext/store.h +14 -14
- data/ext/tags +4322 -232
- data/ext/term.c +140 -109
- data/ext/termdocs.c +74 -60
- data/ext/vector.c +181 -152
- data/ext/w32_io.c +150 -0
- data/lib/ferret.rb +1 -1
- data/lib/ferret/analysis/standard_tokenizer.rb +4 -3
- data/lib/ferret/document/field.rb +1 -1
- data/lib/ferret/index/field_infos.rb +1 -1
- data/lib/ferret/index/term.rb +1 -1
- data/lib/ferret/query_parser/query_parser.tab.rb +8 -24
- data/lib/ferret/search.rb +1 -0
- data/lib/ferret/search/boolean_query.rb +0 -4
- data/lib/ferret/search/index_searcher.rb +21 -8
- data/lib/ferret/search/multi_phrase_query.rb +7 -0
- data/lib/ferret/search/multi_searcher.rb +261 -0
- data/lib/ferret/search/phrase_query.rb +1 -1
- data/lib/ferret/search/query.rb +34 -5
- data/lib/ferret/search/sort.rb +7 -3
- data/lib/ferret/search/sort_field.rb +8 -4
- data/lib/ferret/store/fs_store.rb +13 -6
- data/lib/ferret/store/index_io.rb +0 -14
- data/lib/ferret/store/ram_store.rb +3 -2
- data/lib/rferret.rb +1 -1
- data/test/unit/analysis/ctc_analyzer.rb +131 -0
- data/test/unit/analysis/ctc_tokenstream.rb +98 -9
- data/test/unit/index/tc_index.rb +40 -1
- data/test/unit/index/tc_term.rb +7 -0
- data/test/unit/index/th_doc.rb +8 -0
- data/test/unit/query_parser/tc_query_parser.rb +6 -4
- data/test/unit/search/rtc_sort_field.rb +6 -6
- data/test/unit/search/tc_index_searcher.rb +8 -0
- data/test/unit/search/tc_multi_searcher.rb +275 -0
- data/test/unit/search/tc_multi_searcher2.rb +126 -0
- data/test/unit/search/tc_search_and_sort.rb +66 -0
- metadata +31 -26
- data/test/unit/query_parser/rtc_query_parser.rb +0 -138
data/ext/frtio.h
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#ifndef FRT_IO_H
|
2
|
+
#define FRT_IO_H
|
3
|
+
|
4
|
+
extern char *join_path(char *buf, const char *base, const char *filename);
|
5
|
+
extern bool exists(char *path);
|
6
|
+
extern int fcount(char *path);
|
7
|
+
extern void dir_each(char *path, void (*func)(char *fname, void *arg), void *arg);
|
8
|
+
extern void fs_clear_locks(Store *store);
|
9
|
+
extern void fs_clear(Store *store);
|
10
|
+
extern void fs_clear_all(Store *store);
|
11
|
+
|
12
|
+
#endif
|
13
|
+
|
data/ext/fs_store.c
CHANGED
@@ -1,28 +1,36 @@
|
|
1
|
+
#include "store.h"
|
2
|
+
#include "frtio.h"
|
3
|
+
#ifdef WIN32
|
4
|
+
# ifndef S_IRUSR
|
5
|
+
# define S_IRUSR _S_IREAD
|
6
|
+
# endif
|
7
|
+
# ifndef S_IWUSR
|
8
|
+
# define S_IWUSR _S_IWRITE
|
9
|
+
# endif
|
10
|
+
# include <io.h>
|
11
|
+
#else
|
12
|
+
#include <unistd.h>
|
13
|
+
# define _close close
|
14
|
+
# define _open open
|
15
|
+
# define _creat creat
|
16
|
+
# define _lseek lseek
|
17
|
+
# define _read read
|
18
|
+
# define _stat stat
|
19
|
+
# define _fstat fstat
|
20
|
+
#endif
|
1
21
|
#include <sys/types.h>
|
2
|
-
#include <sys/dir.h>
|
3
|
-
#include <sys/stat.h>
|
4
|
-
#include <dirent.h>
|
5
22
|
#include <fcntl.h>
|
6
|
-
#include <
|
7
|
-
|
23
|
+
#include <sys/stat.h>
|
8
24
|
#include <errno.h>
|
9
25
|
#include <string.h>
|
10
26
|
#include <stdio.h>
|
11
|
-
|
27
|
+
|
12
28
|
|
13
29
|
static char * const FILE_OPEN_ERROR_MSG = "Couldn't open the file to read";
|
14
30
|
static char * const SEEK_ERROR_MSG = "Seek error message";
|
15
31
|
static char * const WRITE_ERROR_MSG = "Write error message";
|
16
32
|
|
17
|
-
|
18
|
-
* Create a filepath for a file in the store using the operating systems
|
19
|
-
* default file seperator.
|
20
|
-
*/
|
21
|
-
static char *join_path(char *buf, const char *base, const char *filename)
|
22
|
-
{
|
23
|
-
sprintf(buf, "%s/%s", base, filename);
|
24
|
-
return buf;
|
25
|
-
}
|
33
|
+
extern void store_destroy(Store *store);
|
26
34
|
|
27
35
|
/**
|
28
36
|
* Create the file +filename+ in the +store+.
|
@@ -31,13 +39,15 @@ static char *join_path(char *buf, const char *base, const char *filename)
|
|
31
39
|
* @param filename the name of the file to create
|
32
40
|
* @throws IO_ERROR if the file cannot be created
|
33
41
|
*/
|
34
|
-
void fs_touch(Store *store, char *filename)
|
42
|
+
static void fs_touch(Store *store, char *filename)
|
35
43
|
{
|
36
|
-
|
37
|
-
|
38
|
-
|
44
|
+
int f;
|
45
|
+
char path[MAX_FILE_PATH];
|
46
|
+
join_path(path, store->dir.path, filename);
|
47
|
+
if ((f = _creat(path, S_IRUSR|S_IWUSR)) == 0) {
|
39
48
|
RAISE(IO_ERROR, strerror(errno));
|
40
|
-
|
49
|
+
}
|
50
|
+
_close(f);
|
41
51
|
}
|
42
52
|
|
43
53
|
/**
|
@@ -50,15 +60,8 @@ void fs_touch(Store *store, char *filename)
|
|
50
60
|
*/
|
51
61
|
int fs_exists(Store *store, char *filename)
|
52
62
|
{
|
53
|
-
char buf[
|
54
|
-
|
55
|
-
if (fd < 0) {
|
56
|
-
if (errno != ENOENT)
|
57
|
-
RAISE(IO_ERROR, strerror(errno));
|
58
|
-
return false;
|
59
|
-
}
|
60
|
-
close(fd);
|
61
|
-
return true;
|
63
|
+
char buf[MAX_FILE_PATH];
|
64
|
+
return exists(join_path(buf, store->dir.path, filename));
|
62
65
|
}
|
63
66
|
|
64
67
|
/**
|
@@ -71,7 +74,7 @@ int fs_exists(Store *store, char *filename)
|
|
71
74
|
*/
|
72
75
|
int fs_remove(Store *store, char *filename)
|
73
76
|
{
|
74
|
-
char buf[
|
77
|
+
char buf[MAX_FILE_PATH];
|
75
78
|
return remove(join_path(buf, store->dir.path, filename));
|
76
79
|
}
|
77
80
|
|
@@ -86,10 +89,17 @@ int fs_remove(Store *store, char *filename)
|
|
86
89
|
*/
|
87
90
|
int fs_rename(Store *store, char *from, char *to)
|
88
91
|
{
|
89
|
-
char buf1[
|
92
|
+
char buf1[MAX_FILE_PATH], buf2[MAX_FILE_PATH];
|
93
|
+
|
94
|
+
#ifdef WIN32
|
95
|
+
remove(join_path(buf1, store->dir.path, to));
|
96
|
+
#endif
|
90
97
|
|
91
|
-
|
92
|
-
|
98
|
+
if (rename(join_path(buf1, store->dir.path, from),
|
99
|
+
join_path(buf2, store->dir.path, to)) < 0) {
|
100
|
+
RAISE(IO_ERROR, strerror(errno));
|
101
|
+
}
|
102
|
+
return true;
|
93
103
|
}
|
94
104
|
|
95
105
|
/**
|
@@ -101,20 +111,7 @@ int fs_rename(Store *store, char *from, char *to)
|
|
101
111
|
*/
|
102
112
|
int fs_count(Store *store)
|
103
113
|
{
|
104
|
-
|
105
|
-
struct dirent *de;
|
106
|
-
DIR *d = opendir(store->dir.path);
|
107
|
-
|
108
|
-
if (!d) RAISE(IO_ERROR, strerror(errno));
|
109
|
-
|
110
|
-
while ((de = readdir(d)) != NULL) {
|
111
|
-
if (de->d_name[0] != '.') {
|
112
|
-
cnt++;
|
113
|
-
}
|
114
|
-
}
|
115
|
-
closedir(d);
|
116
|
-
|
117
|
-
return cnt;
|
114
|
+
return fcount(store->dir.path);
|
118
115
|
}
|
119
116
|
|
120
117
|
/**
|
@@ -130,39 +127,7 @@ int fs_count(Store *store)
|
|
130
127
|
*/
|
131
128
|
void fs_each(Store *store, void (*func)(char *fname, void *arg), void *arg)
|
132
129
|
{
|
133
|
-
|
134
|
-
DIR *d = opendir(store->dir.path);
|
135
|
-
|
136
|
-
if (!d) RAISE(IO_ERROR, strerror(errno));
|
137
|
-
|
138
|
-
while ((de = readdir(d)) != NULL) {
|
139
|
-
if ((strncmp(de->d_name, LOCK_PREFIX, strlen(LOCK_PREFIX)) == 0) ||
|
140
|
-
(de->d_name[0] == '.'))
|
141
|
-
continue;
|
142
|
-
func(de->d_name, arg);
|
143
|
-
}
|
144
|
-
closedir(d);
|
145
|
-
}
|
146
|
-
|
147
|
-
/**
|
148
|
-
* Clear all the locks in the store.
|
149
|
-
*
|
150
|
-
* @param store the store to clear the locks from
|
151
|
-
* @throws IO_ERROR if there is an error opening the directory
|
152
|
-
*/
|
153
|
-
void fs_clear_locks(Store *store)
|
154
|
-
{
|
155
|
-
struct dirent *de;
|
156
|
-
DIR *d = opendir(store->dir.path);
|
157
|
-
|
158
|
-
if (!d) RAISE(IO_ERROR, strerror(errno));
|
159
|
-
|
160
|
-
while ((de = readdir(d)) != NULL) {
|
161
|
-
if (file_is_lock(de->d_name)) {
|
162
|
-
fs_remove(store, de->d_name);
|
163
|
-
}
|
164
|
-
}
|
165
|
-
closedir(d);
|
130
|
+
dir_each(store->dir.path, func, arg);
|
166
131
|
}
|
167
132
|
|
168
133
|
/**
|
@@ -171,54 +136,13 @@ void fs_clear_locks(Store *store)
|
|
171
136
|
* @param p the store to destroy
|
172
137
|
* @throws IO_ERROR if there is an error deleting the locks
|
173
138
|
*/
|
174
|
-
void fs_destroy(
|
139
|
+
void fs_destroy(Store *store)
|
175
140
|
{
|
176
|
-
Store *store = (Store *)p;
|
177
141
|
fs_clear_locks(store);
|
178
142
|
free(store->dir.path);
|
179
143
|
store_destroy(store);
|
180
144
|
}
|
181
145
|
|
182
|
-
/**
|
183
|
-
* Clear all files from the store except the lock files.
|
184
|
-
*
|
185
|
-
* @param store the store to clear all the files from
|
186
|
-
* @throws IO_ERROR if there is an error deleting the files
|
187
|
-
*/
|
188
|
-
void fs_clear(Store *store)
|
189
|
-
{
|
190
|
-
struct dirent *de;
|
191
|
-
DIR *d = opendir(store->dir.path);
|
192
|
-
|
193
|
-
if (!d) RAISE(IO_ERROR, strerror(errno));
|
194
|
-
|
195
|
-
while ((de = readdir(d)) != NULL) {
|
196
|
-
if (de->d_name[0] != '.' && !file_is_lock(de->d_name)) {
|
197
|
-
fs_remove(store, de->d_name);
|
198
|
-
}
|
199
|
-
}
|
200
|
-
closedir(d);
|
201
|
-
}
|
202
|
-
|
203
|
-
/**
|
204
|
-
* Clear all files from the store including the lock files.
|
205
|
-
*
|
206
|
-
* @param store the store to clear all the files from
|
207
|
-
* @throws IO_ERROR if there is an error deleting the files
|
208
|
-
*/
|
209
|
-
void fs_clear_all(Store *store)
|
210
|
-
{
|
211
|
-
struct dirent *de;
|
212
|
-
DIR *d = opendir(store->dir.path);
|
213
|
-
|
214
|
-
while ((de = readdir(d)) != NULL) {
|
215
|
-
if (de->d_name[0] != '.') {
|
216
|
-
fs_remove(store, de->d_name);
|
217
|
-
}
|
218
|
-
}
|
219
|
-
closedir(d);
|
220
|
-
}
|
221
|
-
|
222
146
|
/**
|
223
147
|
* Return the length of the file +filename+ in +store+
|
224
148
|
*
|
@@ -229,7 +153,7 @@ void fs_clear_all(Store *store)
|
|
229
153
|
*/
|
230
154
|
int fs_length(Store *store, char *filename)
|
231
155
|
{
|
232
|
-
char buf[
|
156
|
+
char buf[MAX_FILE_PATH];
|
233
157
|
struct stat stt;
|
234
158
|
|
235
159
|
if (stat(join_path(buf, store->dir.path, filename), &stt))
|
@@ -288,11 +212,12 @@ void fso_close_internal(OutStream *os)
|
|
288
212
|
*/
|
289
213
|
OutStream *fs_create_output(Store *store, const char *filename)
|
290
214
|
{
|
291
|
-
char buf[
|
215
|
+
char buf[MAX_FILE_PATH];
|
292
216
|
FILE *f = fopen(join_path(buf, store->dir.path, filename), "wb");
|
217
|
+
OutStream *os;
|
293
218
|
if (!f) RAISE(IO_ERROR, strerror(errno));
|
294
219
|
|
295
|
-
|
220
|
+
os = os_create();
|
296
221
|
os->file = f;
|
297
222
|
os->flush_internal = &fso_flush_internal;
|
298
223
|
os->seek_internal = &fso_seek_internal;
|
@@ -315,11 +240,14 @@ void fsi_read_internal(InStream *is, uchar *b, int offset, int len)
|
|
315
240
|
{
|
316
241
|
int fd = (int)is->file;
|
317
242
|
int pos = is_pos(is);
|
318
|
-
if (pos !=
|
319
|
-
|
243
|
+
if (pos != _lseek(fd, 0, SEEK_CUR)) {
|
244
|
+
_lseek(fd, pos, SEEK_SET);
|
320
245
|
}
|
321
|
-
if (
|
322
|
-
|
246
|
+
if (_read(fd, b, len) != len) {
|
247
|
+
/* win: the wrong value can be returned for some reason so double check */
|
248
|
+
if (_lseek(fd, 0, SEEK_CUR) != (pos + len)) {
|
249
|
+
RAISE(EOF_ERROR, strerror(errno));
|
250
|
+
}
|
323
251
|
}
|
324
252
|
}
|
325
253
|
|
@@ -332,8 +260,9 @@ void fsi_read_internal(InStream *is, uchar *b, int offset, int len)
|
|
332
260
|
*/
|
333
261
|
void fsi_seek_internal(InStream *is, int pos)
|
334
262
|
{
|
335
|
-
if (
|
263
|
+
if (_lseek((int)is->file, pos, SEEK_SET) < 0) {
|
336
264
|
RAISE(IO_ERROR, strerror(errno));
|
265
|
+
}
|
337
266
|
}
|
338
267
|
|
339
268
|
/**
|
@@ -345,18 +274,13 @@ void fsi_seek_internal(InStream *is, int pos)
|
|
345
274
|
void fsi_close_internal(InStream *is)
|
346
275
|
{
|
347
276
|
if (!is->is_clone) {
|
348
|
-
if (
|
277
|
+
if (_close((int)is->file)) {
|
349
278
|
RAISE(IO_ERROR, strerror(errno));
|
279
|
+
}
|
350
280
|
free(is->d.path);
|
351
281
|
}
|
352
282
|
}
|
353
283
|
|
354
|
-
/**
|
355
|
-
* Clone the input stream. Nothing to do for a file system input stream
|
356
|
-
*/
|
357
|
-
void fsi_clone_internal(InStream *is, InStream *new_is)
|
358
|
-
{ }
|
359
|
-
|
360
284
|
/**
|
361
285
|
* Returns the length of the input stream +is+
|
362
286
|
*
|
@@ -365,12 +289,19 @@ void fsi_clone_internal(InStream *is, InStream *new_is)
|
|
365
289
|
*/
|
366
290
|
int fsi_length(InStream *is)
|
367
291
|
{
|
368
|
-
struct
|
369
|
-
if (
|
292
|
+
struct _stat stt;
|
293
|
+
if (_fstat((int)is->file, &stt)) {
|
370
294
|
RAISE(IO_ERROR, strerror(errno));
|
295
|
+
}
|
371
296
|
return stt.st_size;
|
372
297
|
}
|
373
298
|
|
299
|
+
/**
|
300
|
+
* Clone the input stream. Nothing to do for a file system input stream
|
301
|
+
*/
|
302
|
+
void fsi_clone_internal(InStream *is, InStream *new_is)
|
303
|
+
{ }
|
304
|
+
|
374
305
|
/**
|
375
306
|
* Open an input stream in the +store+ with the name +filename+
|
376
307
|
*
|
@@ -380,11 +311,14 @@ int fsi_length(InStream *is)
|
|
380
311
|
*/
|
381
312
|
InStream *fs_open_input(Store *store, const char *filename)
|
382
313
|
{
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
314
|
+
InStream *is;
|
315
|
+
char buf[MAX_FILE_PATH];
|
316
|
+
int fd = _open(join_path(buf, store->dir.path, filename), O_RDONLY);
|
317
|
+
if (fd < 0) {
|
318
|
+
RAISE(IO_ERROR, FILE_OPEN_ERROR_MSG);
|
319
|
+
}
|
320
|
+
|
321
|
+
is = is_create();
|
388
322
|
is->file = (void *)fd;
|
389
323
|
is->d.path = estrdup(buf);
|
390
324
|
is->is_clone = false;
|
@@ -407,11 +341,12 @@ int fs_lock_obtain(Lock *lock)
|
|
407
341
|
{
|
408
342
|
int f;
|
409
343
|
int trys = LOCK_OBTAIN_TIMEOUT;
|
410
|
-
while (((f =
|
411
|
-
|
344
|
+
while (((f = _open(lock->name, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) &&
|
345
|
+
(trys > 0)) {
|
412
346
|
trys--;
|
347
|
+
}
|
413
348
|
if (f >= 0) {
|
414
|
-
|
349
|
+
_close(f);
|
415
350
|
return true;
|
416
351
|
} else {
|
417
352
|
return false;
|
@@ -426,10 +361,11 @@ int fs_lock_obtain(Lock *lock)
|
|
426
361
|
*/
|
427
362
|
int fs_lock_is_locked(Lock *lock)
|
428
363
|
{
|
429
|
-
int f =
|
364
|
+
int f = _open(lock->name, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR);
|
430
365
|
if (f >= 0) {
|
431
|
-
if (
|
366
|
+
if (_close(f) || remove(lock->name)) {
|
432
367
|
RAISE(IO_ERROR, strerror(errno));
|
368
|
+
}
|
433
369
|
return false;
|
434
370
|
} else {
|
435
371
|
return true;
|
@@ -445,7 +381,7 @@ Lock *fs_open_lock(Store *store, char *lockname)
|
|
445
381
|
{
|
446
382
|
Lock *lock = ALLOC(Lock);
|
447
383
|
char lname[100];
|
448
|
-
char buf[
|
384
|
+
char buf[MAX_FILE_PATH];
|
449
385
|
sprintf(lname, "%s%s.lck", LOCK_PREFIX, lockname);
|
450
386
|
lock->name = estrdup(join_path(buf, store->dir.path, lname));
|
451
387
|
lock->obtain = &fs_lock_obtain;
|
@@ -461,6 +397,20 @@ void fs_close_lock(Lock *lock)
|
|
461
397
|
free(lock);
|
462
398
|
}
|
463
399
|
|
400
|
+
#ifdef WIN32
|
401
|
+
static HshTable stores = {
|
402
|
+
/* fill */0,
|
403
|
+
/* used */0,
|
404
|
+
/* mask */Hsh_MINSIZE - 1,
|
405
|
+
/* table */stores.smalltable,
|
406
|
+
/* smalltable */{0},
|
407
|
+
/* lookup */&h_lookup_str,
|
408
|
+
/* hash */NULL,
|
409
|
+
/* eq */NULL,
|
410
|
+
/* free_key */(free_ft)&dummy_free,
|
411
|
+
/* free_value */(free_ft)&fs_destroy
|
412
|
+
};
|
413
|
+
#else
|
464
414
|
static HshTable stores = {
|
465
415
|
fill:0,
|
466
416
|
used:0,
|
@@ -469,38 +419,33 @@ static HshTable stores = {
|
|
469
419
|
lookup:&h_lookup_str,
|
470
420
|
hash:NULL,
|
471
421
|
eq:NULL,
|
472
|
-
free_key:dummy_free,
|
473
|
-
free_value
|
422
|
+
free_key:(free_ft)&dummy_free,
|
423
|
+
free_value:(free_ft)&fs_destroy
|
474
424
|
};
|
425
|
+
#endif
|
475
426
|
|
476
427
|
#ifndef FERRET_EXT
|
477
428
|
static mutex_t stores_mutex = MUTEX_INITIALIZER;
|
478
429
|
#endif
|
479
430
|
|
480
|
-
void
|
431
|
+
void fs_close_i(Store *store)
|
481
432
|
{
|
482
|
-
mutex_lock(&
|
483
|
-
|
484
|
-
|
485
|
-
h_del(&stores, store->dir.path);
|
486
|
-
mutex_unlock(&stores_mutex);
|
487
|
-
} else {
|
488
|
-
mutex_unlock(&store->mutex);
|
489
|
-
}
|
433
|
+
mutex_lock(&stores_mutex);
|
434
|
+
h_del(&stores, store->dir.path);
|
435
|
+
mutex_unlock(&stores_mutex);
|
490
436
|
}
|
491
437
|
|
492
438
|
Store *fs_store_create(const char *pathname)
|
493
439
|
{
|
494
440
|
Store *new_store = store_create();
|
495
|
-
|
496
|
-
new_store->ref_cnt = 0;
|
441
|
+
|
497
442
|
new_store->dir.path = estrdup(pathname);
|
498
443
|
new_store->touch = &fs_touch;
|
499
444
|
new_store->exists = &fs_exists;
|
500
445
|
new_store->remove = &fs_remove;
|
501
446
|
new_store->rename = &fs_rename;
|
502
447
|
new_store->count = &fs_count;
|
503
|
-
new_store->
|
448
|
+
new_store->close_i = &fs_close_i;
|
504
449
|
new_store->clear = &fs_clear;
|
505
450
|
new_store->clear_all = &fs_clear_all;
|
506
451
|
new_store->clear_locks = &fs_clear_locks;
|
@@ -519,15 +464,15 @@ Store *open_fs_store(const char *pathname)
|
|
519
464
|
|
520
465
|
mutex_lock(&stores_mutex);
|
521
466
|
store = h_get(&stores, pathname);
|
522
|
-
if (
|
467
|
+
if (store) {
|
468
|
+
mutex_lock(&store->mutex);
|
469
|
+
store->ref_cnt++;
|
470
|
+
mutex_unlock(&store->mutex);
|
471
|
+
} else {
|
523
472
|
store = fs_store_create(pathname);
|
524
|
-
h_set(&stores,
|
473
|
+
h_set(&stores, store->dir.path, store);
|
525
474
|
}
|
526
475
|
mutex_unlock(&stores_mutex);
|
527
476
|
|
528
|
-
mutex_lock(&store->mutex);
|
529
|
-
store->ref_cnt++;
|
530
|
-
mutex_unlock(&store->mutex);
|
531
|
-
|
532
477
|
return store;
|
533
478
|
}
|