localmemcache 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +18 -11
- data/Rakefile +22 -7
- data/VERSION +1 -1
- data/bench/common.rb +7 -0
- data/bench/gdbm_vs_lmc +10 -0
- data/bench/gdbm_vs_lmc.rb +29 -0
- data/bench/lmc_bench +11 -0
- data/bench/lmc_bench.rb +27 -0
- data/bench/memcached_bench +8 -0
- data/bench/memcached_bench.rb +19 -0
- data/bench/tyrant_bench +10 -0
- data/bench/tyrant_bench.rb +19 -0
- data/example/hello.c +1 -1
- data/site/doc/classes/LocalMemCache/ArgError.html +113 -0
- data/site/doc/classes/LocalMemCache/InitError.html +113 -0
- data/site/doc/classes/LocalMemCache/LocalMemCacheError.html +111 -0
- data/site/doc/classes/LocalMemCache/LockError.html +113 -0
- data/site/doc/classes/LocalMemCache/LockTimedOut.html +113 -0
- data/site/doc/classes/LocalMemCache/MemoryPoolClosed.html +113 -0
- data/site/doc/classes/LocalMemCache/MemoryPoolFull.html +113 -0
- data/site/doc/classes/LocalMemCache/OutOfMemoryError.html +113 -0
- data/site/doc/classes/LocalMemCache/RecoveryFailed.html +113 -0
- data/site/doc/classes/LocalMemCache/ShmError.html +113 -0
- data/site/doc/classes/LocalMemCache/ShmLockFailed.html +113 -0
- data/site/doc/classes/LocalMemCache/ShmUnlockFailed.html +113 -0
- data/site/doc/classes/LocalMemCache.html +515 -0
- data/site/doc/classes/LocalMemCache.src/M000001.html +19 -0
- data/site/doc/classes/LocalMemCache.src/M000002.html +18 -0
- data/site/doc/classes/LocalMemCache.src/M000003.html +18 -0
- data/site/doc/classes/LocalMemCache.src/M000004.html +39 -0
- data/site/doc/classes/LocalMemCache.src/M000005.html +29 -0
- data/site/doc/classes/LocalMemCache.src/M000006.html +23 -0
- data/site/doc/classes/LocalMemCache.src/M000007.html +23 -0
- data/site/doc/classes/LocalMemCache.src/M000008.html +22 -0
- data/site/doc/classes/LocalMemCache.src/M000009.html +24 -0
- data/site/doc/classes/LocalMemCache.src/M000010.html +24 -0
- data/site/doc/classes/LocalMemCache.src/M000011.html +22 -0
- data/site/doc/classes/LocalMemCache.src/M000012.html +22 -0
- data/site/doc/created.rid +1 -0
- data/site/doc/files/__/src/ruby-binding/extconf_rb.html +108 -0
- data/site/doc/files/__/src/ruby-binding/localmemcache_rb.html +108 -0
- data/site/doc/files/__/src/ruby-binding/rblocalmemcache_c.html +101 -0
- data/site/doc/fr_class_index.html +39 -0
- data/site/doc/fr_file_index.html +28 -0
- data/site/doc/fr_method_index.html +38 -0
- data/site/doc/index.html +24 -0
- data/site/doc/rdoc-style.css +208 -0
- data/site/index.html +50 -46
- data/src/lmc_common.c +22 -0
- data/src/lmc_common.h +4 -0
- data/src/lmc_hashtable.h +1 -1
- data/src/lmc_lock.c +17 -3
- data/src/lmc_shm.c +4 -2
- data/src/lmc_valloc.c +6 -5
- data/src/lmc_valloc.h +1 -0
- data/src/localmemcache.c +56 -35
- data/src/localmemcache.h +161 -4
- data/src/ruby-binding/localmemcache.rb +48 -16
- data/src/ruby-binding/rblocalmemcache.c +131 -24
- data/src/tests/bench.rb +1 -1
- data/src/tests/lmc.rb +11 -2
- metadata +48 -7
- data/INTERNALS +0 -26
- data/example/hello.bin +0 -0
@@ -0,0 +1,208 @@
|
|
1
|
+
|
2
|
+
body {
|
3
|
+
font-family: Verdana,Arial,Helvetica,sans-serif;
|
4
|
+
font-size: 90%;
|
5
|
+
margin: 0;
|
6
|
+
margin-left: 40px;
|
7
|
+
padding: 0;
|
8
|
+
background: white;
|
9
|
+
}
|
10
|
+
|
11
|
+
h1,h2,h3,h4 { margin: 0; color: #efefef; background: transparent; }
|
12
|
+
h1 { font-size: 150%; }
|
13
|
+
h2,h3,h4 { margin-top: 1em; }
|
14
|
+
|
15
|
+
a { background: #eef; color: #039; text-decoration: none; }
|
16
|
+
a:hover { background: #039; color: #eef; }
|
17
|
+
|
18
|
+
/* Override the base stylesheet's Anchor inside a table cell */
|
19
|
+
td > a {
|
20
|
+
background: transparent;
|
21
|
+
color: #039;
|
22
|
+
text-decoration: none;
|
23
|
+
}
|
24
|
+
|
25
|
+
/* and inside a section title */
|
26
|
+
.section-title > a {
|
27
|
+
background: transparent;
|
28
|
+
color: #eee;
|
29
|
+
text-decoration: none;
|
30
|
+
}
|
31
|
+
|
32
|
+
/* === Structural elements =================================== */
|
33
|
+
|
34
|
+
div#index {
|
35
|
+
margin: 0;
|
36
|
+
margin-left: -40px;
|
37
|
+
padding: 0;
|
38
|
+
font-size: 90%;
|
39
|
+
}
|
40
|
+
|
41
|
+
|
42
|
+
div#index a {
|
43
|
+
margin-left: 0.7em;
|
44
|
+
}
|
45
|
+
|
46
|
+
div#index .section-bar {
|
47
|
+
margin-left: 0px;
|
48
|
+
padding-left: 0.7em;
|
49
|
+
background: #ccc;
|
50
|
+
font-size: small;
|
51
|
+
}
|
52
|
+
|
53
|
+
|
54
|
+
div#classHeader, div#fileHeader {
|
55
|
+
width: auto;
|
56
|
+
color: white;
|
57
|
+
padding: 0.5em 1.5em 0.5em 1.5em;
|
58
|
+
margin: 0;
|
59
|
+
margin-left: -40px;
|
60
|
+
border-bottom: 3px solid #006;
|
61
|
+
}
|
62
|
+
|
63
|
+
div#classHeader a, div#fileHeader a {
|
64
|
+
background: inherit;
|
65
|
+
color: white;
|
66
|
+
}
|
67
|
+
|
68
|
+
div#classHeader td, div#fileHeader td {
|
69
|
+
background: inherit;
|
70
|
+
color: white;
|
71
|
+
}
|
72
|
+
|
73
|
+
|
74
|
+
div#fileHeader {
|
75
|
+
background: #057;
|
76
|
+
}
|
77
|
+
|
78
|
+
div#classHeader {
|
79
|
+
background: #048;
|
80
|
+
}
|
81
|
+
|
82
|
+
|
83
|
+
.class-name-in-header {
|
84
|
+
font-size: 180%;
|
85
|
+
font-weight: bold;
|
86
|
+
}
|
87
|
+
|
88
|
+
|
89
|
+
div#bodyContent {
|
90
|
+
padding: 0 1.5em 0 1.5em;
|
91
|
+
}
|
92
|
+
|
93
|
+
div#description {
|
94
|
+
padding: 0.5em 1.5em;
|
95
|
+
background: #efefef;
|
96
|
+
border: 1px dotted #999;
|
97
|
+
}
|
98
|
+
|
99
|
+
div#description h1,h2,h3,h4,h5,h6 {
|
100
|
+
color: #125;;
|
101
|
+
background: transparent;
|
102
|
+
}
|
103
|
+
|
104
|
+
div#validator-badges {
|
105
|
+
text-align: center;
|
106
|
+
}
|
107
|
+
div#validator-badges img { border: 0; }
|
108
|
+
|
109
|
+
div#copyright {
|
110
|
+
color: #333;
|
111
|
+
background: #efefef;
|
112
|
+
font: 0.75em sans-serif;
|
113
|
+
margin-top: 5em;
|
114
|
+
margin-bottom: 0;
|
115
|
+
padding: 0.5em 2em;
|
116
|
+
}
|
117
|
+
|
118
|
+
|
119
|
+
/* === Classes =================================== */
|
120
|
+
|
121
|
+
table.header-table {
|
122
|
+
color: white;
|
123
|
+
font-size: small;
|
124
|
+
}
|
125
|
+
|
126
|
+
.type-note {
|
127
|
+
font-size: small;
|
128
|
+
color: #DEDEDE;
|
129
|
+
}
|
130
|
+
|
131
|
+
.xxsection-bar {
|
132
|
+
background: #eee;
|
133
|
+
color: #333;
|
134
|
+
padding: 3px;
|
135
|
+
}
|
136
|
+
|
137
|
+
.section-bar {
|
138
|
+
color: #333;
|
139
|
+
border-bottom: 1px solid #999;
|
140
|
+
margin-left: -20px;
|
141
|
+
}
|
142
|
+
|
143
|
+
|
144
|
+
.section-title {
|
145
|
+
background: #79a;
|
146
|
+
color: #eee;
|
147
|
+
padding: 3px;
|
148
|
+
margin-top: 2em;
|
149
|
+
margin-left: -30px;
|
150
|
+
border: 1px solid #999;
|
151
|
+
}
|
152
|
+
|
153
|
+
.top-aligned-row { vertical-align: top }
|
154
|
+
.bottom-aligned-row { vertical-align: bottom }
|
155
|
+
|
156
|
+
/* --- Context section classes ----------------------- */
|
157
|
+
|
158
|
+
.context-row { }
|
159
|
+
.context-item-name { font-family: monospace; font-weight: bold; color: black; }
|
160
|
+
.context-item-value { font-size: small; color: #448; }
|
161
|
+
.context-item-desc { color: #333; padding-left: 2em; }
|
162
|
+
|
163
|
+
/* --- Method classes -------------------------- */
|
164
|
+
.method-detail {
|
165
|
+
background: #efefef;
|
166
|
+
padding: 0;
|
167
|
+
margin-top: 0.5em;
|
168
|
+
margin-bottom: 1em;
|
169
|
+
border: 1px dotted #ccc;
|
170
|
+
}
|
171
|
+
.method-heading {
|
172
|
+
color: black;
|
173
|
+
background: #ccc;
|
174
|
+
border-bottom: 1px solid #666;
|
175
|
+
padding: 0.2em 0.5em 0 0.5em;
|
176
|
+
}
|
177
|
+
.method-signature { color: black; background: inherit; }
|
178
|
+
.method-name { font-weight: bold; }
|
179
|
+
.method-args { font-style: italic; }
|
180
|
+
.method-description { padding: 0 0.5em 0 0.5em; }
|
181
|
+
|
182
|
+
/* --- Source code sections -------------------- */
|
183
|
+
|
184
|
+
a.source-toggle { font-size: 90%; }
|
185
|
+
div.method-source-code {
|
186
|
+
background: #262626;
|
187
|
+
color: #ffdead;
|
188
|
+
margin: 1em;
|
189
|
+
padding: 0.5em;
|
190
|
+
border: 1px dashed #999;
|
191
|
+
overflow: hidden;
|
192
|
+
}
|
193
|
+
|
194
|
+
div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
195
|
+
|
196
|
+
/* --- Ruby keyword styles --------------------- */
|
197
|
+
|
198
|
+
.standalone-code { background: #221111; color: #ffdead; overflow: hidden; }
|
199
|
+
|
200
|
+
.ruby-constant { color: #7fffd4; background: transparent; }
|
201
|
+
.ruby-keyword { color: #00ffff; background: transparent; }
|
202
|
+
.ruby-ivar { color: #eedd82; background: transparent; }
|
203
|
+
.ruby-operator { color: #00ffee; background: transparent; }
|
204
|
+
.ruby-identifier { color: #ffdead; background: transparent; }
|
205
|
+
.ruby-node { color: #ffa07a; background: transparent; }
|
206
|
+
.ruby-comment { color: #b22222; font-weight: bold; background: transparent; }
|
207
|
+
.ruby-regexp { color: #ffa07a; background: transparent; }
|
208
|
+
.ruby-value { color: #7fffd4; background: transparent; }
|
data/site/index.html
CHANGED
@@ -7,44 +7,29 @@
|
|
7
7
|
<body>
|
8
8
|
|
9
9
|
<div id="content">
|
10
|
-
<h1>
|
10
|
+
<h1>A persistent key-value database based on mmap()'ed shared memory</h1>
|
11
11
|
|
12
12
|
<p><b>Localmemcache</b> is a library for C and ruby that aims to provide
|
13
13
|
an interface similar to memcached but for accessing local data instead of
|
14
14
|
remote data. It's based on <b>mmap()</b>'ed shared memory for maximum speed.
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
<
|
19
|
-
<li
|
20
|
-
<li
|
21
|
-
|
22
|
-
<
|
23
|
-
<li
|
24
|
-
|
25
|
-
|
26
|
-
<li>
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
accessing the shared memory (eg by <b>kill -9</b>), it is now able to
|
34
|
-
<b>restore the integrity of your data</b>.</li>
|
35
|
-
<li><b>\0 character</b> can now be used in <b>keys</b> and
|
36
|
-
<b>values</b></li>
|
37
|
-
<li>The ruby binding now features a <b>keys()</b> method.</b>
|
38
|
-
<li>Added a <b>C API</b>. See <a href="http://github.com/sck/localmemcache/blob/8c753f74c53b107d271975bedcc1f91a3dbd6961/src/localmemcache.h">localmemcache.h</a></li>
|
39
|
-
|
40
|
-
<h2>Supported Systems</h2>
|
41
|
-
|
42
|
-
<li>Unix (for <b>mmap())</b></li>
|
43
|
-
<li>OS X is currently not supported because it doesn't have
|
44
|
-
sem_timedwait() and sem_getvalue()</li>
|
45
|
-
<li>A CPU architecture with more than <b>32 bits</b> is recommended, since
|
46
|
-
otherwise you might run out of virtual address space when you use larger
|
47
|
-
shared memory segments.</li>
|
15
|
+
Since version 0.3.0 it supports persistence, also making it a fast
|
16
|
+
alternative to GDBM and Berkeley DB.
|
17
|
+
|
18
|
+
<h2>Key features as of 0.3.0 (2009-04-17)</h2>
|
19
|
+
<li><a href="#performance">blazingly fast</a></li>
|
20
|
+
<li>persistent</li>
|
21
|
+
<li>parallel writes are supported by default</li>
|
22
|
+
<li>uses transactions internally to avoid data corruption</li>
|
23
|
+
<li>lightweight: the core library is just about <b>1400</b> lines of <b>C</b> code</li>
|
24
|
+
|
25
|
+
<h2>Requirements</h2>
|
26
|
+
<li>a >=64bit Unix</li>
|
27
|
+
<li>a file system that offers <a href="http://en.wikipedia.org/wiki/Sparse_file">sparse files</a></li>
|
28
|
+
Note for <b>OS X</b>: <b>OS X</b> disqualifies as <b>HFS+</b> doesn't
|
29
|
+
have sparse files and <b>sem_timedwait</b>() and <b>sem_getvalue</b>() aren't
|
30
|
+
supported as well.
|
31
|
+
Note for <b>FreeBSD</b>: It has been reported that Localmemcache
|
32
|
+
sometimes hangs there, it is not yet clear what the problem is.
|
48
33
|
|
49
34
|
<h2>Install</h2>
|
50
35
|
|
@@ -53,19 +38,24 @@ shared memory segments.</li>
|
|
53
38
|
<pre><code>gem install localmemcache
|
54
39
|
</code></pre>
|
55
40
|
|
41
|
+
|
56
42
|
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>.
|
57
43
|
|
58
44
|
<h2>Using</h2>
|
45
|
+
<b>API</b>: <a href="http://github.com/sck/localmemcache/blob/e980ba949034a349dbf0e6f8f9ef77bbe3e3e314/src/localmemcache.h">C</a>|<a href="http://localmemcache.rubyforge.org/doc/">Ruby</a><br>
|
59
46
|
<p><pre><code>require 'localmemcache'
|
60
|
-
|
47
|
+
# 1. the memcached way
|
48
|
+
# $lm = LocalMemCache.new :namespace => :viewcounters
|
49
|
+
# 2. the GDBM way
|
50
|
+
$lm = LocalMemCache.new :filename => "./viewcounters.lmc"
|
61
51
|
$lm[:foo] = 1
|
62
52
|
$lm[:foo]
|
63
53
|
$lm.delete(:foo)
|
64
54
|
</code></pre>
|
65
|
-
(C version of this example: <a href="http://github.com/sck/localmemcache/blob/
|
55
|
+
(C version of this example: <a href="http://github.com/sck/localmemcache/blob/e980ba949034a349dbf0e6f8f9ef77bbe3e3e314/example/hello.c">hello.c</a>)
|
66
56
|
</p>
|
67
|
-
<a href="http://github.com/sck/localmemcache/tree/master">Read more</a>.
|
68
57
|
|
58
|
+
<a name="performance" id="performance"></a>
|
69
59
|
<h2>Performance</h2>
|
70
60
|
|
71
61
|
<p>Here's a quick speed comparison, made on an
|
@@ -79,14 +69,22 @@ Ruby benchmark pseudo code:
|
|
79
69
|
</code></pre>
|
80
70
|
|
81
71
|
<pre>
|
82
|
-
|
83
|
-
|
84
|
-
|
72
|
+
Tokyo Tyrant: <b>298,226.197</b> ms
|
73
|
+
MemCache: <b>253,326.122</b> ms
|
74
|
+
GDBM: <b>24,226.116</b> ms
|
75
|
+
Localmemcache 0.2.2: <b>5,799.225</b> ms
|
76
|
+
Localmemcache 0.3.0: <b>5,300.055</b> ms
|
77
|
+
Ruby Hash of Strings: <b>4,963.313</b> ms
|
85
78
|
</pre>
|
79
|
+
(<a href="http://github.com/sck/localmemcache/tree/e980ba949034a349dbf0e6f8f9ef77bbe3e3e314/bench">Code of the benchmarks used</a>)
|
86
80
|
|
87
|
-
|
88
|
-
|
89
|
-
|
81
|
+
<p>
|
82
|
+
|
83
|
+
So, on my machine, using <b>Localmemcache</b> 0.3.0 to store key-value
|
84
|
+
data on disk is about <b>10</b>% slower than keeping them in memory in a
|
85
|
+
Ruby hash of strings. Also keep in mind that of the above mentioned
|
86
|
+
software components <b>Tokyo Tyrant</b> is the only one that offers
|
87
|
+
persistence and parallel writes like <b>Localmemcache</b> does.
|
90
88
|
|
91
89
|
<h2>Source code</h2>
|
92
90
|
|
@@ -96,10 +94,16 @@ can be retrieved by executing</p>
|
|
96
94
|
<pre><code>git clone git://github.com/sck/localmemcache.git
|
97
95
|
</code></pre>
|
98
96
|
|
99
|
-
<h2>
|
97
|
+
<h2>Tips for backups</h1>
|
98
|
+
|
99
|
+
Note that you cannot copy Localmemcache's .lmc files while other
|
100
|
+
processes are making changes to the data, this will likely result in a
|
101
|
+
corrupt backup. So you need to make sure that none of your processes are
|
102
|
+
writing during the time you do an backup. As for copying sparse files,
|
103
|
+
<b>cp</b> recognizes them automatically, with <b>tar</b> you need to use
|
104
|
+
the <b>-S</b> option.
|
100
105
|
|
101
|
-
|
102
|
-
href="http://github.com/sck/localmemcache/blob/96b5e0863e1da7f17e249a6c8884984e0c23ee2f/INTERNALS">works</a>.
|
106
|
+
<h2><a href="http://localmemcache.rubyforge.org/doc/classes/LocalMemCache.html">Read on / RDoc</a></h2>
|
103
107
|
|
104
108
|
<h2>License</h2>
|
105
109
|
|
data/src/lmc_common.c
CHANGED
@@ -7,6 +7,7 @@
|
|
7
7
|
#include <sys/types.h>
|
8
8
|
#include <unistd.h>
|
9
9
|
#include <stdlib.h>
|
10
|
+
#include <string.h>
|
10
11
|
|
11
12
|
int lmc_test_crash_enabled = 0;
|
12
13
|
int lmc_showed_status = 0;
|
@@ -41,3 +42,24 @@ size_t lmc_test_valloc_fail(const char *file, int line, const char *function,
|
|
41
42
|
return lmc_valloc(base, s);
|
42
43
|
}
|
43
44
|
|
45
|
+
void lmc_clean_string(char *result, const char *source) {
|
46
|
+
size_t n = strlen(source);
|
47
|
+
if (n > 256) { n = 256; }
|
48
|
+
const char *s = source;
|
49
|
+
char *d = result;
|
50
|
+
char ch;
|
51
|
+
for (; n--; d++, s++) {
|
52
|
+
ch = *s;
|
53
|
+
if ((ch >= 'a' && ch <= 'z') ||
|
54
|
+
(ch >= 'A' && ch <= 'Z')) {
|
55
|
+
*d = ch;
|
56
|
+
} else {
|
57
|
+
*d = '-';
|
58
|
+
}
|
59
|
+
}
|
60
|
+
*d = 0x0;
|
61
|
+
}
|
62
|
+
|
63
|
+
int lmc_is_filename(const char *s) {
|
64
|
+
return strlen(s) > 1 && (s[0] == '/' || (s[0] == '.' && s[1] == '/'));
|
65
|
+
}
|
data/src/lmc_common.h
CHANGED
@@ -5,6 +5,8 @@
|
|
5
5
|
#ifndef _LMC_COMMON_H_INCLUDED_
|
6
6
|
#define _LMC_COMMON_H_INCLUDED_
|
7
7
|
|
8
|
+
#define LMC_DB_VERSION 0
|
9
|
+
|
8
10
|
extern int lmc_test_crash_enabled;
|
9
11
|
#ifdef DO_TEST_CRASH
|
10
12
|
#define LMC_TEST_CRASH lmc_test_crash(__FILE__, __LINE__, __FUNCTION__);
|
@@ -21,6 +23,8 @@ extern int lmc_test_crash_enabled;
|
|
21
23
|
void lmc_test_crash(const char* file, int line, const char *function);
|
22
24
|
size_t lmc_test_valloc_fail(const char *file, int line, const char *function,
|
23
25
|
void *base, size_t s);
|
26
|
+
void lmc_clean_string(char *result, const char *source);
|
27
|
+
int lmc_is_filename(const char *s);
|
24
28
|
|
25
29
|
#endif
|
26
30
|
|
data/src/lmc_hashtable.h
CHANGED
data/src/lmc_lock.c
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (c) 2009, Sven C. Koehler
|
3
|
+
*/
|
4
|
+
|
1
5
|
#include <stdio.h>
|
2
6
|
#include <stdlib.h>
|
3
7
|
#include <fcntl.h>
|
@@ -8,11 +12,19 @@
|
|
8
12
|
#include <unistd.h>
|
9
13
|
#include <time.h>
|
10
14
|
#include "lmc_lock.h"
|
15
|
+
#include "lmc_common.h"
|
16
|
+
|
17
|
+
void lmc_namespacify(char *result, const char *s) {
|
18
|
+
if (lmc_is_filename(s)) { lmc_clean_string(result, s); }
|
19
|
+
else { strcpy(result, s); }
|
20
|
+
}
|
11
21
|
|
12
|
-
lmc_lock_t *lmc_lock_init(const char *
|
22
|
+
lmc_lock_t *lmc_lock_init(const char *ns, int init, lmc_error_t *e) {
|
23
|
+
char namespace[1024];
|
24
|
+
lmc_namespacify(namespace, ns);
|
13
25
|
lmc_lock_t *l = malloc(sizeof(lmc_lock_t));
|
14
26
|
if (!l) return NULL;
|
15
|
-
|
27
|
+
snprintf((char *)&l->namespace, 1023, "%s", namespace);
|
16
28
|
|
17
29
|
lmc_handle_error((l->sem = sem_open(l->namespace, O_CREAT, 0600, init)) ==
|
18
30
|
NULL, "sem_open", "LockError", e);
|
@@ -20,7 +32,9 @@ lmc_lock_t *lmc_lock_init(const char *namespace, int init, lmc_error_t *e) {
|
|
20
32
|
return l;
|
21
33
|
}
|
22
34
|
|
23
|
-
int lmc_clear_namespace_lock(const char *
|
35
|
+
int lmc_clear_namespace_lock(const char *ns) {
|
36
|
+
char namespace[1024];
|
37
|
+
lmc_namespacify(namespace, ns);
|
24
38
|
lmc_error_t e;
|
25
39
|
lmc_lock_t *l = lmc_lock_init(namespace, 1, &e);
|
26
40
|
lmc_lock_repair(l);
|
data/src/lmc_shm.c
CHANGED
@@ -11,6 +11,7 @@
|
|
11
11
|
#include <fcntl.h>
|
12
12
|
#include <sys/mman.h>
|
13
13
|
|
14
|
+
#include "lmc_common.h"
|
14
15
|
#include "lmc_shm.h"
|
15
16
|
|
16
17
|
const char *lmc_namespace_root_path() {
|
@@ -37,7 +38,8 @@ void lmc_shm_ensure_root_path() {
|
|
37
38
|
}
|
38
39
|
|
39
40
|
void lmc_file_path_for_namespace(char *result, const char *ns) {
|
40
|
-
snprintf(result, 1023, "%s
|
41
|
+
if (lmc_is_filename(ns)) { snprintf(result, 1023, "%s", ns); }
|
42
|
+
else { snprintf(result, 1023, "%s/%s.lmc", lmc_namespace_root_path(), ns); }
|
41
43
|
}
|
42
44
|
|
43
45
|
int lmc_does_namespace_exist(const char *ns) {
|
@@ -78,7 +80,7 @@ lmc_shm_t *lmc_shm_create(const char* namespace, size_t size, int use_persistenc
|
|
78
80
|
STD_OUT_OF_MEMORY_ERROR("lmc_shm_create");
|
79
81
|
return NULL;
|
80
82
|
}
|
81
|
-
|
83
|
+
snprintf((char *)&mc->namespace, 1023, "%s", namespace);
|
82
84
|
mc->use_persistence = 0;
|
83
85
|
mc->size = size;
|
84
86
|
|
data/src/lmc_valloc.c
CHANGED
@@ -69,7 +69,7 @@ lmc_mem_status_t lmc_status(void *base, char *where) {
|
|
69
69
|
ms.total_mem = md->total_size;
|
70
70
|
while (c) {
|
71
71
|
if (!lmc_is_va_valid(base, (void *)c - base)) {
|
72
|
-
printf("
|
72
|
+
printf("[localmemcache] [%s] invalid pointer detected: %zd...\n", where,
|
73
73
|
(void *)c - base);
|
74
74
|
lmc_dump(base);
|
75
75
|
abort();
|
@@ -108,7 +108,8 @@ void lmc_init_memory(void *ptr, size_t size) {
|
|
108
108
|
size_t s = size - sizeof(lmc_mem_descriptor_t);
|
109
109
|
md->first_free = sizeof(lmc_mem_descriptor_t);
|
110
110
|
md->magic = 0xF00D;
|
111
|
-
md->
|
111
|
+
md->version = LMC_DB_VERSION;
|
112
|
+
md->locked = 1;
|
112
113
|
md->total_size = s;
|
113
114
|
lmc_mem_chunk_descriptor_t *c = ptr + sizeof(lmc_mem_descriptor_t);
|
114
115
|
c->next = 0;
|
@@ -319,7 +320,7 @@ void lmc_free(void *base, size_t chunk) {
|
|
319
320
|
if (chunk == 0) { return; }
|
320
321
|
if (!(chunk >= sizeof(lmc_mem_descriptor_t) + sizeof(size_t)) ||
|
321
322
|
!lmc_is_va_valid(base, chunk)) {
|
322
|
-
|
323
|
+
fprintf(stderr, "[localmemcache] lmc_free: Invalid pointer: %zd\n", chunk);
|
323
324
|
return;
|
324
325
|
}
|
325
326
|
size_t va_used_chunk = chunk - sizeof(size_t);
|
@@ -396,8 +397,8 @@ int lmc_um_mark(void *base, char *bf, size_t va, size_t size) {
|
|
396
397
|
lmc_mem_descriptor_t *md = base;
|
397
398
|
if ((va > sizeof(lmc_mem_descriptor_t)) &&
|
398
399
|
(!lmc_is_va_valid(base, va) || !lmc_is_va_valid(base, va + size))) {
|
399
|
-
printf("
|
400
|
-
va, va + size, md->total_size);
|
400
|
+
printf("[localmemcache] Error: VA start out of range: "
|
401
|
+
"va: %zd - %zd max %zd!\n", va, va + size, md->total_size);
|
401
402
|
return 0;
|
402
403
|
}
|
403
404
|
if (!lmc_um_check_unmarked(base, bf, va, size)) return 0;
|