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.
Files changed (105) hide show
  1. data/README +6 -5
  2. data/Rakefile +34 -13
  3. data/TODO +1 -0
  4. data/TUTORIAL +1 -1
  5. data/ext/analysis.c +87 -70
  6. data/ext/analysis.h +18 -6
  7. data/ext/array.c +1 -2
  8. data/ext/array.h +1 -1
  9. data/ext/bitvector.c +10 -6
  10. data/ext/bitvector.h +2 -2
  11. data/ext/compound_io.c +30 -27
  12. data/ext/document.c +15 -15
  13. data/ext/document.h +5 -5
  14. data/ext/except.c +2 -0
  15. data/ext/except.h +25 -23
  16. data/ext/extconf.rb +1 -0
  17. data/ext/ferret.c +10 -8
  18. data/ext/ferret.h +9 -8
  19. data/ext/field.c +29 -25
  20. data/ext/filter.c +52 -14
  21. data/ext/frtio.h +13 -0
  22. data/ext/fs_store.c +115 -170
  23. data/ext/global.c +9 -8
  24. data/ext/global.h +17 -13
  25. data/ext/hash.c +13 -19
  26. data/ext/hash.h +11 -11
  27. data/ext/hashset.c +5 -7
  28. data/ext/hashset.h +9 -8
  29. data/ext/helper.c +1 -1
  30. data/ext/helper.h +2 -1
  31. data/ext/inc/except.h +25 -23
  32. data/ext/inc/lang.h +11 -1
  33. data/ext/ind.c +33 -21
  34. data/ext/index.h +44 -39
  35. data/ext/index_io.c +61 -57
  36. data/ext/index_rw.c +418 -361
  37. data/ext/lang.c +10 -0
  38. data/ext/lang.h +11 -1
  39. data/ext/nix_io.c +135 -0
  40. data/ext/priorityqueue.c +16 -16
  41. data/ext/priorityqueue.h +9 -6
  42. data/ext/q_boolean.c +128 -76
  43. data/ext/q_const_score.c +20 -20
  44. data/ext/q_filtered_query.c +20 -20
  45. data/ext/q_fuzzy.c +37 -23
  46. data/ext/q_match_all.c +15 -19
  47. data/ext/q_multi_phrase.c +87 -46
  48. data/ext/q_parser.c +247 -119
  49. data/ext/q_phrase.c +86 -52
  50. data/ext/q_prefix.c +25 -14
  51. data/ext/q_range.c +59 -14
  52. data/ext/q_span.c +263 -172
  53. data/ext/q_term.c +62 -51
  54. data/ext/q_wildcard.c +24 -13
  55. data/ext/r_analysis.c +328 -80
  56. data/ext/r_doc.c +11 -6
  57. data/ext/r_index_io.c +40 -32
  58. data/ext/r_qparser.c +15 -14
  59. data/ext/r_search.c +270 -152
  60. data/ext/r_store.c +32 -17
  61. data/ext/ram_store.c +38 -22
  62. data/ext/search.c +617 -87
  63. data/ext/search.h +227 -163
  64. data/ext/similarity.c +54 -45
  65. data/ext/similarity.h +3 -3
  66. data/ext/sort.c +132 -53
  67. data/ext/store.c +21 -2
  68. data/ext/store.h +14 -14
  69. data/ext/tags +4322 -232
  70. data/ext/term.c +140 -109
  71. data/ext/termdocs.c +74 -60
  72. data/ext/vector.c +181 -152
  73. data/ext/w32_io.c +150 -0
  74. data/lib/ferret.rb +1 -1
  75. data/lib/ferret/analysis/standard_tokenizer.rb +4 -3
  76. data/lib/ferret/document/field.rb +1 -1
  77. data/lib/ferret/index/field_infos.rb +1 -1
  78. data/lib/ferret/index/term.rb +1 -1
  79. data/lib/ferret/query_parser/query_parser.tab.rb +8 -24
  80. data/lib/ferret/search.rb +1 -0
  81. data/lib/ferret/search/boolean_query.rb +0 -4
  82. data/lib/ferret/search/index_searcher.rb +21 -8
  83. data/lib/ferret/search/multi_phrase_query.rb +7 -0
  84. data/lib/ferret/search/multi_searcher.rb +261 -0
  85. data/lib/ferret/search/phrase_query.rb +1 -1
  86. data/lib/ferret/search/query.rb +34 -5
  87. data/lib/ferret/search/sort.rb +7 -3
  88. data/lib/ferret/search/sort_field.rb +8 -4
  89. data/lib/ferret/store/fs_store.rb +13 -6
  90. data/lib/ferret/store/index_io.rb +0 -14
  91. data/lib/ferret/store/ram_store.rb +3 -2
  92. data/lib/rferret.rb +1 -1
  93. data/test/unit/analysis/ctc_analyzer.rb +131 -0
  94. data/test/unit/analysis/ctc_tokenstream.rb +98 -9
  95. data/test/unit/index/tc_index.rb +40 -1
  96. data/test/unit/index/tc_term.rb +7 -0
  97. data/test/unit/index/th_doc.rb +8 -0
  98. data/test/unit/query_parser/tc_query_parser.rb +6 -4
  99. data/test/unit/search/rtc_sort_field.rb +6 -6
  100. data/test/unit/search/tc_index_searcher.rb +8 -0
  101. data/test/unit/search/tc_multi_searcher.rb +275 -0
  102. data/test/unit/search/tc_multi_searcher2.rb +126 -0
  103. data/test/unit/search/tc_search_and_sort.rb +66 -0
  104. metadata +31 -26
  105. 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 <unistd.h>
7
-
23
+ #include <sys/stat.h>
8
24
  #include <errno.h>
9
25
  #include <string.h>
10
26
  #include <stdio.h>
11
- #include "store.h"
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
- char buf[MAX_PATH];
37
- int fd = creat(join_path(buf, store->dir.path, filename), S_IRUSR|S_IWUSR);
38
- if (fd == -1)
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
- close(fd);
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[MAX_PATH];
54
- int fd = open(join_path(buf, store->dir.path, filename), 0);
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[MAX_PATH];
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[MAX_PATH], buf2[MAX_PATH];
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
- return rename(join_path(buf1, store->dir.path, from),
92
- join_path(buf2, store->dir.path, to));
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
- int cnt = 0;
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
- struct dirent *de;
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(void *p)
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[MAX_PATH];
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[MAX_PATH];
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
- OutStream *os = os_create();
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 != lseek(fd, 0, SEEK_CUR)) {
319
- lseek(fd, pos, SEEK_SET);
243
+ if (pos != _lseek(fd, 0, SEEK_CUR)) {
244
+ _lseek(fd, pos, SEEK_SET);
320
245
  }
321
- if (read(fd, b, len) != len) {
322
- RAISE(EOF_ERROR, strerror(errno));
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 (lseek((int)is->file, pos, SEEK_SET) < 0)
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 (close((int)is->file))
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 stat stt;
369
- if (fstat((int)is->file, &stt))
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
- char buf[MAX_PATH];
384
- int fd = open(join_path(buf, store->dir.path, filename), O_RDONLY);
385
- if (fd < 0) RAISE(IO_ERROR, FILE_OPEN_ERROR_MSG);
386
-
387
- InStream *is = is_create();
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 = open(lock->name, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) &&
411
- (trys > 0))
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
- close(f);
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 = open(lock->name, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR);
364
+ int f = _open(lock->name, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR);
430
365
  if (f >= 0) {
431
- if (close(f) || remove(lock->name))
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[MAX_PATH];
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:&fs_destroy
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 fs_close(Store *store)
431
+ void fs_close_i(Store *store)
481
432
  {
482
- mutex_lock(&store->mutex);
483
- if (--(store->ref_cnt) == 0) {
484
- mutex_lock(&stores_mutex);
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->close = &fs_close;
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 (!store) {
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, pathname, store);
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
  }