localmemcache 0.3.0 → 0.4.0
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 +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
|
}
|