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,106 @@
|
|
1
|
+
#ifndef SP_FILE_H_
|
2
|
+
#define SP_FILE_H_
|
3
|
+
|
4
|
+
/*
|
5
|
+
* sophia database
|
6
|
+
* sphia.org
|
7
|
+
*
|
8
|
+
* Copyright (c) Dmitry Simonenko
|
9
|
+
* BSD License
|
10
|
+
*/
|
11
|
+
|
12
|
+
typedef struct spfile spfile;
|
13
|
+
|
14
|
+
struct spfile {
|
15
|
+
spa *a;
|
16
|
+
int creat;
|
17
|
+
uint64_t used;
|
18
|
+
uint64_t size;
|
19
|
+
uint64_t svp;
|
20
|
+
char *file;
|
21
|
+
int fd;
|
22
|
+
char *map;
|
23
|
+
struct iovec iov[8];
|
24
|
+
int iovc;
|
25
|
+
};
|
26
|
+
|
27
|
+
int sp_fileexists(char*);
|
28
|
+
int sp_filerm(char*);
|
29
|
+
|
30
|
+
static inline void
|
31
|
+
sp_fileinit(spfile *f, spa *a) {
|
32
|
+
memset(f, 0, sizeof(*f));
|
33
|
+
f->a = a;
|
34
|
+
f->fd = -1;
|
35
|
+
}
|
36
|
+
|
37
|
+
static inline void
|
38
|
+
sp_filesvp(spfile *f) {
|
39
|
+
f->svp = f->used;
|
40
|
+
}
|
41
|
+
|
42
|
+
int sp_mapopen(spfile*, char*);
|
43
|
+
int sp_mapnew(spfile*, char*, uint64_t);
|
44
|
+
int sp_mapclose(spfile*);
|
45
|
+
int sp_mapcomplete(spfile*);
|
46
|
+
int sp_mapunmap(spfile*);
|
47
|
+
int sp_mapunlink(spfile*);
|
48
|
+
int sp_mapensure(spfile*, uint64_t, float);
|
49
|
+
|
50
|
+
static inline int
|
51
|
+
sp_mapepoch(spfile *f, char *dir, uint32_t epoch, char *ext) {
|
52
|
+
char path[1024];
|
53
|
+
snprintf(path, sizeof(path), "%s/%"PRIu32".%s", dir, epoch, ext);
|
54
|
+
return sp_mapopen(f, path);
|
55
|
+
}
|
56
|
+
|
57
|
+
static inline int
|
58
|
+
sp_mapepochnew(spfile *f, uint64_t size,
|
59
|
+
char *dir, uint32_t epoch, char *ext) {
|
60
|
+
char path[1024];
|
61
|
+
snprintf(path, sizeof(path), "%s/%"PRIu32".%s.incomplete", dir, epoch, ext);
|
62
|
+
return sp_mapnew(f, path, size);
|
63
|
+
}
|
64
|
+
|
65
|
+
static inline void
|
66
|
+
sp_mapuse(spfile *f, size_t size) {
|
67
|
+
f->used += size;
|
68
|
+
assert(f->used <= f->size);
|
69
|
+
}
|
70
|
+
|
71
|
+
static inline void
|
72
|
+
sp_maprlb(spfile *f) {
|
73
|
+
f->used = f->svp;
|
74
|
+
}
|
75
|
+
|
76
|
+
static inline int
|
77
|
+
sp_mapinbound(spfile *f, size_t off) {
|
78
|
+
return off <= f->size;
|
79
|
+
}
|
80
|
+
|
81
|
+
int sp_lognew(spfile*, char*, uint32_t);
|
82
|
+
int sp_logcontinue(spfile*, char*, uint32_t);
|
83
|
+
int sp_logclose(spfile*);
|
84
|
+
int sp_logcomplete(spfile*);
|
85
|
+
int sp_logcompleteforce(spfile*);
|
86
|
+
int sp_logunlink(spfile*);
|
87
|
+
int sp_logflush(spfile*);
|
88
|
+
int sp_logrlb(spfile*);
|
89
|
+
int sp_logeof(spfile*);
|
90
|
+
|
91
|
+
static inline void
|
92
|
+
sp_logadd(spfile *f, const void *buf, int size) {
|
93
|
+
assert(f->iovc < 8);
|
94
|
+
f->iov[f->iovc].iov_base = (void*)buf;
|
95
|
+
f->iov[f->iovc].iov_len = size;
|
96
|
+
f->iovc++;
|
97
|
+
}
|
98
|
+
|
99
|
+
static inline int
|
100
|
+
sp_epochrm(char *dir, uint32_t epoch, char *ext) {
|
101
|
+
char path[1024];
|
102
|
+
snprintf(path, sizeof(path), "%s/%"PRIu32".%s", dir, epoch, ext);
|
103
|
+
return sp_filerm(path);
|
104
|
+
}
|
105
|
+
|
106
|
+
#endif
|
@@ -0,0 +1,71 @@
|
|
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
|
+
int sp_gc(sp *s, spepoch *x)
|
13
|
+
{
|
14
|
+
/*
|
15
|
+
* copy all yet active pages from a epoch's
|
16
|
+
* databases picked for the garbage
|
17
|
+
* collecting.
|
18
|
+
*/
|
19
|
+
for (;;)
|
20
|
+
{
|
21
|
+
sp_lock(&s->lockr);
|
22
|
+
spepoch *g = sp_repgc(&s->rep, s->e->gcfactor);
|
23
|
+
sp_unlock(&s->lockr);
|
24
|
+
if (g == NULL)
|
25
|
+
break;
|
26
|
+
|
27
|
+
int rc;
|
28
|
+
splist *i, *n;
|
29
|
+
sp_listforeach_safe(&g->pages, i, n) {
|
30
|
+
sppage *p = spcast(i, sppage, link);
|
31
|
+
|
32
|
+
/* map origin page and copy to db file */
|
33
|
+
sppageh *h = (sppageh*)(g->db.map + p->offset);
|
34
|
+
sp_lock(&x->lock);
|
35
|
+
rc = sp_mapensure(&x->db, sizeof(sppageh) + h->size, s->e->dbgrow);
|
36
|
+
if (spunlikely(rc == -1)) {
|
37
|
+
sp_unlock(&x->lock);
|
38
|
+
return sp_e(s, SPEIO, "failed to remap db file", x->epoch);
|
39
|
+
}
|
40
|
+
sp_unlock(&x->lock);
|
41
|
+
memcpy(x->db.map + x->db.used, h, sizeof(sppageh) + h->size);
|
42
|
+
|
43
|
+
/* update page location */
|
44
|
+
sp_lock(&s->locks);
|
45
|
+
sp_listunlink(&p->link);
|
46
|
+
sp_listappend(&x->pages, &p->link);
|
47
|
+
p->epoch = x;
|
48
|
+
p->offset = x->db.used;
|
49
|
+
sp_unlock(&s->locks);
|
50
|
+
|
51
|
+
/* advance file pointer */
|
52
|
+
sp_mapuse(&x->db, sizeof(sppageh) + h->size);
|
53
|
+
}
|
54
|
+
|
55
|
+
/*
|
56
|
+
* remove old files and unlink the epoch
|
57
|
+
* from the repository.
|
58
|
+
*/
|
59
|
+
rc = sp_mapunlink(&g->db);
|
60
|
+
if (spunlikely(rc == -1))
|
61
|
+
return sp_e(s, SPEIO, "failed to unlink db file", g->epoch);
|
62
|
+
rc = sp_mapclose(&g->db);
|
63
|
+
if (spunlikely(rc == -1))
|
64
|
+
return sp_e(s, SPEIO, "failed to close db file", g->epoch);
|
65
|
+
sp_lock(&s->lockr);
|
66
|
+
sp_repdetach(&s->rep, g);
|
67
|
+
sp_free(&s->a, g);
|
68
|
+
sp_unlock(&s->lockr);
|
69
|
+
}
|
70
|
+
return 0;
|
71
|
+
}
|
@@ -0,0 +1,368 @@
|
|
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_iensure(spi *i) {
|
13
|
+
if (splikely((i->icount + 1) < i->itop))
|
14
|
+
return 0;
|
15
|
+
i->itop *= 2;
|
16
|
+
i->i = sp_realloc(i->a, i->i, i->itop * sizeof(spipage*));
|
17
|
+
if (spunlikely(i->i == NULL))
|
18
|
+
return -1;
|
19
|
+
return 0;
|
20
|
+
}
|
21
|
+
|
22
|
+
static inline int
|
23
|
+
sp_ipagesize(spi *i) {
|
24
|
+
return sizeof(spipage) + sizeof(spv*) * i->pagesize;
|
25
|
+
}
|
26
|
+
|
27
|
+
static inline spipage*
|
28
|
+
sp_ipagealloc(spi *i) {
|
29
|
+
spipage *p = sp_malloc(i->a, sp_ipagesize(i));
|
30
|
+
if (spunlikely(p == NULL))
|
31
|
+
return NULL;
|
32
|
+
p->count = 0;
|
33
|
+
return p;
|
34
|
+
}
|
35
|
+
|
36
|
+
int sp_iinit(spi *i, spa *a, int pagesize, spcmpf cmp, void *cmparg)
|
37
|
+
{
|
38
|
+
i->a = a;
|
39
|
+
i->cmp = cmp;
|
40
|
+
i->cmparg = cmparg;
|
41
|
+
i->count = 0;
|
42
|
+
i->pagesize = pagesize;
|
43
|
+
/* start from 4 pages vector */
|
44
|
+
i->itop = 2;
|
45
|
+
i->icount = 1;
|
46
|
+
i->i = NULL;
|
47
|
+
int rc = sp_iensure(i);
|
48
|
+
if (spunlikely(rc == -1))
|
49
|
+
return -1;
|
50
|
+
/* allocate first page */
|
51
|
+
i->i[0] = sp_ipagealloc(i);
|
52
|
+
if (spunlikely(i->i[0] == NULL)) {
|
53
|
+
sp_free(i->a, i->i);
|
54
|
+
i->i = NULL;
|
55
|
+
return -1;
|
56
|
+
}
|
57
|
+
return 0;
|
58
|
+
}
|
59
|
+
|
60
|
+
void sp_ifree(spi *i)
|
61
|
+
{
|
62
|
+
uint32_t p = 0;
|
63
|
+
while (p < i->icount) {
|
64
|
+
uint32_t k = 0;
|
65
|
+
while (k < i->i[p]->count) {
|
66
|
+
sp_free(i->a, i->i[p]->i[k]);
|
67
|
+
k++;
|
68
|
+
}
|
69
|
+
sp_free(i->a, i->i[p]);
|
70
|
+
p++;
|
71
|
+
}
|
72
|
+
sp_free(i->a, i->i);
|
73
|
+
i->i = NULL;
|
74
|
+
}
|
75
|
+
|
76
|
+
int sp_itruncate(spi *i)
|
77
|
+
{
|
78
|
+
sp_ifree(i);
|
79
|
+
return sp_iinit(i, i->a, i->pagesize, i->cmp, i->cmparg);
|
80
|
+
}
|
81
|
+
|
82
|
+
static inline void*
|
83
|
+
sp_iminof(spi *i, spipage *p, char *rkey, int size, uint32_t *idx)
|
84
|
+
{
|
85
|
+
register int min = 0;
|
86
|
+
register int max = p->count - 1;
|
87
|
+
while (max >= min) {
|
88
|
+
register int mid = min + ((max - min) >> 1);
|
89
|
+
register int rc =
|
90
|
+
i->cmp(p->i[mid]->key,
|
91
|
+
p->i[mid]->size, rkey, size, i->cmparg);
|
92
|
+
switch (rc) {
|
93
|
+
case -1: min = mid + 1;
|
94
|
+
continue;
|
95
|
+
case 1: max = mid - 1;
|
96
|
+
continue;
|
97
|
+
default: *idx = mid;
|
98
|
+
return p->i[mid];
|
99
|
+
}
|
100
|
+
}
|
101
|
+
*idx = min;
|
102
|
+
return NULL;
|
103
|
+
}
|
104
|
+
|
105
|
+
static inline void*
|
106
|
+
sp_imaxof(spi *i, spipage *p, char *rkey, int size, uint32_t *idx)
|
107
|
+
{
|
108
|
+
register int min = 0;
|
109
|
+
register int max = p->count - 1;
|
110
|
+
while (max >= min) {
|
111
|
+
register int mid = min + ((max - min) >> 1);
|
112
|
+
register int rc =
|
113
|
+
i->cmp(p->i[mid]->key,
|
114
|
+
p->i[mid]->size,
|
115
|
+
rkey, size, i->cmparg);
|
116
|
+
switch (rc) {
|
117
|
+
case -1: min = mid + 1;
|
118
|
+
continue;
|
119
|
+
case 1: max = mid - 1;
|
120
|
+
continue;
|
121
|
+
default: *idx = mid;
|
122
|
+
return p->i[mid];
|
123
|
+
}
|
124
|
+
}
|
125
|
+
*idx = max;
|
126
|
+
return NULL;
|
127
|
+
}
|
128
|
+
|
129
|
+
static inline int
|
130
|
+
sp_ipagecmp(spi *i, spipage *p, char *rkey, int size)
|
131
|
+
{
|
132
|
+
if (spunlikely(p->count == 0))
|
133
|
+
return 0;
|
134
|
+
register int l =
|
135
|
+
i->cmp(p->i[0]->key, p->i[0]->size, rkey, size, i->cmparg);
|
136
|
+
register int r =
|
137
|
+
i->cmp(p->i[p->count-1]->key, p->i[p->count-1]->size,
|
138
|
+
rkey, size, i->cmparg);
|
139
|
+
/* inside page range */
|
140
|
+
if (l <= 0 && r >= 0)
|
141
|
+
return 0;
|
142
|
+
/* page min < key */
|
143
|
+
if (l == -1)
|
144
|
+
return -1;
|
145
|
+
/* page max > key */
|
146
|
+
assert(r == 1);
|
147
|
+
return 1;
|
148
|
+
}
|
149
|
+
|
150
|
+
static inline spipage*
|
151
|
+
sp_ipageof(spi *i, char *rkey, int size, uint32_t *idx)
|
152
|
+
{
|
153
|
+
register int min = 0;
|
154
|
+
register int max = i->icount - 1;
|
155
|
+
while (max >= min) {
|
156
|
+
register int mid = min + ((max - min) >> 1);
|
157
|
+
switch (sp_ipagecmp(i, i->i[mid], rkey, size)) {
|
158
|
+
case -1: min = mid + 1;
|
159
|
+
continue;
|
160
|
+
case 1: max = mid - 1;
|
161
|
+
continue;
|
162
|
+
default:
|
163
|
+
*idx = mid;
|
164
|
+
return i->i[mid];
|
165
|
+
}
|
166
|
+
}
|
167
|
+
*idx = min;
|
168
|
+
return NULL;
|
169
|
+
}
|
170
|
+
|
171
|
+
int sp_isetorget(spi *i, spv *v, spii *old)
|
172
|
+
{
|
173
|
+
/* 1. do binary search on the vector and find usable
|
174
|
+
* page for a key */
|
175
|
+
spipage *p = i->i[0];
|
176
|
+
uint32_t a = 0;
|
177
|
+
if (splikely(i->icount > 1)) {
|
178
|
+
p = sp_ipageof(i, v->key, v->size, &a);
|
179
|
+
if (spunlikely(p == NULL)) {
|
180
|
+
if (a >= i->icount)
|
181
|
+
a = i->icount-1;
|
182
|
+
p = i->i[a];
|
183
|
+
assert(a < i->icount);
|
184
|
+
}
|
185
|
+
assert(p != NULL);
|
186
|
+
}
|
187
|
+
|
188
|
+
/* 2. if page is full, split it and insert new one:
|
189
|
+
* copy second half of the keys from first page to second */
|
190
|
+
/* 2.1. insert page to vector, by moving pointers forward */
|
191
|
+
if (spunlikely(p->count == i->pagesize)) {
|
192
|
+
int rc = sp_iensure(i);
|
193
|
+
if (spunlikely(rc == -1))
|
194
|
+
return -1;
|
195
|
+
/* split page */
|
196
|
+
spipage *n = sp_ipagealloc(i);
|
197
|
+
if (spunlikely(n == NULL))
|
198
|
+
return -1;
|
199
|
+
int half = p->count >> 1;
|
200
|
+
memcpy(&n->i[0], &p->i[half], sizeof(void*) * (half));
|
201
|
+
n->count = half;
|
202
|
+
p->count = half;
|
203
|
+
/* split page i and insert new page */
|
204
|
+
memmove(&i->i[a + 1], &i->i[a], sizeof(spipage*) * (i->icount - a));
|
205
|
+
i->i[a] = p;
|
206
|
+
i->i[a+1] = n;
|
207
|
+
i->icount++;
|
208
|
+
/* choose which part to use */
|
209
|
+
if (sp_ipagecmp(i, n, v->key, v->size) <= 0) {
|
210
|
+
p = n;
|
211
|
+
a++;
|
212
|
+
}
|
213
|
+
}
|
214
|
+
|
215
|
+
/* 3. if page is not full, do nothing */
|
216
|
+
/* 4. do binary search on a page and match room, move
|
217
|
+
* pointers forward */
|
218
|
+
/* 5. insert key, increment counters */
|
219
|
+
assert(p->count < i->pagesize);
|
220
|
+
|
221
|
+
uint32_t j;
|
222
|
+
void *o = sp_iminof(i, p, v->key, v->size, &j);
|
223
|
+
if (spunlikely(o)) {
|
224
|
+
old->i = i;
|
225
|
+
old->p = a;
|
226
|
+
old->n = j;
|
227
|
+
assert(sp_ival(old) == o);
|
228
|
+
return 1;
|
229
|
+
}
|
230
|
+
if (j >= p->count) {
|
231
|
+
p->i[p->count] = v;
|
232
|
+
} else {
|
233
|
+
memmove(&p->i[j + 1], &p->i[j], sizeof(spv*) * (p->count - j));
|
234
|
+
p->i[j] = v;
|
235
|
+
}
|
236
|
+
i->count++;
|
237
|
+
p->count++;
|
238
|
+
return 0;
|
239
|
+
}
|
240
|
+
|
241
|
+
int sp_idelraw(spi *i, char *rkey, int size, spv **old)
|
242
|
+
{
|
243
|
+
spipage *p = i->i[0];
|
244
|
+
uint32_t a = 0;
|
245
|
+
if (splikely(i->icount > 1))
|
246
|
+
p = sp_ipageof(i, rkey, size, &a);
|
247
|
+
if (spunlikely(p == NULL))
|
248
|
+
return 0;
|
249
|
+
uint32_t j;
|
250
|
+
*old = sp_iminof(i, p, rkey, size, &j);
|
251
|
+
if (spunlikely(*old == NULL))
|
252
|
+
return 0;
|
253
|
+
if (splikely(j != (uint32_t)(p->count-1)))
|
254
|
+
memmove(&p->i[j], &p->i[j + 1], sizeof(spv*) * (p->count - j - 1));
|
255
|
+
p->count--;
|
256
|
+
i->count--;
|
257
|
+
if (splikely(p->count > 0))
|
258
|
+
return 1;
|
259
|
+
/* do not touch last page */
|
260
|
+
if (spunlikely(i->icount == 1))
|
261
|
+
return 1;
|
262
|
+
/* remove empty page */
|
263
|
+
sp_free(i->a, i->i[a]);
|
264
|
+
if (splikely(a != (i->icount - 1)))
|
265
|
+
memmove(&i->i[a], &i->i[a + 1], sizeof(spipage*) * (i->icount - a - 1));
|
266
|
+
i->icount--;
|
267
|
+
return 1;
|
268
|
+
}
|
269
|
+
|
270
|
+
spv *sp_igetraw(spi *i, char *rkey, int size)
|
271
|
+
{
|
272
|
+
spipage *p = i->i[0];
|
273
|
+
uint32_t a = 0;
|
274
|
+
if (splikely(i->icount > 1))
|
275
|
+
p = sp_ipageof(i, rkey, size, &a);
|
276
|
+
if (p == NULL)
|
277
|
+
return NULL;
|
278
|
+
uint32_t j;
|
279
|
+
return sp_iminof(i, p, rkey, size, &j);
|
280
|
+
}
|
281
|
+
|
282
|
+
static inline int
|
283
|
+
sp_iworldcmp(spi *i, char *rkey, int size)
|
284
|
+
{
|
285
|
+
register spipage *last = i->i[i->icount-1];
|
286
|
+
register int l =
|
287
|
+
i->cmp(i->i[0]->i[0]->key,
|
288
|
+
i->i[0]->i[0]->size, rkey, size, i->cmparg);
|
289
|
+
register int r =
|
290
|
+
i->cmp(last->i[last->count-1]->key,
|
291
|
+
last->i[last->count-1]->size,
|
292
|
+
rkey, size, i->cmparg);
|
293
|
+
/* inside index range */
|
294
|
+
if (l <= 0 && r >= 0)
|
295
|
+
return 0;
|
296
|
+
/* index min < key */
|
297
|
+
if (l == -1)
|
298
|
+
return -1;
|
299
|
+
/* index max > key */
|
300
|
+
assert(r == 1);
|
301
|
+
return 1;
|
302
|
+
}
|
303
|
+
|
304
|
+
int sp_ilte(spi *i, spii *ii, char *k, int size)
|
305
|
+
{
|
306
|
+
if (spunlikely(i->count == 0)) {
|
307
|
+
sp_iinv(i, ii);
|
308
|
+
return 0;
|
309
|
+
}
|
310
|
+
spipage *p = i->i[0];
|
311
|
+
uint32_t a = 0;
|
312
|
+
if (splikely(i->icount > 1))
|
313
|
+
p = sp_ipageof(i, k, size, &a);
|
314
|
+
if (p == NULL) {
|
315
|
+
switch (sp_iworldcmp(i, k, size)) {
|
316
|
+
case -1:
|
317
|
+
sp_iinv(i, ii);
|
318
|
+
break;
|
319
|
+
case 1:
|
320
|
+
ii->i = i;
|
321
|
+
ii->p = i->icount - 1;
|
322
|
+
ii->n = i->i[i->icount - 1]->count - 1;
|
323
|
+
break;
|
324
|
+
case 0:
|
325
|
+
assert(0);
|
326
|
+
}
|
327
|
+
return 0;
|
328
|
+
}
|
329
|
+
uint32_t j;
|
330
|
+
int eq = sp_iminof(i, p, k, size, &j) != NULL;
|
331
|
+
ii->i = i;
|
332
|
+
ii->p = a;
|
333
|
+
ii->n = j;
|
334
|
+
return eq;
|
335
|
+
}
|
336
|
+
|
337
|
+
int sp_igte(spi *i, spii *ii, char *k, int size)
|
338
|
+
{
|
339
|
+
if (spunlikely(i->count == 0)) {
|
340
|
+
sp_iinv(i, ii);
|
341
|
+
return 0;
|
342
|
+
}
|
343
|
+
spipage *p = i->i[0];
|
344
|
+
uint32_t a = 0;
|
345
|
+
if (splikely(i->icount > 1))
|
346
|
+
p = sp_ipageof(i, k, size, &a);
|
347
|
+
if (p == NULL) {
|
348
|
+
switch (sp_iworldcmp(i, k, size)) {
|
349
|
+
case -1:
|
350
|
+
ii->i = i;
|
351
|
+
ii->p = i->icount - 1;
|
352
|
+
ii->n = i->i[i->icount - 1]->count - 1;
|
353
|
+
break;
|
354
|
+
case 1:
|
355
|
+
sp_iinv(i, ii);
|
356
|
+
break;
|
357
|
+
case 0:
|
358
|
+
assert(0);
|
359
|
+
}
|
360
|
+
return 0;
|
361
|
+
}
|
362
|
+
uint32_t j;
|
363
|
+
int eq = sp_imaxof(i, p, k, size, &j) != NULL;
|
364
|
+
ii->i = i;
|
365
|
+
ii->p = a;
|
366
|
+
ii->n = j;
|
367
|
+
return eq;
|
368
|
+
}
|