localmemcache 0.2.2 → 0.3.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 +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;
|