sophia-ruby 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.gitmodules +3 -0
  4. data/Gemfile +6 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +29 -0
  7. data/Rakefile +22 -0
  8. data/ext/extconf.rb +13 -0
  9. data/ext/sophia.c +220 -0
  10. data/lib/sophia-ruby.rb +1 -0
  11. data/lib/sophia/version.rb +3 -0
  12. data/sophia-ruby.gemspec +47 -0
  13. data/test/test_sophia.rb +33 -0
  14. data/vendor/sophia/.gitignore +18 -0
  15. data/vendor/sophia/COPYRIGHT +29 -0
  16. data/vendor/sophia/README +5 -0
  17. data/vendor/sophia/db/a.h +58 -0
  18. data/vendor/sophia/db/cat.c +195 -0
  19. data/vendor/sophia/db/cat.h +32 -0
  20. data/vendor/sophia/db/core.h +129 -0
  21. data/vendor/sophia/db/crc.c +343 -0
  22. data/vendor/sophia/db/crc.h +14 -0
  23. data/vendor/sophia/db/cursor.c +551 -0
  24. data/vendor/sophia/db/cursor.h +47 -0
  25. data/vendor/sophia/db/e.c +49 -0
  26. data/vendor/sophia/db/e.h +49 -0
  27. data/vendor/sophia/db/file.c +355 -0
  28. data/vendor/sophia/db/file.h +106 -0
  29. data/vendor/sophia/db/gc.c +71 -0
  30. data/vendor/sophia/db/gc.h +14 -0
  31. data/vendor/sophia/db/i.c +368 -0
  32. data/vendor/sophia/db/i.h +155 -0
  33. data/vendor/sophia/db/list.h +91 -0
  34. data/vendor/sophia/db/lock.h +77 -0
  35. data/vendor/sophia/db/macro.h +20 -0
  36. data/vendor/sophia/db/makefile +44 -0
  37. data/vendor/sophia/db/merge.c +662 -0
  38. data/vendor/sophia/db/merge.h +14 -0
  39. data/vendor/sophia/db/meta.h +87 -0
  40. data/vendor/sophia/db/recover.c +433 -0
  41. data/vendor/sophia/db/recover.h +14 -0
  42. data/vendor/sophia/db/ref.h +111 -0
  43. data/vendor/sophia/db/rep.c +128 -0
  44. data/vendor/sophia/db/rep.h +120 -0
  45. data/vendor/sophia/db/sophia.h +84 -0
  46. data/vendor/sophia/db/sp.c +626 -0
  47. data/vendor/sophia/db/sp.h +50 -0
  48. data/vendor/sophia/db/task.h +70 -0
  49. data/vendor/sophia/db/track.h +99 -0
  50. data/vendor/sophia/db/util.c +105 -0
  51. data/vendor/sophia/db/util.h +25 -0
  52. data/vendor/sophia/makefile +7 -0
  53. data/vendor/sophia/sophia.gyp +30 -0
  54. data/vendor/sophia/test/common.c +870 -0
  55. data/vendor/sophia/test/crash.c +492 -0
  56. data/vendor/sophia/test/i.c +403 -0
  57. data/vendor/sophia/test/limit.c +65 -0
  58. data/vendor/sophia/test/makefile +30 -0
  59. data/vendor/sophia/test/merge.c +890 -0
  60. data/vendor/sophia/test/recover.c +1550 -0
  61. data/vendor/sophia/test/test.h +66 -0
  62. metadata +134 -0
@@ -0,0 +1,47 @@
1
+ #ifndef SP_CURSOR_H_
2
+ #define SP_CURSOR_H_
3
+
4
+ /*
5
+ * sophia database
6
+ * sphia.org
7
+ *
8
+ * Copyright (c) Dmitry Simonenko
9
+ * BSD License
10
+ */
11
+
12
+ typedef struct spc spc;
13
+
14
+ enum spcsrc {
15
+ SPCNONE,
16
+ SPCI0,
17
+ SPCI1,
18
+ SPCP
19
+ };
20
+
21
+ #define SPCVDUP 1
22
+ #define SPCPDUP 2
23
+
24
+ typedef enum spcsrc spcsrc;
25
+
26
+ struct spc {
27
+ spmagic m;
28
+ sporder o;
29
+ sp *s;
30
+ spii i0, i1;
31
+ int dup; /* last iteration duplicate flags */
32
+ sppageh *ph;
33
+ sppage *p;
34
+ int pi; /* page space index */
35
+ spvh *pv;
36
+ int pvi; /* version page index */
37
+ spcsrc vsrc; /* last iteration source */
38
+ spref r; /* last iteration result */
39
+ };
40
+
41
+ void sp_cursoropen(spc*, sp*, sporder, char*, int);
42
+ void sp_cursorclose(spc*);
43
+
44
+ int sp_iterate(spc*);
45
+ int sp_match(sp*, void*, size_t, void**, size_t*);
46
+
47
+ #endif
@@ -0,0 +1,49 @@
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
+ void sp_ve(spe *e, int type, va_list args)
13
+ {
14
+ sp_lock(&e->lock);
15
+ if (e->type != SPENONE) {
16
+ sp_unlock(&e->lock);
17
+ return;
18
+ }
19
+ e->type = type;
20
+ switch (type) {
21
+ case SPE: {
22
+ char *fmt = va_arg(args, char*);
23
+ int len = snprintf(e->e, sizeof(e->e), "error: ");
24
+ vsnprintf(e->e + len, sizeof(e->e) - len, fmt, args);
25
+ break;
26
+ }
27
+ case SPEOOM: {
28
+ char *msg = va_arg(args, char*);
29
+ snprintf(e->e, sizeof(e->e), "out-of-memory error: %s", msg);
30
+ break;
31
+ }
32
+ case SPESYS: {
33
+ e->errno_ = errno;
34
+ char *msg = va_arg(args, char*);
35
+ snprintf(e->e, sizeof(e->e), "system error: %s (errno: %d, %s)",
36
+ msg, e->errno_, strerror(e->errno_));
37
+ break;
38
+ }
39
+ case SPEIO: {
40
+ e->errno_ = errno;
41
+ char *msg = va_arg(args, char*);
42
+ uint32_t epoch = va_arg(args, uint32_t);
43
+ snprintf(e->e, sizeof(e->e), "io error: [epoch %"PRIu32"] %s (errno: %d, %s)",
44
+ epoch, msg, e->errno_, strerror(e->errno_));
45
+ break;
46
+ }
47
+ }
48
+ sp_unlock(&e->lock);
49
+ }
@@ -0,0 +1,49 @@
1
+ #ifndef SP_E_H_
2
+ #define SP_E_H_
3
+
4
+ /*
5
+ * sophia database
6
+ * sphia.org
7
+ *
8
+ * Copyright (c) Dmitry Simonenko
9
+ * BSD License
10
+ */
11
+
12
+ typedef struct spe spe;
13
+
14
+ enum {
15
+ SPENONE,
16
+ SPE, /* general error (with format) */
17
+ SPEOOM, /* out of memory */
18
+ SPESYS, /* system + errno */
19
+ SPEIO /* system-io + errno */
20
+ };
21
+
22
+ struct spe {
23
+ spspinlock lock;
24
+ int type;
25
+ int errno_;
26
+ char e[256];
27
+ };
28
+
29
+ static inline void sp_einit(spe *e) {
30
+ e->lock = 0;
31
+ e->type = SPENONE;
32
+ e->e[0] = 0;
33
+ sp_lockinit(&e->lock);
34
+ }
35
+
36
+ static inline void sp_efree(spe *e) {
37
+ sp_lockfree(&e->lock);
38
+ }
39
+
40
+ static inline int sp_eis(spe *e) {
41
+ sp_lock(&e->lock);
42
+ register int is = e->type != SPENONE;
43
+ sp_unlock(&e->lock);
44
+ return is;
45
+ }
46
+
47
+ void sp_ve(spe *e, int type, va_list args);
48
+
49
+ #endif
@@ -0,0 +1,355 @@
1
+
2
+ /*
3
+ * sophia database
4
+ * sphia.org
5
+ *
6
+ * Copyright (c) Dmitry Simonenko
7
+ * BSD License
8
+ */
9
+
10
+ #include <sp.h>
11
+ #include <sys/mman.h>
12
+ #include <fcntl.h>
13
+ #include <unistd.h>
14
+ #include <errno.h>
15
+
16
+ int sp_fileexists(char *path) {
17
+ struct stat st;
18
+ int rc = lstat(path, &st);
19
+ return rc == 0;
20
+ }
21
+
22
+ int sp_filerm(char *path) {
23
+ return unlink(path);
24
+ }
25
+
26
+ static inline ssize_t
27
+ sp_mapsizeof(char *path) {
28
+ struct stat st;
29
+ int rc = lstat(path, &st);
30
+ if (spunlikely(rc == -1))
31
+ return -1;
32
+ return st.st_size;
33
+ }
34
+
35
+ static inline int
36
+ sp_mapresize(spfile *f, size_t size) {
37
+ int rc = ftruncate(f->fd, size);
38
+ if (spunlikely(rc == -1))
39
+ return -1;
40
+ f->size = size;
41
+ return 0;
42
+ }
43
+
44
+ static inline int
45
+ sp_map(spfile *f, int flags) {
46
+ void *p = mmap(NULL, f->size, flags, MAP_SHARED, f->fd, 0);
47
+ if (p == MAP_FAILED)
48
+ return -1;
49
+ f->map = p;
50
+ return 0;
51
+ }
52
+
53
+ static inline int
54
+ sp_unmap(spfile *f) {
55
+ int rc;
56
+ if (f->map) {
57
+ rc = munmap(f->map, f->size);
58
+ f->map = NULL;
59
+ return rc;
60
+ }
61
+ return 0;
62
+ }
63
+
64
+ static inline int
65
+ sp_mapopenof(spfile *f, char *path, int flags, uint64_t size)
66
+ {
67
+ f->fd = open(path, flags, 0600);
68
+ if (spunlikely(f->fd == -1))
69
+ return -1;
70
+ f->file = sp_strdup(f->a, path);
71
+ if (spunlikely(f->file == NULL)) {
72
+ close(f->fd);
73
+ f->fd = -1;
74
+ return -1;
75
+ }
76
+ f->used = 0;
77
+ f->creat = (flags & O_CREAT ? 1 : 0);
78
+ int rc;
79
+ if (! f->creat) {
80
+ ssize_t sz = sp_mapsizeof(path);
81
+ if (spunlikely(sz == -1))
82
+ goto err;
83
+ f->size = sz;
84
+ rc = sp_map(f, PROT_READ);
85
+ if (spunlikely(rc == -1))
86
+ goto err;
87
+ return 0;
88
+ }
89
+ f->size = 0;
90
+ rc = sp_mapresize(f, size);
91
+ if (spunlikely(rc == -1))
92
+ goto err;
93
+ rc = sp_map(f, PROT_READ|PROT_WRITE);
94
+ if (spunlikely(rc == -1))
95
+ goto err;
96
+ return 0;
97
+ err:
98
+ close(f->fd);
99
+ f->fd = -1;
100
+ sp_free(f->a, f->file);
101
+ f->file = NULL;
102
+ return -1;
103
+ }
104
+
105
+ int sp_mapopen(spfile *f, char *path) {
106
+ return sp_mapopenof(f, path, O_RDONLY, 0);
107
+ }
108
+
109
+ int sp_mapnew(spfile *f, char *path, uint64_t size) {
110
+ return sp_mapopenof(f, path, O_RDWR|O_CREAT, size);
111
+ }
112
+
113
+ static inline int
114
+ sp_mapsync(spfile *f) {
115
+ return msync(f->map, f->size, MS_SYNC);
116
+ }
117
+
118
+
119
+ int sp_mapunlink(spfile *f) {
120
+ return sp_filerm(f->file);
121
+ }
122
+
123
+ static inline int
124
+ sp_mapcut(spfile *f)
125
+ {
126
+ if (f->creat == 0)
127
+ return 0;
128
+ int rc = sp_mapsync(f);
129
+ if (spunlikely(rc == -1))
130
+ return -1;
131
+ rc = sp_unmap(f);
132
+ if (spunlikely(rc == -1))
133
+ return -1;
134
+ rc = sp_mapresize(f, f->used);
135
+ if (spunlikely(rc == -1))
136
+ return -1;
137
+ return 0;
138
+ }
139
+
140
+ static inline int
141
+ sp_fileclose(spfile *f)
142
+ {
143
+ /* leave file incomplete */
144
+ if (splikely(f->file)) {
145
+ sp_free(f->a, f->file);
146
+ f->file = NULL;
147
+ }
148
+ int rc;
149
+ if (spunlikely(f->fd != -1)) {
150
+ rc = close(f->fd);
151
+ if (spunlikely(rc == -1))
152
+ return -1;
153
+ f->fd = -1;
154
+ }
155
+ return 0;
156
+ }
157
+
158
+ static inline int
159
+ sp_filecomplete(spfile *f)
160
+ {
161
+ if (f->creat == 0)
162
+ return 0;
163
+ /* remove .incomplete part */
164
+ f->creat = 0;
165
+ char path[1024];
166
+ snprintf(path, sizeof(path), "%s", f->file);
167
+ char *ext = strrchr(path, '.');
168
+ assert(ext != NULL);
169
+ *ext = 0;
170
+ int rc = rename(f->file, path);
171
+ if (spunlikely(rc == -1))
172
+ return -1;
173
+ char *p = sp_strdup(f->a, path);
174
+ if (spunlikely(p == NULL))
175
+ return -1;
176
+ sp_free(f->a, f->file);
177
+ f->file = p;
178
+ return 0;
179
+ }
180
+
181
+ int sp_mapunmap(spfile *f) {
182
+ return sp_unmap(f);
183
+ }
184
+
185
+ int sp_mapclose(spfile *f)
186
+ {
187
+ int rc = sp_mapcut(f);
188
+ if (spunlikely(rc == -1))
189
+ return -1;
190
+ if (f->map) {
191
+ rc = sp_unmap(f);
192
+ if (spunlikely(rc == -1))
193
+ return -1;
194
+ }
195
+ return sp_fileclose(f);
196
+ }
197
+
198
+ int sp_mapcomplete(spfile *f)
199
+ {
200
+ if (f->creat == 0)
201
+ return 0;
202
+ /* sync and truncate file by used size */
203
+ int rc = sp_mapcut(f);
204
+ if (spunlikely(rc == -1))
205
+ return -1;
206
+ /* remove .incomplete part */
207
+ rc = sp_filecomplete(f);
208
+ if (spunlikely(rc == -1))
209
+ return -1;
210
+ return sp_map(f, PROT_READ);
211
+ }
212
+
213
+ int sp_mapensure(spfile *f, uint64_t size, float grow)
214
+ {
215
+ if (splikely((f->used + size) < f->size))
216
+ return 0;
217
+ int rc = sp_unmap(f);
218
+ if (spunlikely(rc == -1))
219
+ return -1;
220
+ long double nsz = f->size * grow;
221
+ if (spunlikely(nsz < size))
222
+ nsz = size;
223
+ rc = sp_mapresize(f, nsz);
224
+ if (spunlikely(rc == -1))
225
+ return -1;
226
+ return sp_map(f, PROT_READ|PROT_WRITE);
227
+ }
228
+
229
+ static inline int
230
+ sp_logopenof(spfile *f, char *path, int flags)
231
+ {
232
+ f->creat = 1;
233
+ f->fd = open(path, flags, 0600);
234
+ if (spunlikely(f->fd == -1))
235
+ return -1;
236
+ f->file = sp_strdup(f->a, path);
237
+ if (spunlikely(f->file == NULL)) {
238
+ close(f->fd);
239
+ f->fd = -1;
240
+ return -1;
241
+ }
242
+ f->size = 0;
243
+ f->used = 0;
244
+ return 0;
245
+ }
246
+
247
+ int sp_lognew(spfile *f, char *dir, uint32_t epoch)
248
+ {
249
+ char path[1024];
250
+ snprintf(path, sizeof(path), "%s/%"PRIu32".log.incomplete",
251
+ dir, epoch);
252
+ int rc = sp_logopenof(f, path, O_WRONLY|O_APPEND|O_CREAT);
253
+ if (spunlikely(rc == -1))
254
+ return -1;
255
+ // posix_fadvise(seq)
256
+ return 0;
257
+ }
258
+
259
+ int sp_logcontinue(spfile *f, char *dir, uint32_t epoch) {
260
+ char path[1024];
261
+ snprintf(path, sizeof(path), "%s/%"PRIu32".log.incomplete",
262
+ dir, epoch);
263
+ int rc = sp_logopenof(f, path, O_WRONLY|O_APPEND);
264
+ if (spunlikely(rc == -1))
265
+ return -1;
266
+ return 0;
267
+ }
268
+
269
+ int sp_logclose(spfile *f) {
270
+ return sp_fileclose(f);
271
+ }
272
+
273
+ static inline int
274
+ sp_logsync(spfile *f) {
275
+ return (f->creat ? fsync(f->fd) : 0);
276
+ }
277
+
278
+ int sp_logcomplete(spfile *f)
279
+ {
280
+ int rc = sp_logsync(f);
281
+ if (spunlikely(rc == -1))
282
+ return -1;
283
+ return sp_filecomplete(f);
284
+ }
285
+
286
+ int sp_logcompleteforce(spfile *f) {
287
+ int rc = sp_logsync(f);
288
+ if (spunlikely(rc == -1))
289
+ return -1;
290
+ int oldcreat = f->creat;
291
+ f->creat = 1;
292
+ rc = sp_filecomplete(f);
293
+ f->creat = oldcreat;
294
+ return rc;
295
+ }
296
+
297
+ int sp_logunlink(spfile *f) {
298
+ return sp_filerm(f->file);
299
+ }
300
+
301
+ int sp_logflush(spfile *f)
302
+ {
303
+ register struct iovec *v = f->iov;
304
+ register uint64_t size = 0;
305
+ register int n = f->iovc;
306
+ do {
307
+ int r;
308
+ do {
309
+ r = writev(f->fd, v, n);
310
+ } while (r == -1 && errno == EINTR);
311
+ if (r < 0) {
312
+ f->iovc = 0;
313
+ return -1;
314
+ }
315
+ size += r;
316
+ while (n > 0) {
317
+ if (v->iov_len > (size_t)r) {
318
+ v->iov_base = (char*)v->iov_base + r;
319
+ v->iov_len -= r;
320
+ break;
321
+ } else {
322
+ r -= v->iov_len;
323
+ v++;
324
+ n--;
325
+ }
326
+ }
327
+ } while (n > 0);
328
+ f->used += size;
329
+ f->iovc = 0;
330
+ return 0;
331
+ }
332
+
333
+ int sp_logrlb(spfile *f)
334
+ {
335
+ assert(f->iovc == 0);
336
+ int rc = ftruncate(f->fd, f->svp);
337
+ if (spunlikely(rc == -1))
338
+ return -1;
339
+ f->used = f->svp;
340
+ f->svp = 0;
341
+ return lseek(f->fd, f->used, SEEK_SET);
342
+ }
343
+
344
+ int sp_logeof(spfile *f)
345
+ {
346
+ sp_filesvp(f);
347
+ speofh eof = { SPEOF };
348
+ sp_logadd(f, (char*)&eof, sizeof(eof));
349
+ int rc = sp_logflush(f);
350
+ if (spunlikely(rc == -1)) {
351
+ sp_logrlb(f);
352
+ return -1;
353
+ }
354
+ return 0;
355
+ }