sophia-ruby 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.gitmodules +3 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +22 -0
- data/ext/extconf.rb +13 -0
- data/ext/sophia.c +220 -0
- data/lib/sophia-ruby.rb +1 -0
- data/lib/sophia/version.rb +3 -0
- data/sophia-ruby.gemspec +47 -0
- data/test/test_sophia.rb +33 -0
- data/vendor/sophia/.gitignore +18 -0
- data/vendor/sophia/COPYRIGHT +29 -0
- data/vendor/sophia/README +5 -0
- data/vendor/sophia/db/a.h +58 -0
- data/vendor/sophia/db/cat.c +195 -0
- data/vendor/sophia/db/cat.h +32 -0
- data/vendor/sophia/db/core.h +129 -0
- data/vendor/sophia/db/crc.c +343 -0
- data/vendor/sophia/db/crc.h +14 -0
- data/vendor/sophia/db/cursor.c +551 -0
- data/vendor/sophia/db/cursor.h +47 -0
- data/vendor/sophia/db/e.c +49 -0
- data/vendor/sophia/db/e.h +49 -0
- data/vendor/sophia/db/file.c +355 -0
- data/vendor/sophia/db/file.h +106 -0
- data/vendor/sophia/db/gc.c +71 -0
- data/vendor/sophia/db/gc.h +14 -0
- data/vendor/sophia/db/i.c +368 -0
- data/vendor/sophia/db/i.h +155 -0
- data/vendor/sophia/db/list.h +91 -0
- data/vendor/sophia/db/lock.h +77 -0
- data/vendor/sophia/db/macro.h +20 -0
- data/vendor/sophia/db/makefile +44 -0
- data/vendor/sophia/db/merge.c +662 -0
- data/vendor/sophia/db/merge.h +14 -0
- data/vendor/sophia/db/meta.h +87 -0
- data/vendor/sophia/db/recover.c +433 -0
- data/vendor/sophia/db/recover.h +14 -0
- data/vendor/sophia/db/ref.h +111 -0
- data/vendor/sophia/db/rep.c +128 -0
- data/vendor/sophia/db/rep.h +120 -0
- data/vendor/sophia/db/sophia.h +84 -0
- data/vendor/sophia/db/sp.c +626 -0
- data/vendor/sophia/db/sp.h +50 -0
- data/vendor/sophia/db/task.h +70 -0
- data/vendor/sophia/db/track.h +99 -0
- data/vendor/sophia/db/util.c +105 -0
- data/vendor/sophia/db/util.h +25 -0
- data/vendor/sophia/makefile +7 -0
- data/vendor/sophia/sophia.gyp +30 -0
- data/vendor/sophia/test/common.c +870 -0
- data/vendor/sophia/test/crash.c +492 -0
- data/vendor/sophia/test/i.c +403 -0
- data/vendor/sophia/test/limit.c +65 -0
- data/vendor/sophia/test/makefile +30 -0
- data/vendor/sophia/test/merge.c +890 -0
- data/vendor/sophia/test/recover.c +1550 -0
- data/vendor/sophia/test/test.h +66 -0
- metadata +134 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
Copyright (C) 2013 Dmitry Simonenko (pmwkaa@gmail.com)
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or
|
5
|
+
without modification, are permitted provided that the following
|
6
|
+
conditions are met:
|
7
|
+
|
8
|
+
1. Redistributions of source code must retain the above
|
9
|
+
copyright notice, this list of conditions and the
|
10
|
+
following disclaimer.
|
11
|
+
|
12
|
+
2. Redistributions in binary form must reproduce the above
|
13
|
+
copyright notice, this list of conditions and the following
|
14
|
+
disclaimer in the documentation and/or other materials
|
15
|
+
provided with the distribution.
|
16
|
+
|
17
|
+
THIS SOFTWARE IS PROVIDED BY AUTHORS ``AS IS'' AND
|
18
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
19
|
+
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
20
|
+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
21
|
+
AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
22
|
+
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
23
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
24
|
+
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
25
|
+
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
26
|
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
27
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
28
|
+
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
29
|
+
SUCH DAMAGE.
|
@@ -0,0 +1,58 @@
|
|
1
|
+
#ifndef SP_A_H_
|
2
|
+
#define SP_A_H_
|
3
|
+
|
4
|
+
/*
|
5
|
+
* sophia database
|
6
|
+
* sphia.org
|
7
|
+
*
|
8
|
+
* Copyright (c) Dmitry Simonenko
|
9
|
+
* BSD License
|
10
|
+
*/
|
11
|
+
|
12
|
+
typedef struct spa spa;
|
13
|
+
|
14
|
+
struct spa {
|
15
|
+
spallocf alloc;
|
16
|
+
void *arg;
|
17
|
+
};
|
18
|
+
|
19
|
+
static inline void
|
20
|
+
sp_allocinit(spa *a, spallocf f, void *arg) {
|
21
|
+
a->alloc = f;
|
22
|
+
a->arg = arg;
|
23
|
+
}
|
24
|
+
|
25
|
+
static inline void*
|
26
|
+
sp_allocstd(void *ptr, size_t size, void *arg spunused) {
|
27
|
+
if (splikely(size > 0)) {
|
28
|
+
if (ptr != NULL)
|
29
|
+
return realloc(ptr, size);
|
30
|
+
return malloc(size);
|
31
|
+
}
|
32
|
+
assert(ptr != NULL);
|
33
|
+
free(ptr);
|
34
|
+
return NULL;
|
35
|
+
}
|
36
|
+
|
37
|
+
static inline void *sp_realloc(spa *a, void *ptr, size_t size) {
|
38
|
+
return a->alloc(ptr, size, a->arg);
|
39
|
+
}
|
40
|
+
|
41
|
+
static inline void *sp_malloc(spa *a, size_t size) {
|
42
|
+
return a->alloc(NULL, size, a->arg);
|
43
|
+
}
|
44
|
+
|
45
|
+
static inline char *sp_strdup(spa *a, char *str) {
|
46
|
+
int sz = strlen(str) + 1;
|
47
|
+
char *s = a->alloc(NULL, sz, a->arg);
|
48
|
+
if (spunlikely(s == NULL))
|
49
|
+
return NULL;
|
50
|
+
memcpy(s, str, sz);
|
51
|
+
return s;
|
52
|
+
}
|
53
|
+
|
54
|
+
static inline void sp_free(spa *a, void *ptr) {
|
55
|
+
a->alloc(ptr, 0, a->arg);
|
56
|
+
}
|
57
|
+
|
58
|
+
#endif
|
@@ -0,0 +1,195 @@
|
|
1
|
+
|
2
|
+
/*
|
3
|
+
* sophia database
|
4
|
+
* sphia.org
|
5
|
+
*
|
6
|
+
* Copyright (c) Dmitry Simonenko
|
7
|
+
* BSD License
|
8
|
+
*/
|
9
|
+
|
10
|
+
#include <sp.h>
|
11
|
+
|
12
|
+
static inline int sp_catensure(spcat *c) {
|
13
|
+
if ((c->count + 1) < c->top)
|
14
|
+
return 0;
|
15
|
+
c->top *= 2;
|
16
|
+
c->i = realloc(c->i, c->top * sizeof(sppage*));
|
17
|
+
if (c->i == NULL)
|
18
|
+
return -1;
|
19
|
+
return 0;
|
20
|
+
}
|
21
|
+
|
22
|
+
int sp_catinit(spcat *c, spa *a, int top, spcmpf cmp, void *cmparg) {
|
23
|
+
c->a = a;
|
24
|
+
c->cmp = cmp;
|
25
|
+
c->cmparg = cmparg;
|
26
|
+
c->count = 0;
|
27
|
+
c->top = top;
|
28
|
+
c->i = sp_malloc(a, sizeof(sppage*) * top);
|
29
|
+
if (spunlikely(c->i == NULL))
|
30
|
+
return -1;
|
31
|
+
return 0;
|
32
|
+
}
|
33
|
+
|
34
|
+
void sp_catfree(spcat *c) {
|
35
|
+
uint32_t p = 0;
|
36
|
+
while (p < c->count) {
|
37
|
+
sp_free(c->a, c->i[p]->min);
|
38
|
+
sp_free(c->a, c->i[p]->max);
|
39
|
+
sp_free(c->a, c->i[p]);
|
40
|
+
p++;
|
41
|
+
}
|
42
|
+
sp_free(c->a, c->i);
|
43
|
+
}
|
44
|
+
|
45
|
+
static inline int
|
46
|
+
cmppage(spcat *c, sppage *p, sppage *v) {
|
47
|
+
int l = c->cmp(p->min->key,
|
48
|
+
p->min->size,
|
49
|
+
v->min->key,
|
50
|
+
v->min->size, c->cmparg);
|
51
|
+
assert(l == c->cmp(p->max->key,
|
52
|
+
p->max->size,
|
53
|
+
v->max->key,
|
54
|
+
v->max->size, c->cmparg));
|
55
|
+
return l;
|
56
|
+
}
|
57
|
+
|
58
|
+
static inline sppage*
|
59
|
+
sp_catsearch(spcat *c, sppage *v, uint32_t *index) {
|
60
|
+
int min = 0;
|
61
|
+
int max = c->count - 1;
|
62
|
+
while (max >= min) {
|
63
|
+
int mid = min + ((max - min) >> 1);
|
64
|
+
switch (cmppage(c, c->i[mid], v)) {
|
65
|
+
case -1: min = mid + 1;
|
66
|
+
continue;
|
67
|
+
case 1: max = mid - 1;
|
68
|
+
continue;
|
69
|
+
default:
|
70
|
+
*index = mid;
|
71
|
+
return c->i[mid];
|
72
|
+
}
|
73
|
+
}
|
74
|
+
*index = min;
|
75
|
+
return NULL;
|
76
|
+
}
|
77
|
+
|
78
|
+
int sp_catset(spcat *c, sppage *n, sppage **o)
|
79
|
+
{
|
80
|
+
uint32_t i;
|
81
|
+
sppage *p = sp_catsearch(c, n, &i);
|
82
|
+
if (p) {
|
83
|
+
/* replace */
|
84
|
+
*o = c->i[i];
|
85
|
+
c->i[i] = p;
|
86
|
+
return 0;
|
87
|
+
}
|
88
|
+
/* insert */
|
89
|
+
int rc = sp_catensure(c);
|
90
|
+
if (spunlikely(rc == -1))
|
91
|
+
return -1;
|
92
|
+
/* split page index and insert new page */
|
93
|
+
memmove(&c->i[i + 1], &c->i[i], sizeof(sppage*) * (c->count - i));
|
94
|
+
c->i[i] = n;
|
95
|
+
c->count++;
|
96
|
+
*o = NULL;
|
97
|
+
return 0;
|
98
|
+
}
|
99
|
+
|
100
|
+
int sp_catdel(spcat *c, uint32_t idx)
|
101
|
+
{
|
102
|
+
assert(idx < c->count);
|
103
|
+
if (splikely(idx != (uint32_t)(c->count-1)))
|
104
|
+
memmove(&c->i[idx], &c->i[idx + 1],
|
105
|
+
sizeof(sppage*) * (c->count - idx - 1));
|
106
|
+
c->count--;
|
107
|
+
return 0;
|
108
|
+
}
|
109
|
+
|
110
|
+
static inline int
|
111
|
+
cmpkey(spcat *c, sppage *p, void *rkey, int size)
|
112
|
+
{
|
113
|
+
register int l =
|
114
|
+
c->cmp(p->min->key, p->min->size, rkey, size, c->cmparg);
|
115
|
+
register int r =
|
116
|
+
c->cmp(p->max->key, p->max->size, rkey, size, c->cmparg);
|
117
|
+
/* inside page range */
|
118
|
+
if (l <= 0 && r >= 0)
|
119
|
+
return 0;
|
120
|
+
/* key > page */
|
121
|
+
if (l == -1)
|
122
|
+
return -1;
|
123
|
+
/* key < page */
|
124
|
+
assert(r == 1);
|
125
|
+
return 1;
|
126
|
+
}
|
127
|
+
|
128
|
+
sppage*
|
129
|
+
sp_catfind(spcat *c, char *rkey, int size, uint32_t *index)
|
130
|
+
{
|
131
|
+
register int min = 0;
|
132
|
+
register int max = c->count - 1;
|
133
|
+
while (max >= min) {
|
134
|
+
register int mid = min + ((max - min) >> 1);
|
135
|
+
switch (cmpkey(c, c->i[mid], rkey, size)) {
|
136
|
+
case -1: min = mid + 1;
|
137
|
+
continue;
|
138
|
+
case 1: max = mid - 1;
|
139
|
+
continue;
|
140
|
+
default: *index = mid;
|
141
|
+
return c->i[mid];
|
142
|
+
}
|
143
|
+
}
|
144
|
+
*index = min;
|
145
|
+
return NULL;
|
146
|
+
}
|
147
|
+
|
148
|
+
sppage *sp_catroute(spcat *c, char *rkey, int size, uint32_t *idx)
|
149
|
+
{
|
150
|
+
if (spunlikely(c->count == 1))
|
151
|
+
return c->i[0];
|
152
|
+
uint32_t i;
|
153
|
+
sppage *p = sp_catfind(c, rkey, size, &i);
|
154
|
+
if (splikely(p)) {
|
155
|
+
*idx = i;
|
156
|
+
return p;
|
157
|
+
}
|
158
|
+
if (spunlikely(i >= c->count))
|
159
|
+
i = c->count - 1;
|
160
|
+
|
161
|
+
if (i > 0 && c->cmp(c->i[i]->min->key, c->i[i]->min->size,
|
162
|
+
rkey,
|
163
|
+
size, c->cmparg) == 1) {
|
164
|
+
i = i - 1;
|
165
|
+
}
|
166
|
+
if (idx)
|
167
|
+
*idx = i;
|
168
|
+
return c->i[i];
|
169
|
+
}
|
170
|
+
|
171
|
+
int sp_catown(spcat *c, uint32_t idx, spv *v)
|
172
|
+
{
|
173
|
+
register sppage *p = c->i[idx];
|
174
|
+
/* equal or equal min or equal max */
|
175
|
+
switch (cmpkey(c, p, v->key, v->size)) {
|
176
|
+
case 0:
|
177
|
+
return 1;
|
178
|
+
case -1: /* key > page */
|
179
|
+
/* key > max */
|
180
|
+
if (idx == c->count-1)
|
181
|
+
return 1;
|
182
|
+
break;
|
183
|
+
case 1: /* key < page */
|
184
|
+
/* key < min */
|
185
|
+
if (idx == 0)
|
186
|
+
return 1;
|
187
|
+
break;
|
188
|
+
}
|
189
|
+
/* key > page && key < page+1.min */
|
190
|
+
if (c->cmp(v->key, v->size,
|
191
|
+
c->i[idx + 1]->min->key,
|
192
|
+
c->i[idx + 1]->min->size, c->cmparg) == -1)
|
193
|
+
return 1;
|
194
|
+
return 0;
|
195
|
+
}
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#ifndef SP_CAT_H_
|
2
|
+
#define SP_CAT_H_
|
3
|
+
|
4
|
+
/*
|
5
|
+
* sophia database
|
6
|
+
* sphia.org
|
7
|
+
*
|
8
|
+
* Copyright (c) Dmitry Simonenko
|
9
|
+
* BSD License
|
10
|
+
*/
|
11
|
+
|
12
|
+
typedef struct spcat spcat;
|
13
|
+
|
14
|
+
struct spcat {
|
15
|
+
spa *a;
|
16
|
+
sppage **i;
|
17
|
+
uint32_t count;
|
18
|
+
uint32_t top;
|
19
|
+
spcmpf cmp;
|
20
|
+
void *cmparg;
|
21
|
+
};
|
22
|
+
|
23
|
+
int sp_catinit(spcat*, spa*, int, spcmpf, void*);
|
24
|
+
void sp_catfree(spcat*);
|
25
|
+
int sp_catset(spcat*, sppage*, sppage**);
|
26
|
+
int sp_catget(spcat*, uint64_t);
|
27
|
+
int sp_catdel(spcat*, uint32_t);
|
28
|
+
sppage *sp_catfind(spcat*, char*, int, uint32_t*);
|
29
|
+
sppage *sp_catroute(spcat*, char*, int, uint32_t*);
|
30
|
+
int sp_catown(spcat*, uint32_t, spv*);
|
31
|
+
|
32
|
+
#endif
|
@@ -0,0 +1,129 @@
|
|
1
|
+
#ifndef SP_CORE_H_
|
2
|
+
#define SP_CORE_H_
|
3
|
+
|
4
|
+
/*
|
5
|
+
* sophia database
|
6
|
+
* sphia.org
|
7
|
+
*
|
8
|
+
* Copyright (c) Dmitry Simonenko
|
9
|
+
* BSD License
|
10
|
+
*/
|
11
|
+
|
12
|
+
#define SP_VERSION_MAJOR 1
|
13
|
+
#define SP_VERSION_MINOR 1
|
14
|
+
|
15
|
+
typedef struct sp sp;
|
16
|
+
typedef struct spenv spenv;
|
17
|
+
|
18
|
+
enum spmagic {
|
19
|
+
SPMCUR = 0x15481936L,
|
20
|
+
SPMENV = 0x06154834L,
|
21
|
+
SPMDB = 0x00fec0feL,
|
22
|
+
SPMNONE = 0L
|
23
|
+
};
|
24
|
+
|
25
|
+
typedef enum spmagic spmagic;
|
26
|
+
|
27
|
+
struct spenv {
|
28
|
+
spmagic m;
|
29
|
+
spe e;
|
30
|
+
int inuse;
|
31
|
+
spallocf alloc;
|
32
|
+
void *allocarg;
|
33
|
+
spcmpf cmp;
|
34
|
+
void *cmparg;
|
35
|
+
uint32_t flags;
|
36
|
+
char *dir;
|
37
|
+
int merge;
|
38
|
+
uint32_t mergewm;
|
39
|
+
uint32_t page;
|
40
|
+
uint32_t dbnewsize;
|
41
|
+
float dbgrow;
|
42
|
+
int gc;
|
43
|
+
float gcfactor;
|
44
|
+
};
|
45
|
+
|
46
|
+
struct sp {
|
47
|
+
spmagic m;
|
48
|
+
spenv *e;
|
49
|
+
spa a;
|
50
|
+
sprep rep;
|
51
|
+
spi *i, i0, i1;
|
52
|
+
int iskip; /* skip second index during read */
|
53
|
+
uint64_t psn; /* page sequence number */
|
54
|
+
spcat s;
|
55
|
+
volatile int stop;
|
56
|
+
sptask merger;
|
57
|
+
sprefset refs; /* pre allocated key buffer (page merge) */
|
58
|
+
int lockc; /* incremental cursor lock */
|
59
|
+
spspinlock lockr; /* repository lock */
|
60
|
+
spspinlock locks; /* space lock */
|
61
|
+
spspinlock locki; /* index lock */
|
62
|
+
};
|
63
|
+
|
64
|
+
int sp_rotate(sp*);
|
65
|
+
|
66
|
+
static inline int sp_active(sp *s) {
|
67
|
+
return !s->stop;
|
68
|
+
}
|
69
|
+
|
70
|
+
static inline int
|
71
|
+
sp_e(sp *s, int type, ...) {
|
72
|
+
va_list args;
|
73
|
+
va_start(args, type);
|
74
|
+
sp_ve(&s->e->e, type, args);
|
75
|
+
va_end(args);
|
76
|
+
return -1;
|
77
|
+
}
|
78
|
+
|
79
|
+
static inline int
|
80
|
+
sp_ee(spenv *e, int type, ...) {
|
81
|
+
va_list args;
|
82
|
+
va_start(args, type);
|
83
|
+
sp_ve(&e->e, type, args);
|
84
|
+
va_end(args);
|
85
|
+
return -1;
|
86
|
+
}
|
87
|
+
|
88
|
+
static inline void
|
89
|
+
sp_glock(sp *s) {
|
90
|
+
if (s->lockc > 0)
|
91
|
+
return;
|
92
|
+
sp_lock(&s->lockr);
|
93
|
+
sp_replockall(&s->rep);
|
94
|
+
sp_lock(&s->locki);
|
95
|
+
sp_lock(&s->locks);
|
96
|
+
s->lockc++;
|
97
|
+
}
|
98
|
+
|
99
|
+
static inline void
|
100
|
+
sp_gunlock(sp *s) {
|
101
|
+
s->lockc--;
|
102
|
+
if (s->lockc > 0)
|
103
|
+
return;
|
104
|
+
sp_unlock(&s->locks);
|
105
|
+
sp_unlock(&s->locki);
|
106
|
+
sp_repunlockall(&s->rep);
|
107
|
+
sp_unlock(&s->lockr);
|
108
|
+
}
|
109
|
+
|
110
|
+
static inline void
|
111
|
+
sp_iskipset(sp *s, int v) {
|
112
|
+
sp_lock(&s->locki);
|
113
|
+
s->iskip = v;
|
114
|
+
sp_unlock(&s->locki);
|
115
|
+
}
|
116
|
+
|
117
|
+
static inline spi*
|
118
|
+
sp_ipair(sp *s) {
|
119
|
+
return (s->i == &s->i0 ? &s->i1 : &s->i0);
|
120
|
+
}
|
121
|
+
|
122
|
+
static inline spi*
|
123
|
+
sp_iswap(sp *s) {
|
124
|
+
spi *old = s->i;
|
125
|
+
s->i = sp_ipair(s);
|
126
|
+
return old;
|
127
|
+
}
|
128
|
+
|
129
|
+
#endif
|