localmemcache 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +5 -2
- data/Rakefile +4 -0
- data/VERSION +1 -1
- data/bench/lmc_bench.rb +1 -1
- data/bench/tokyo_cabinet_bench +3 -0
- data/bench/tokyo_cabinet_bench.rb +20 -0
- data/site/doc/classes/LocalMemCache.html +146 -129
- data/site/doc/classes/LocalMemCache.src/M000001.html +1 -1
- data/site/doc/classes/LocalMemCache.src/M000002.html +26 -5
- data/site/doc/classes/LocalMemCache.src/M000003.html +16 -5
- data/site/doc/classes/LocalMemCache.src/M000004.html +7 -23
- data/site/doc/classes/LocalMemCache.src/M000005.html +7 -13
- data/site/doc/classes/LocalMemCache.src/M000006.html +4 -5
- data/site/doc/classes/LocalMemCache.src/M000007.html +6 -5
- data/site/doc/classes/LocalMemCache.src/M000008.html +6 -6
- data/site/doc/classes/LocalMemCache.src/M000009.html +1 -1
- data/site/doc/classes/LocalMemCache.src/M000010.html +4 -6
- data/site/doc/classes/LocalMemCache.src/M000011.html +4 -4
- data/site/doc/classes/LocalMemCache.src/M000012.html +4 -4
- data/site/doc/classes/LocalMemCache/ArgError.html +2 -2
- data/site/doc/classes/LocalMemCache/InitError.html +2 -2
- data/site/doc/classes/LocalMemCache/LocalMemCacheError.html +2 -2
- data/site/doc/classes/LocalMemCache/LockError.html +2 -2
- data/site/doc/classes/LocalMemCache/LockTimedOut.html +2 -2
- data/site/doc/classes/LocalMemCache/MemoryPoolClosed.html +2 -2
- data/site/doc/classes/LocalMemCache/MemoryPoolFull.html +2 -2
- data/site/doc/classes/LocalMemCache/OutOfMemoryError.html +2 -2
- data/site/doc/classes/LocalMemCache/RecoveryFailed.html +2 -2
- data/site/doc/classes/LocalMemCache/ShmError.html +2 -2
- data/site/doc/classes/LocalMemCache/ShmLockFailed.html +2 -2
- data/site/doc/classes/LocalMemCache/ShmUnlockFailed.html +2 -2
- data/site/doc/created.rid +1 -1
- data/site/doc/fr_class_index.html +2 -0
- data/site/doc/fr_file_index.html +3 -2
- data/site/doc/fr_method_index.html +17 -11
- data/site/doc/index.html +1 -1
- data/site/index.html +33 -17
- data/src/lmc_common.c +2 -1
- data/src/lmc_common.h +1 -1
- data/src/lmc_hashtable.c +62 -2
- data/src/lmc_hashtable.h +4 -1
- data/src/lmc_shm.c +1 -3
- data/src/lmc_shm.h +1 -3
- data/src/lmc_valloc.c +5 -0
- data/src/lmc_valloc.h +1 -0
- data/src/localmemcache.c +43 -8
- data/src/localmemcache.h +24 -6
- data/src/ruby-binding/localmemcache.rb +14 -29
- data/src/ruby-binding/rblocalmemcache.c +127 -16
- data/src/tests/allocfailure.rb +1 -1
- data/src/tests/bench.rb +1 -1
- data/src/tests/bench_keys.rb +1 -1
- data/src/tests/crash.rb +1 -1
- data/src/tests/lmc.rb +65 -9
- data/src/tests/lmctestapi.c +1 -1
- data/src/tests/parallelwrite.rb +1 -1
- data/src/tests/ttkeys +10 -0
- data/src/tests/ttkeys.rb +35 -0
- data/src/tests/ttlmc.rb +24 -6
- data/src/tests/ttrandom_pair +10 -0
- data/src/tests/ttrandom_pair.rb +23 -0
- metadata +8 -5
- data/site/doc/files/__/src/ruby-binding/extconf_rb.html +0 -108
- data/site/doc/files/__/src/ruby-binding/localmemcache_rb.html +0 -108
- data/site/doc/files/__/src/ruby-binding/rblocalmemcache_c.html +0 -101
@@ -55,8 +55,8 @@
|
|
55
55
|
<tr class="top-aligned-row">
|
56
56
|
<td><strong>In:</strong></td>
|
57
57
|
<td>
|
58
|
-
<a href="../../files/
|
59
|
-
|
58
|
+
<a href="../../files/localmemcache_rb.html">
|
59
|
+
localmemcache.rb
|
60
60
|
</a>
|
61
61
|
<br />
|
62
62
|
</td>
|
data/site/doc/created.rid
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
Wed, 06 May 2009 09:55:58 +0000
|
@@ -22,6 +22,7 @@
|
|
22
22
|
<div id="index-entries">
|
23
23
|
<a href="classes/LocalMemCache.html">LocalMemCache</a><br />
|
24
24
|
<a href="classes/LocalMemCache/ArgError.html">LocalMemCache::ArgError</a><br />
|
25
|
+
<a href="classes/LocalMemCache/DBVersionNotSupported.html">LocalMemCache::DBVersionNotSupported</a><br />
|
25
26
|
<a href="classes/LocalMemCache/InitError.html">LocalMemCache::InitError</a><br />
|
26
27
|
<a href="classes/LocalMemCache/LocalMemCacheError.html">LocalMemCache::LocalMemCacheError</a><br />
|
27
28
|
<a href="classes/LocalMemCache/LockError.html">LocalMemCache::LockError</a><br />
|
@@ -30,6 +31,7 @@
|
|
30
31
|
<a href="classes/LocalMemCache/MemoryPoolFull.html">LocalMemCache::MemoryPoolFull</a><br />
|
31
32
|
<a href="classes/LocalMemCache/OutOfMemoryError.html">LocalMemCache::OutOfMemoryError</a><br />
|
32
33
|
<a href="classes/LocalMemCache/RecoveryFailed.html">LocalMemCache::RecoveryFailed</a><br />
|
34
|
+
<a href="classes/LocalMemCache/SharedObjectStorage.html">LocalMemCache::SharedObjectStorage</a><br />
|
33
35
|
<a href="classes/LocalMemCache/ShmError.html">LocalMemCache::ShmError</a><br />
|
34
36
|
<a href="classes/LocalMemCache/ShmLockFailed.html">LocalMemCache::ShmLockFailed</a><br />
|
35
37
|
<a href="classes/LocalMemCache/ShmUnlockFailed.html">LocalMemCache::ShmUnlockFailed</a><br />
|
data/site/doc/fr_file_index.html
CHANGED
@@ -20,8 +20,9 @@
|
|
20
20
|
<div id="index">
|
21
21
|
<h1 class="section-bar">Files</h1>
|
22
22
|
<div id="index-entries">
|
23
|
-
<a href="files/
|
24
|
-
<a href="files/
|
23
|
+
<a href="files/extconf_rb.html">extconf.rb</a><br />
|
24
|
+
<a href="files/localmemcache_rb.html">localmemcache.rb</a><br />
|
25
|
+
<a href="files/rblocalmemcache_c.html">rblocalmemcache.c</a><br />
|
25
26
|
</div>
|
26
27
|
</div>
|
27
28
|
</body>
|
@@ -20,18 +20,24 @@
|
|
20
20
|
<div id="index">
|
21
21
|
<h1 class="section-bar">Methods</h1>
|
22
22
|
<div id="index-entries">
|
23
|
-
<a href="classes/LocalMemCache.html#
|
24
|
-
<a href="classes/LocalMemCache.html#
|
25
|
-
<a href="classes/LocalMemCache.html#
|
26
|
-
<a href="classes/LocalMemCache.html#
|
27
|
-
<a href="classes/LocalMemCache.html#
|
28
|
-
<a href="classes/LocalMemCache.html#
|
29
|
-
<a href="classes/LocalMemCache.html#
|
30
|
-
<a href="classes/LocalMemCache.html#
|
31
|
-
<a href="classes/LocalMemCache.html#
|
32
|
-
<a href="classes/LocalMemCache.html#M000011">
|
23
|
+
<a href="classes/LocalMemCache/SharedObjectStorage.html#M000016">[] (LocalMemCache::SharedObjectStorage)</a><br />
|
24
|
+
<a href="classes/LocalMemCache.html#M000005">[] (LocalMemCache)</a><br />
|
25
|
+
<a href="classes/LocalMemCache.html#M000009">[]= (LocalMemCache)</a><br />
|
26
|
+
<a href="classes/LocalMemCache/SharedObjectStorage.html#M000015">[]= (LocalMemCache::SharedObjectStorage)</a><br />
|
27
|
+
<a href="classes/LocalMemCache.html#M000003">check (LocalMemCache)</a><br />
|
28
|
+
<a href="classes/LocalMemCache.html#M000008">clear (LocalMemCache)</a><br />
|
29
|
+
<a href="classes/LocalMemCache.html#M000013">close (LocalMemCache)</a><br />
|
30
|
+
<a href="classes/LocalMemCache.html#M000006">delete (LocalMemCache)</a><br />
|
31
|
+
<a href="classes/LocalMemCache.html#M000002">drop (LocalMemCache)</a><br />
|
32
|
+
<a href="classes/LocalMemCache.html#M000011">each_pair (LocalMemCache)</a><br />
|
33
|
+
<a href="classes/LocalMemCache/SharedObjectStorage.html#M000017">each_pair (LocalMemCache::SharedObjectStorage)</a><br />
|
34
|
+
<a href="classes/LocalMemCache.html#M000004">get (LocalMemCache)</a><br />
|
35
|
+
<a href="classes/LocalMemCache.html#M000010">keys (LocalMemCache)</a><br />
|
33
36
|
<a href="classes/LocalMemCache.html#M000001">new (LocalMemCache)</a><br />
|
34
|
-
<a href="classes/LocalMemCache.html#
|
37
|
+
<a href="classes/LocalMemCache.html#M000012">random_pair (LocalMemCache)</a><br />
|
38
|
+
<a href="classes/LocalMemCache/SharedObjectStorage.html#M000018">random_pair (LocalMemCache::SharedObjectStorage)</a><br />
|
39
|
+
<a href="classes/LocalMemCache.html#M000007">set (LocalMemCache)</a><br />
|
40
|
+
<a href="classes/LocalMemCache.html#M000014">size (LocalMemCache)</a><br />
|
35
41
|
</div>
|
36
42
|
</div>
|
37
43
|
</body>
|
data/site/doc/index.html
CHANGED
@@ -19,6 +19,6 @@
|
|
19
19
|
<frame src="fr_class_index.html" name="Classes" />
|
20
20
|
<frame src="fr_method_index.html" name="Methods" />
|
21
21
|
</frameset>
|
22
|
-
<frame src="files/
|
22
|
+
<frame src="files/localmemcache_rb.html" name="docwin" />
|
23
23
|
</frameset>
|
24
24
|
</html>
|
data/site/index.html
CHANGED
@@ -9,25 +9,28 @@
|
|
9
9
|
<div id="content">
|
10
10
|
<h1>A persistent key-value database based on mmap()'ed shared memory</h1>
|
11
11
|
|
12
|
-
<p><b>Localmemcache</b> is a library for C and
|
12
|
+
<p><b>Localmemcache</b> is a library for <b>C</b> and <b>Ruby</b> that aims
|
13
|
+
to provide
|
13
14
|
an interface similar to memcached but for accessing local data instead of
|
14
|
-
remote data. It's based on <b>mmap()</b>'ed shared memory for maximum
|
15
|
-
|
16
|
-
|
15
|
+
remote data. It's based on <b>mmap()</b>'ed shared memory for <b>maximum
|
16
|
+
speed</b>.
|
17
|
+
Since version 0.3.0 it supports <b>persistence</b>, also making it <b>a fast
|
18
|
+
alternative to GDBM and Berkeley DB</b>.
|
17
19
|
|
18
|
-
<h2>Key features as of 0.
|
20
|
+
<h2>Key features as of 0.4.0 (2009-05-16)</h2>
|
19
21
|
<li><a href="#performance">blazingly fast</a></li>
|
22
|
+
<li>a very simple API</li>
|
20
23
|
<li>persistent</li>
|
21
24
|
<li>parallel writes are supported by default</li>
|
22
25
|
<li>uses transactions internally to avoid data corruption</li>
|
23
26
|
<li>lightweight: the core library is just about <b>1400</b> lines of <b>C</b> code</li>
|
24
27
|
|
25
28
|
<h2>Requirements</h2>
|
26
|
-
<li>a >=64bit Unix</li>
|
29
|
+
<li>a >=64bit Unix (32bit is possible but you'll run out of virtual address space quickly)</li>
|
27
30
|
<li>a file system that offers <a href="http://en.wikipedia.org/wiki/Sparse_file">sparse files</a></li>
|
28
31
|
Note for <b>OS X</b>: <b>OS X</b> disqualifies as <b>HFS+</b> doesn't
|
29
32
|
have sparse files and <b>sem_timedwait</b>() and <b>sem_getvalue</b>() aren't
|
30
|
-
supported as well
|
33
|
+
supported as well.<br>
|
31
34
|
Note for <b>FreeBSD</b>: It has been reported that Localmemcache
|
32
35
|
sometimes hangs there, it is not yet clear what the problem is.
|
33
36
|
|
@@ -42,15 +45,19 @@ sometimes hangs there, it is not yet clear what the problem is.
|
|
42
45
|
If you just want to use the <b>C API</b>, download the .tar.gz from <a href="http://rubyforge.org/frs/?group_id=7925">here</a>.
|
43
46
|
|
44
47
|
<h2>Using</h2>
|
45
|
-
<b>API</b>: <a href="http://github.com/sck/localmemcache/blob/
|
48
|
+
<b>API</b>: <a href="http://github.com/sck/localmemcache/blob/591d943507236035e99471f372dc2826271610c9/src/localmemcache.h">C</a>|<a href="http://localmemcache.rubyforge.org/doc/">Ruby</a><br>
|
46
49
|
<p><pre><code>require 'localmemcache'
|
47
50
|
# 1. the memcached way
|
48
51
|
# $lm = LocalMemCache.new :namespace => :viewcounters
|
49
52
|
# 2. the GDBM way
|
50
|
-
|
53
|
+
#$lm = LocalMemCache.new :filename => "./viewcounters.lmc"
|
54
|
+
# 3. Using LocalMemCache::SharedObjectStorage
|
55
|
+
$lm = LocalMemCache::SharedObjectStorage.new :filename =>
|
56
|
+
"./viewcounters.lmc"
|
51
57
|
$lm[:foo] = 1
|
52
58
|
$lm[:foo]
|
53
59
|
$lm.delete(:foo)
|
60
|
+
|
54
61
|
</code></pre>
|
55
62
|
(C version of this example: <a href="http://github.com/sck/localmemcache/blob/e980ba949034a349dbf0e6f8f9ef77bbe3e3e314/example/hello.c">hello.c</a>)
|
56
63
|
</p>
|
@@ -69,22 +76,20 @@ Ruby benchmark pseudo code:
|
|
69
76
|
</code></pre>
|
70
77
|
|
71
78
|
<pre>
|
72
|
-
Tokyo Tyrant: <b>298,226.197</b> ms
|
73
79
|
MemCache: <b>253,326.122</b> ms
|
74
80
|
GDBM: <b>24,226.116</b> ms
|
75
|
-
|
76
|
-
Localmemcache 0.
|
81
|
+
Tokyo Cabinet: <b>9,092.707</b> ms
|
82
|
+
Localmemcache 0.4.0: <b>5,310.055</b> ms
|
77
83
|
Ruby Hash of Strings: <b>4,963.313</b> ms
|
78
84
|
</pre>
|
79
|
-
(<a href="http://github.com/sck/localmemcache/tree/
|
85
|
+
(<a href="http://github.com/sck/localmemcache/tree/7e5a9549a3b8c32662aaebaec3642253ce0ea8b0/bench">Code of the benchmarks used</a>)
|
80
86
|
|
81
87
|
<p>
|
82
88
|
|
83
|
-
So, on my machine, using <b>Localmemcache</b> 0.
|
89
|
+
So, on my machine, using <b>Localmemcache</b> 0.4.0 to store key-value
|
84
90
|
data on disk is about <b>10</b>% slower than keeping them in memory in a
|
85
|
-
Ruby hash of strings.
|
86
|
-
|
87
|
-
persistence and parallel writes like <b>Localmemcache</b> does.
|
91
|
+
Ruby hash of strings. It's about 70% faster than <b>Tokyo Cabinet</b>
|
92
|
+
(which offers features similar to <b>LocalMemCache</b>).
|
88
93
|
|
89
94
|
<h2>Source code</h2>
|
90
95
|
|
@@ -115,4 +120,15 @@ Localmemcache is freely distributable under the terms of an
|
|
115
120
|
</div>
|
116
121
|
|
117
122
|
</body>
|
123
|
+
<script type="text/javascript">
|
124
|
+
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl."
|
125
|
+
: "http://www.");
|
126
|
+
document.write(unescape("%3Cscript src='" + gaJsHost +
|
127
|
+
"google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
|
128
|
+
</script>
|
129
|
+
<script type="text/javascript">
|
130
|
+
try {
|
131
|
+
var pageTracker = _gat._getTracker("UA-657352-3");
|
132
|
+
pageTracker._trackPageview();
|
133
|
+
} catch(err) {}</script>
|
118
134
|
</html>
|
data/src/lmc_common.c
CHANGED
@@ -51,7 +51,8 @@ void lmc_clean_string(char *result, const char *source) {
|
|
51
51
|
for (; n--; d++, s++) {
|
52
52
|
ch = *s;
|
53
53
|
if ((ch >= 'a' && ch <= 'z') ||
|
54
|
-
(ch >= 'A' && ch <= 'Z')
|
54
|
+
(ch >= 'A' && ch <= 'Z') ||
|
55
|
+
(ch >= '0' && ch <= '9')) {
|
55
56
|
*d = ch;
|
56
57
|
} else {
|
57
58
|
*d = '-';
|
data/src/lmc_common.h
CHANGED
data/src/lmc_hashtable.c
CHANGED
@@ -131,6 +131,7 @@ int ht_set(void *base, va_ht_hash_t va_ht, const char *key,
|
|
131
131
|
hr->va_next = ht->va_buckets[v];
|
132
132
|
ht->va_buckets[v] = va;
|
133
133
|
hr->va_value = l->va_value;
|
134
|
+
ht->size += 1;
|
134
135
|
lmc_log_finish(base);
|
135
136
|
} else {
|
136
137
|
LMC_TEST_CRASH
|
@@ -174,6 +175,7 @@ int ht_delete(void *base, va_ht_hash_t va_ht, const char *key, size_t n_key) {
|
|
174
175
|
lmc_free(base, hr->va_key);
|
175
176
|
lmc_free(base, hr->va_value);
|
176
177
|
lmc_free(base, va_hr);
|
178
|
+
ht->size -= 1;
|
177
179
|
return 1;
|
178
180
|
|
179
181
|
next:
|
@@ -183,21 +185,79 @@ int ht_delete(void *base, va_ht_hash_t va_ht, const char *key, size_t n_key) {
|
|
183
185
|
}
|
184
186
|
|
185
187
|
int ht_hash_iterate(void *base, va_ht_hash_t va_ht, void *ctx,
|
186
|
-
LMC_ITERATOR_P(iter)) {
|
188
|
+
size_t *ofs, LMC_ITERATOR_P(iter)) {
|
187
189
|
va_ht_hash_entry_t va_hr;
|
188
190
|
ht_hash_entry_t *hr = &lmc_null_node;
|
189
191
|
ht_hash_t *ht = base + va_ht;
|
190
192
|
size_t k;
|
193
|
+
size_t item_c = 0;
|
194
|
+
size_t slice_counter = 0;
|
191
195
|
for (k = 0; k < LMC_HT_BUCKETS; k++) {
|
192
196
|
for (va_hr = ht->va_buckets[k]; va_hr != 0 && hr != NULL;
|
193
197
|
va_hr = hr->va_next) {
|
194
198
|
hr = va_hr ? base + va_hr : 0;
|
195
|
-
|
199
|
+
if (*ofs < ++item_c) {
|
200
|
+
iter(ctx, base + hr->va_key, base + hr->va_value);
|
201
|
+
if (++slice_counter > 999) {
|
202
|
+
*ofs = item_c;
|
203
|
+
return 2;
|
204
|
+
}
|
205
|
+
}
|
196
206
|
}
|
197
207
|
}
|
198
208
|
return 1;
|
199
209
|
}
|
200
210
|
|
211
|
+
int ht_random_pair(void *base, va_ht_hash_t va_ht, char **r_key,
|
212
|
+
size_t *n_key, char **r_value, size_t *n_value) {
|
213
|
+
va_ht_hash_entry_t va_hr;
|
214
|
+
ht_hash_t *ht = base + va_ht;
|
215
|
+
ht_hash_entry_t *hr = &lmc_null_node;
|
216
|
+
size_t k;
|
217
|
+
int rk = -1;
|
218
|
+
int filled_buckets = 0;
|
219
|
+
for (k = 0; k < LMC_HT_BUCKETS; k++) {
|
220
|
+
if (ht->va_buckets[k]) { filled_buckets++; }
|
221
|
+
}
|
222
|
+
if (filled_buckets == 0) { *r_key = 0x0; r_value = 0x0; return 0; }
|
223
|
+
int bnr = rand() % filled_buckets;
|
224
|
+
for (k = 0; k < LMC_HT_BUCKETS; k++) {
|
225
|
+
if (ht->va_buckets[k] && bnr-- < 1) {
|
226
|
+
rk = k;
|
227
|
+
break;
|
228
|
+
}
|
229
|
+
}
|
230
|
+
if (rk == -1) {
|
231
|
+
printf("WHOA: Bucket not found!\n");
|
232
|
+
abort();
|
233
|
+
}
|
234
|
+
int pair_counter = 0;
|
235
|
+
hr = &lmc_null_node;
|
236
|
+
for (va_hr = ht->va_buckets[rk]; va_hr != 0 && hr != NULL;
|
237
|
+
va_hr = hr->va_next) {
|
238
|
+
hr = va_hr ? base + va_hr : 0;
|
239
|
+
pair_counter++;
|
240
|
+
}
|
241
|
+
int random_pair = rand() % pair_counter;
|
242
|
+
hr = &lmc_null_node;
|
243
|
+
for (va_hr = ht->va_buckets[rk]; va_hr != 0 && hr != NULL;
|
244
|
+
va_hr = hr->va_next) {
|
245
|
+
hr = va_hr ? base + va_hr : 0;
|
246
|
+
if (random_pair-- < 1) {
|
247
|
+
char *k = base + hr->va_key;
|
248
|
+
char *v = base + hr->va_value;
|
249
|
+
*r_key = lmc_string_data(k);
|
250
|
+
*n_key = lmc_string_len(k);
|
251
|
+
*r_value = lmc_string_data(v);
|
252
|
+
*n_value = lmc_string_len(v);
|
253
|
+
return 1;
|
254
|
+
}
|
255
|
+
}
|
256
|
+
printf("whoa no random entry found!\n");
|
257
|
+
abort();
|
258
|
+
return 0;
|
259
|
+
}
|
260
|
+
|
201
261
|
int ht_check_memory(void *base, va_ht_hash_t va_ht) {
|
202
262
|
char *bf = lmc_um_new_mem_usage_bitmap(base);
|
203
263
|
if (!bf) return 0;
|
data/src/lmc_hashtable.h
CHANGED
@@ -22,6 +22,7 @@ typedef struct {
|
|
22
22
|
|
23
23
|
typedef size_t va_ht_hash_t;
|
24
24
|
typedef struct {
|
25
|
+
size_t size;
|
25
26
|
va_ht_hash_entry_t va_buckets[LMC_HT_BUCKETS];
|
26
27
|
} ht_hash_t;
|
27
28
|
|
@@ -34,8 +35,10 @@ const char *ht_get(void *base, va_ht_hash_t va_ht, const char *key, size_t n_key
|
|
34
35
|
size_t *n_value);
|
35
36
|
int ht_delete(void *base, va_ht_hash_t va_ht, const char *key, size_t n_key);
|
36
37
|
int ht_hash_destroy(void *base, va_ht_hash_t ht);
|
37
|
-
int ht_hash_iterate(void *base, va_ht_hash_t ht, void *ctx,
|
38
|
+
int ht_hash_iterate(void *base, va_ht_hash_t ht, void *ctx, size_t *ofs,
|
38
39
|
LMC_ITERATOR_P(iter));
|
40
|
+
int ht_random_pair(void *base, va_ht_hash_t va_ht, char **r_key,
|
41
|
+
size_t *n_key, char **r_value, size_t *n_value);
|
39
42
|
|
40
43
|
int ht_check_memory(void *base, va_ht_hash_t va_ht);
|
41
44
|
int ht_redo(void *base, va_ht_hash_t va_ht, lmc_log_descriptor_t *l,
|
data/src/lmc_shm.c
CHANGED
@@ -73,15 +73,13 @@ void lmc_shm_ensure_namespace_file(const char *ns) {
|
|
73
73
|
if (!lmc_does_namespace_exist(ns)) { close(open(fn, O_CREAT, 0777)); }
|
74
74
|
}
|
75
75
|
|
76
|
-
lmc_shm_t *lmc_shm_create(const char* namespace, size_t size,
|
77
|
-
lmc_error_t *e) {
|
76
|
+
lmc_shm_t *lmc_shm_create(const char* namespace, size_t size, lmc_error_t *e) {
|
78
77
|
lmc_shm_t *mc = calloc(1, sizeof(lmc_shm_t));
|
79
78
|
if (!mc) {
|
80
79
|
STD_OUT_OF_MEMORY_ERROR("lmc_shm_create");
|
81
80
|
return NULL;
|
82
81
|
}
|
83
82
|
snprintf((char *)&mc->namespace, 1023, "%s", namespace);
|
84
|
-
mc->use_persistence = 0;
|
85
83
|
mc->size = size;
|
86
84
|
|
87
85
|
lmc_shm_ensure_namespace_file(mc->namespace);
|
data/src/lmc_shm.h
CHANGED
@@ -10,12 +10,10 @@ typedef struct {
|
|
10
10
|
int fd;
|
11
11
|
void *base;
|
12
12
|
size_t size;
|
13
|
-
int use_persistence;
|
14
13
|
char namespace[1024];
|
15
14
|
} lmc_shm_t;
|
16
15
|
|
17
|
-
lmc_shm_t *lmc_shm_create(const char *namespace, size_t size,
|
18
|
-
lmc_error_t *e);
|
16
|
+
lmc_shm_t *lmc_shm_create(const char *namespace, size_t size, lmc_error_t *e);
|
19
17
|
int lmc_shm_destroy(lmc_shm_t *mc, lmc_error_t *e);
|
20
18
|
int lmc_does_namespace_exist(const char *ns);
|
21
19
|
int lmc_namespace_size(const char *ns);
|
data/src/lmc_valloc.c
CHANGED
@@ -116,6 +116,11 @@ void lmc_init_memory(void *ptr, size_t size) {
|
|
116
116
|
c->size = s;
|
117
117
|
}
|
118
118
|
|
119
|
+
size_t lmc_get_db_version(void *ptr) {
|
120
|
+
lmc_mem_descriptor_t *md = ptr;
|
121
|
+
return md->version;
|
122
|
+
}
|
123
|
+
|
119
124
|
size_t lmc_max(size_t a, size_t b) {
|
120
125
|
return a > b ? a : b;
|
121
126
|
}
|
data/src/lmc_valloc.h
CHANGED
@@ -41,6 +41,7 @@ void lmc_free(void *base, size_t chunk);
|
|
41
41
|
lmc_mem_status_t lmc_status(void *base, char *where);
|
42
42
|
int is_lmc_already_initialized(void *base);
|
43
43
|
void lmc_init_memory(void *ptr, size_t size);
|
44
|
+
size_t lmc_get_db_version(void *ptr);
|
44
45
|
|
45
46
|
int lmc_um_mark_allocated(void *base, char *bf, size_t va);
|
46
47
|
char *lmc_um_new_mem_usage_bitmap(void *base);
|
data/src/localmemcache.c
CHANGED
@@ -55,13 +55,13 @@ int lmc_namespace_or_filename(char *result, const char* ons, const char *ofn,
|
|
55
55
|
return 0;
|
56
56
|
}
|
57
57
|
|
58
|
-
int
|
59
|
-
int
|
58
|
+
int local_memcache_drop_namespace(const char *namespace, const char *filename,
|
59
|
+
int force, lmc_error_t *e) {
|
60
60
|
char clean_ns[1024];
|
61
61
|
if (!lmc_namespace_or_filename((char *)clean_ns, namespace, filename, e))
|
62
62
|
return 1;
|
63
63
|
lmc_clean_namespace((char *)clean_ns, e);
|
64
|
-
if (
|
64
|
+
if (force) {
|
65
65
|
lmc_lock_t *l = lmc_lock_init((char *)clean_ns, 1, e);
|
66
66
|
lmc_lock_repair(l);
|
67
67
|
free(l);
|
@@ -106,7 +106,7 @@ retry:
|
|
106
106
|
{
|
107
107
|
if (*ok && !lmc_lock_obtain("local_memcache_create", lmc->lock, &lmc->error))
|
108
108
|
goto failed;
|
109
|
-
if ((lmc->shm = lmc_shm_create(lmc->namespace, lmc->size,
|
109
|
+
if ((lmc->shm = lmc_shm_create(lmc->namespace, lmc->size, e)) == NULL)
|
110
110
|
goto release_and_fail;
|
111
111
|
lmc->base = lmc->shm->base;
|
112
112
|
if (!*ok || is_lmc_already_initialized(lmc->base)) {
|
@@ -114,6 +114,11 @@ retry:
|
|
114
114
|
if (!force) goto release_and_fail;
|
115
115
|
*ok = 0;
|
116
116
|
}
|
117
|
+
if (lmc_get_db_version(lmc->base) != LMC_DB_VERSION) {
|
118
|
+
lmc_handle_error_with_err_string("local_memcache_create",
|
119
|
+
"DB version is incompatible", "DBVersionNotSupported", e);
|
120
|
+
goto unlock_and_fail;
|
121
|
+
}
|
117
122
|
lmc_mem_descriptor_t *md = lmc->base;
|
118
123
|
lmc->va_hash = md->va_hash;
|
119
124
|
} else {
|
@@ -230,8 +235,6 @@ int local_memcache_check_namespace(const char *namespace, const char *filename,
|
|
230
235
|
return __local_memcache_check_namespace(clean_ns, e);
|
231
236
|
}
|
232
237
|
|
233
|
-
|
234
|
-
|
235
238
|
int lmc_lock_shm_region(const char *who, local_memcache_t *lmc) {
|
236
239
|
int r;
|
237
240
|
int retry_counter = 0;
|
@@ -279,6 +282,27 @@ char *local_memcache_get_new(local_memcache_t *lmc,
|
|
279
282
|
return new_s;
|
280
283
|
}
|
281
284
|
|
285
|
+
int __local_memcache_random_pair(local_memcache_t *lmc,
|
286
|
+
char **r_key, size_t *n_key, char **r_value, size_t *n_value) {
|
287
|
+
if (!lmc_lock_shm_region("local_memcache_random_pair", lmc)) return 0;
|
288
|
+
return ht_random_pair(lmc->base, lmc->va_hash, r_key, n_key, r_value,
|
289
|
+
n_value);
|
290
|
+
}
|
291
|
+
|
292
|
+
int local_memcache_random_pair_new(local_memcache_t *lmc,
|
293
|
+
char **r_key, size_t *n_key, char **r_value, size_t *n_value) {
|
294
|
+
char *k;
|
295
|
+
char *v;
|
296
|
+
if (__local_memcache_random_pair(lmc, &k, n_key, &v, n_value)) {
|
297
|
+
char *new_k = malloc(*n_key);
|
298
|
+
memcpy(new_k, k, *n_key);
|
299
|
+
char *new_v = malloc(*n_value);
|
300
|
+
memcpy(new_v, v, *n_value);
|
301
|
+
}
|
302
|
+
if (!lmc_unlock_shm_region("local_memcache_random_pair", lmc)) return 0;
|
303
|
+
return 1;
|
304
|
+
}
|
305
|
+
|
282
306
|
int local_memcache_set(local_memcache_t *lmc,
|
283
307
|
const char *key, size_t n_key, const char* value, size_t n_value) {
|
284
308
|
if (!lmc_lock_shm_region("local_memcache_set", lmc)) return 0;
|
@@ -288,6 +312,17 @@ int local_memcache_set(local_memcache_t *lmc,
|
|
288
312
|
return r;
|
289
313
|
}
|
290
314
|
|
315
|
+
int local_memcache_clear(local_memcache_t *lmc) {
|
316
|
+
if (!lmc_lock_shm_region("local_memcache_clear", lmc)) return 0;
|
317
|
+
lmc_init_memory(lmc->base, lmc->size);
|
318
|
+
lmc_mem_descriptor_t *md = lmc->base;
|
319
|
+
int r = 1;
|
320
|
+
if ((md->va_hash = ht_hash_create(lmc->base, &lmc->error)) == 0) { r = 0; }
|
321
|
+
else { lmc->va_hash = md->va_hash; }
|
322
|
+
if (!lmc_unlock_shm_region("local_memcache_clear", lmc)) return 0;
|
323
|
+
return r;
|
324
|
+
}
|
325
|
+
|
291
326
|
int local_memcache_delete(local_memcache_t *lmc, char *key, size_t n_key) {
|
292
327
|
if (!lmc_lock_shm_region("local_memcache_delete", lmc)) return 0;
|
293
328
|
int r = ht_delete(lmc->base, lmc->va_hash, key, n_key);
|
@@ -306,9 +341,9 @@ int local_memcache_free(local_memcache_t *lmc, lmc_error_t *e) {
|
|
306
341
|
}
|
307
342
|
|
308
343
|
int local_memcache_iterate(local_memcache_t *lmc, void *ctx,
|
309
|
-
LMC_ITERATOR_P(iter)) {
|
344
|
+
size_t *ofs, LMC_ITERATOR_P(iter)) {
|
310
345
|
if (!lmc_lock_shm_region("local_memcache_iterate", lmc)) return 0;
|
311
|
-
int r = ht_hash_iterate(lmc->base, lmc->va_hash, ctx, iter);
|
346
|
+
int r = ht_hash_iterate(lmc->base, lmc->va_hash, ctx, ofs, iter);
|
312
347
|
if (!lmc_unlock_shm_region("local_memcache_iterate", lmc)) return 0;
|
313
348
|
return r;
|
314
349
|
}
|