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.
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
+ }