sophia-ruby 0.0.1
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.
- 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
|