hirlite 0.0.2.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +13 -5
- data/ext/hirlite_ext/hirlite_ext.h +1 -1
- data/ext/hirlite_ext/rlite.c +3 -23
- data/lib/hirlite/connection.rb +4 -0
- data/lib/hirlite/version.rb +1 -1
- data/vendor/rlite/deps/lua/src/lua_cjson.c +1 -1
- data/vendor/rlite/src/Makefile +12 -25
- data/vendor/rlite/src/dump.c +3 -3
- data/vendor/rlite/src/flock_posix.c +79 -0
- data/vendor/rlite/src/flock_win.c +6 -0
- data/vendor/rlite/src/hirlite.c +265 -25
- data/vendor/rlite/src/hyperloglog.c +1 -1
- data/vendor/rlite/src/lzf_c.c +1 -1
- data/vendor/rlite/src/lzf_d.c +1 -1
- data/vendor/rlite/src/page_btree.c +3 -3
- data/vendor/rlite/src/page_key.c +12 -13
- data/vendor/rlite/src/page_list.c +4 -4
- data/vendor/rlite/src/page_long.c +2 -2
- data/vendor/rlite/src/page_multi_string.c +5 -5
- data/vendor/rlite/src/page_skiplist.c +3 -3
- data/vendor/rlite/src/page_string.c +2 -2
- data/vendor/rlite/src/pubsub.c +448 -0
- data/vendor/rlite/src/restore.c +5 -5
- data/vendor/rlite/src/rlite.c +141 -146
- data/vendor/rlite/src/rlite.h +40 -12
- data/vendor/rlite/src/{constants.h → rlite/constants.h} +0 -0
- data/vendor/rlite/src/{crc64.h → rlite/crc64.h} +0 -0
- data/vendor/rlite/src/{dump.h → rlite/dump.h} +0 -0
- data/vendor/rlite/src/{endianconv.h → rlite/endianconv.h} +0 -0
- data/vendor/rlite/src/rlite/flock.h +8 -0
- data/vendor/rlite/src/{hirlite.h → rlite/hirlite.h} +1 -0
- data/vendor/rlite/src/{hyperloglog.h → rlite/hyperloglog.h} +0 -0
- data/vendor/rlite/src/{lzf.h → rlite/lzf.h} +0 -0
- data/vendor/rlite/src/{lzfP.h → rlite/lzfP.h} +0 -0
- data/vendor/rlite/src/{page_btree.h → rlite/page_btree.h} +0 -0
- data/vendor/rlite/src/{page_key.h → rlite/page_key.h} +0 -0
- data/vendor/rlite/src/{page_list.h → rlite/page_list.h} +0 -0
- data/vendor/rlite/src/{page_long.h → rlite/page_long.h} +0 -0
- data/vendor/rlite/src/{page_multi_string.h → rlite/page_multi_string.h} +0 -0
- data/vendor/rlite/src/{page_skiplist.h → rlite/page_skiplist.h} +0 -0
- data/vendor/rlite/src/{page_string.h → rlite/page_string.h} +0 -0
- data/vendor/rlite/src/{pqsort.h → rlite/pqsort.h} +0 -0
- data/vendor/rlite/src/rlite/pubsub.h +25 -0
- data/vendor/rlite/src/{rand.h → rlite/rand.h} +0 -0
- data/vendor/rlite/src/{restore.h → rlite/restore.h} +0 -0
- data/vendor/rlite/src/{scripting.h → rlite/scripting.h} +0 -0
- data/vendor/rlite/src/{sha1.h → rlite/sha1.h} +0 -0
- data/vendor/rlite/src/rlite/signal.h +11 -0
- data/vendor/rlite/src/{solarisfixes.h → rlite/solarisfixes.h} +0 -0
- data/vendor/rlite/src/{sort.h → rlite/sort.h} +0 -0
- data/vendor/rlite/src/{status.h → rlite/status.h} +1 -0
- data/vendor/rlite/src/{type_hash.h → rlite/type_hash.h} +0 -0
- data/vendor/rlite/src/{type_list.h → rlite/type_list.h} +0 -0
- data/vendor/rlite/src/{type_set.h → rlite/type_set.h} +0 -0
- data/vendor/rlite/src/{type_string.h → rlite/type_string.h} +0 -0
- data/vendor/rlite/src/{type_zset.h → rlite/type_zset.h} +0 -0
- data/vendor/rlite/src/{util.h → rlite/util.h} +2 -1
- data/vendor/rlite/src/{utilfromredis.h → rlite/utilfromredis.h} +0 -0
- data/vendor/rlite/src/rlite/wal.h +8 -0
- data/vendor/rlite/src/scripting.c +8 -10
- data/vendor/rlite/src/sha1.c +2 -2
- data/vendor/rlite/src/signal_posix.c +118 -0
- data/vendor/rlite/src/signal_win.c +17 -0
- data/vendor/rlite/src/sort.c +2 -2
- data/vendor/rlite/src/type_hash.c +4 -4
- data/vendor/rlite/src/type_list.c +4 -4
- data/vendor/rlite/src/type_set.c +4 -4
- data/vendor/rlite/src/type_string.c +4 -4
- data/vendor/rlite/src/type_zset.c +7 -7
- data/vendor/rlite/src/util.c +28 -5
- data/vendor/rlite/src/utilfromredis.c +1 -1
- data/vendor/rlite/src/wal.c +309 -0
- metadata +59 -35
@@ -4,10 +4,10 @@
|
|
4
4
|
#include <math.h>
|
5
5
|
#include <stdlib.h>
|
6
6
|
#include "rlite.h"
|
7
|
-
#include "page_multi_string.h"
|
8
|
-
#include "type_hash.h"
|
9
|
-
#include "page_btree.h"
|
10
|
-
#include "util.h"
|
7
|
+
#include "rlite/page_multi_string.h"
|
8
|
+
#include "rlite/type_hash.h"
|
9
|
+
#include "rlite/page_btree.h"
|
10
|
+
#include "rlite/util.h"
|
11
11
|
|
12
12
|
static int rl_hash_create(rlite *db, long btree_page, rl_btree **btree)
|
13
13
|
{
|
@@ -1,9 +1,9 @@
|
|
1
1
|
#include <stdlib.h>
|
2
2
|
#include "rlite.h"
|
3
|
-
#include "page_multi_string.h"
|
4
|
-
#include "type_list.h"
|
5
|
-
#include "page_list.h"
|
6
|
-
#include "util.h"
|
3
|
+
#include "rlite/page_multi_string.h"
|
4
|
+
#include "rlite/type_list.h"
|
5
|
+
#include "rlite/page_list.h"
|
6
|
+
#include "rlite/util.h"
|
7
7
|
|
8
8
|
static int rl_llist_create(rlite *db, long list_page, rl_list **_list)
|
9
9
|
{
|
data/vendor/rlite/src/type_set.c
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
#include <stdlib.h>
|
2
2
|
#include "rlite.h"
|
3
|
-
#include "page_multi_string.h"
|
4
|
-
#include "type_set.h"
|
5
|
-
#include "page_btree.h"
|
6
|
-
#include "util.h"
|
3
|
+
#include "rlite/page_multi_string.h"
|
4
|
+
#include "rlite/type_set.h"
|
5
|
+
#include "rlite/page_btree.h"
|
6
|
+
#include "rlite/util.h"
|
7
7
|
|
8
8
|
static int rl_set_create(rlite *db, long btree_page, rl_btree **btree)
|
9
9
|
{
|
@@ -3,10 +3,10 @@
|
|
3
3
|
#include <math.h>
|
4
4
|
#include <ctype.h>
|
5
5
|
#include "rlite.h"
|
6
|
-
#include "page_multi_string.h"
|
7
|
-
#include "type_string.h"
|
8
|
-
#include "util.h"
|
9
|
-
#include "hyperloglog.h"
|
6
|
+
#include "rlite/page_multi_string.h"
|
7
|
+
#include "rlite/type_string.h"
|
8
|
+
#include "rlite/util.h"
|
9
|
+
#include "rlite/hyperloglog.h"
|
10
10
|
|
11
11
|
static int rl_string_get_objects(rlite *db, const unsigned char *key, long keylen, long *_page_number, unsigned long long *expires, long *version)
|
12
12
|
{
|
@@ -1,13 +1,13 @@
|
|
1
1
|
#include <math.h>
|
2
2
|
#include <stdlib.h>
|
3
3
|
#include "rlite.h"
|
4
|
-
#include "page_key.h"
|
5
|
-
#include "page_multi_string.h"
|
6
|
-
#include "type_zset.h"
|
7
|
-
#include "page_btree.h"
|
8
|
-
#include "page_list.h"
|
9
|
-
#include "page_skiplist.h"
|
10
|
-
#include "util.h"
|
4
|
+
#include "rlite/page_key.h"
|
5
|
+
#include "rlite/page_multi_string.h"
|
6
|
+
#include "rlite/type_zset.h"
|
7
|
+
#include "rlite/page_btree.h"
|
8
|
+
#include "rlite/page_list.h"
|
9
|
+
#include "rlite/page_skiplist.h"
|
10
|
+
#include "rlite/util.h"
|
11
11
|
|
12
12
|
static int rl_zset_create(rlite *db, long levels_page_number, rl_btree **btree, long *btree_page, rl_skiplist **_skiplist, long *skiplist_page)
|
13
13
|
{
|
data/vendor/rlite/src/util.c
CHANGED
@@ -2,15 +2,15 @@
|
|
2
2
|
#include <string.h>
|
3
3
|
#include <stdio.h>
|
4
4
|
#include <math.h>
|
5
|
-
#include "sha1.h"
|
5
|
+
#include "rlite/sha1.h"
|
6
6
|
#ifdef RL_DEBUG
|
7
7
|
#include <unistd.h>
|
8
8
|
#include <sys/stat.h>
|
9
9
|
#include <execinfo.h>
|
10
10
|
#include <valgrind/valgrind.h>
|
11
11
|
#endif
|
12
|
-
#include "status.h"
|
13
|
-
#include "util.h"
|
12
|
+
#include "rlite/status.h"
|
13
|
+
#include "rlite/util.h"
|
14
14
|
#include <sys/time.h>
|
15
15
|
|
16
16
|
int _sha1_formatter(unsigned char *data, char formatted[40])
|
@@ -170,13 +170,16 @@ int long_formatter(void *v2, char **formatted, int *size)
|
|
170
170
|
return RL_OK;
|
171
171
|
}
|
172
172
|
|
173
|
+
#endif
|
174
|
+
|
173
175
|
int sha1_formatter(void *v2, char **formatted, int *size)
|
174
176
|
{
|
175
177
|
unsigned char *data = (unsigned char *)v2;
|
176
|
-
*formatted = rl_malloc(sizeof(char) *
|
178
|
+
*formatted = rl_malloc(sizeof(char) * 41);
|
177
179
|
if (*formatted == NULL) {
|
178
180
|
return RL_OUT_OF_MEMORY;
|
179
181
|
}
|
182
|
+
(*formatted)[40] = 0;
|
180
183
|
_sha1_formatter(data, *formatted);
|
181
184
|
if (size) {
|
182
185
|
*size = 40;
|
@@ -184,7 +187,6 @@ int sha1_formatter(void *v2, char **formatted, int *size)
|
|
184
187
|
return RL_OK;
|
185
188
|
}
|
186
189
|
|
187
|
-
#endif
|
188
190
|
|
189
191
|
// Code for serialize/deserialize double comes from
|
190
192
|
// http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#serialization
|
@@ -332,3 +334,24 @@ double rl_strtod(unsigned char *_str, long strlen, unsigned char **_eptr) {
|
|
332
334
|
}
|
333
335
|
return d;
|
334
336
|
}
|
337
|
+
|
338
|
+
char *rl_get_filename_with_suffix(const char *filename, char *suffix) {
|
339
|
+
int retval = RL_OK;
|
340
|
+
char *new_path = NULL;
|
341
|
+
size_t i, last_slash = 0, filenamelen = strlen(filename);
|
342
|
+
size_t suffixlen = strlen(suffix);
|
343
|
+
// Adding "." to the beginning of the filename, and null termination
|
344
|
+
RL_MALLOC(new_path, sizeof(char) * (filenamelen + suffixlen + 2));
|
345
|
+
for (i = filenamelen - 1; i > 0; i--) {
|
346
|
+
if (filename[i] == '/') {
|
347
|
+
last_slash = i + 1;
|
348
|
+
break;
|
349
|
+
}
|
350
|
+
}
|
351
|
+
memcpy(new_path, filename, last_slash);
|
352
|
+
new_path[last_slash] = '.';
|
353
|
+
memcpy(&new_path[last_slash + 1], &filename[last_slash], filenamelen - last_slash);
|
354
|
+
memcpy(&new_path[filenamelen + 1], suffix, suffixlen + 1);
|
355
|
+
cleanup:
|
356
|
+
return new_path;
|
357
|
+
}
|
@@ -0,0 +1,309 @@
|
|
1
|
+
#include <stdio.h>
|
2
|
+
#include <stdlib.h>
|
3
|
+
#include <unistd.h>
|
4
|
+
|
5
|
+
#include "rlite.h"
|
6
|
+
#include "rlite/flock.h"
|
7
|
+
#include "rlite/sha1.h"
|
8
|
+
|
9
|
+
#ifdef RL_DEBUG
|
10
|
+
int rl_search_cache(rlite *db, rl_data_type *type, long page_number, void **obj, long *position, void *context, rl_page **pages, long page_len);
|
11
|
+
#endif
|
12
|
+
|
13
|
+
static const char *identifier = "rlwal0.0";
|
14
|
+
|
15
|
+
static char *get_wal_filename(const char *filename) {
|
16
|
+
return rl_get_filename_with_suffix(filename, ".wal");
|
17
|
+
}
|
18
|
+
|
19
|
+
static int rl_delete_wal(const char *wal_path) {
|
20
|
+
unlink(wal_path);
|
21
|
+
return RL_OK;
|
22
|
+
}
|
23
|
+
|
24
|
+
static int rl_read_wal(const char *wal_path, unsigned char **_data, size_t *_datalen) {
|
25
|
+
int retval = RL_OK;
|
26
|
+
char *data = NULL;
|
27
|
+
size_t datalen;
|
28
|
+
FILE *fp = fopen(wal_path, "rb");
|
29
|
+
if (fp == NULL) {
|
30
|
+
// file does not exist! empty data, retval=ok are set
|
31
|
+
goto cleanup;
|
32
|
+
}
|
33
|
+
RL_CALL(rl_flock, RL_OK, fp, RLITE_FLOCK_EX);
|
34
|
+
fseek(fp, 0, SEEK_END);
|
35
|
+
datalen = (size_t)ftell(fp);
|
36
|
+
fseek(fp, 0, SEEK_SET);
|
37
|
+
|
38
|
+
data = malloc(datalen * sizeof(char));
|
39
|
+
fread(data, datalen, 1, fp);
|
40
|
+
fclose(fp);
|
41
|
+
cleanup:
|
42
|
+
if (retval == RL_OK) {
|
43
|
+
*_data = (unsigned char *)data;
|
44
|
+
*_datalen = datalen;
|
45
|
+
}
|
46
|
+
return retval;
|
47
|
+
}
|
48
|
+
|
49
|
+
static int rl_apply_wal_data(rlite *db, unsigned char *data, size_t datalen, int skip_check) {
|
50
|
+
if (skip_check == 0) {
|
51
|
+
if (datalen < 36 + (size_t)db->page_size) {
|
52
|
+
// too short to be a valid wal file
|
53
|
+
return RL_UNEXPECTED;
|
54
|
+
}
|
55
|
+
if (memcmp(data, identifier, strlen(identifier))) {
|
56
|
+
// expected identifier
|
57
|
+
return RL_UNEXPECTED;
|
58
|
+
}
|
59
|
+
unsigned char digest[20];
|
60
|
+
SHA1_CTX sha;
|
61
|
+
SHA1Init(&sha);
|
62
|
+
SHA1Update(&sha, &data[32], datalen - 32);
|
63
|
+
SHA1Final(digest, &sha);
|
64
|
+
if (memcmp(&data[8], digest, 20) != 0) {
|
65
|
+
// digest mismatch
|
66
|
+
return RL_UNEXPECTED;
|
67
|
+
}
|
68
|
+
}
|
69
|
+
int retval;
|
70
|
+
rl_file_driver *driver = db->driver;
|
71
|
+
size_t written, position = 28;
|
72
|
+
long page_number;
|
73
|
+
long i, write_pages_len = get_4bytes(&data[position]);
|
74
|
+
position += 4;
|
75
|
+
int readwrite = (driver->mode & RLITE_OPEN_READWRITE) != 0;
|
76
|
+
rl_page *page_obj;
|
77
|
+
for (i = 0; i < write_pages_len; i++) {
|
78
|
+
page_number = get_4bytes(&data[position]);
|
79
|
+
position += 4;
|
80
|
+
if (readwrite) {
|
81
|
+
fseek(driver->fp, page_number * db->page_size, SEEK_SET);
|
82
|
+
written = fwrite(&data[position], sizeof(unsigned char), db->page_size, driver->fp);
|
83
|
+
if ((size_t)db->page_size != written) {
|
84
|
+
// at this point we have corrupted the database
|
85
|
+
// we have written something, but not all of it
|
86
|
+
retval = RL_UNEXPECTED;
|
87
|
+
goto cleanup;
|
88
|
+
}
|
89
|
+
} else {
|
90
|
+
/**
|
91
|
+
* Since we are in read-only mode, but the wal is fully written,
|
92
|
+
* we need to store its information as if it was written in the
|
93
|
+
* file, since it might be partially updated.
|
94
|
+
* We don't want to modify the file as a side effect when we are
|
95
|
+
* in a read only mode.
|
96
|
+
*/
|
97
|
+
|
98
|
+
// TODO: better cleanup on OOM
|
99
|
+
rl_ensure_pages(db);
|
100
|
+
RL_MALLOC(page_obj, sizeof(*page_obj));
|
101
|
+
page_obj->page_number = page_number;
|
102
|
+
page_obj->type = NULL;
|
103
|
+
page_obj->obj = malloc(sizeof(unsigned char) * db->page_size);
|
104
|
+
if (page_obj->obj == NULL) {
|
105
|
+
rl_free(page_obj);
|
106
|
+
return RL_OUT_OF_MEMORY;
|
107
|
+
}
|
108
|
+
memcpy(page_obj->obj, &data[position], db->page_size);
|
109
|
+
db->read_pages[db->read_pages_len] = page_obj;
|
110
|
+
db->read_pages_len++;
|
111
|
+
}
|
112
|
+
if (page_number == 0) {
|
113
|
+
// header has changed! need to parse it before using db->page_size
|
114
|
+
RL_CALL(rl_header_deserialize, RL_OK, db, NULL, NULL, &data[position]);
|
115
|
+
}
|
116
|
+
position += db->page_size;
|
117
|
+
}
|
118
|
+
retval = RL_OK;
|
119
|
+
cleanup:
|
120
|
+
return retval;
|
121
|
+
}
|
122
|
+
|
123
|
+
static int create_wal_data(rlite *db, unsigned char **_data, size_t *_datalen) {
|
124
|
+
// 20 (sha1) + 8 (header) + 4 (number of pages)
|
125
|
+
size_t datalen = db->write_pages_len * (db->page_size + 4) + 32;
|
126
|
+
unsigned char *data;
|
127
|
+
int i, retval = RL_OK;
|
128
|
+
rl_page *page;
|
129
|
+
SHA1_CTX sha;
|
130
|
+
SHA1Init(&sha);
|
131
|
+
RL_MALLOC(data, sizeof(char) * datalen);
|
132
|
+
size_t position = strlen(identifier);
|
133
|
+
memcpy(data, identifier, position);
|
134
|
+
position += 20; // leaving space blank for sha1
|
135
|
+
put_4bytes(&data[position], db->write_pages_len);
|
136
|
+
position += 4;
|
137
|
+
for (i = 0; i < db->write_pages_len; i++) {
|
138
|
+
page = db->write_pages[i];
|
139
|
+
put_4bytes(&data[position], page->page_number);
|
140
|
+
position += 4;
|
141
|
+
memset(&data[position], 0, db->page_size);
|
142
|
+
if (page->type) {
|
143
|
+
retval = page->type->serialize(db, page->obj, &data[position]);
|
144
|
+
}
|
145
|
+
position += db->page_size;
|
146
|
+
SHA1Update(&sha, &data[position - db->page_size - 4], db->page_size + 4);
|
147
|
+
}
|
148
|
+
SHA1Final(&data[strlen(identifier)], &sha);
|
149
|
+
*_data = data;
|
150
|
+
*_datalen = datalen;
|
151
|
+
cleanup:
|
152
|
+
if (retval != RL_OK) {
|
153
|
+
rl_free(data);
|
154
|
+
}
|
155
|
+
return retval;
|
156
|
+
}
|
157
|
+
|
158
|
+
static int rl_write_wal_file(FILE *fp, rlite *db, unsigned char **_data, size_t *_datalen) {
|
159
|
+
int retval;
|
160
|
+
unsigned char *data = NULL;
|
161
|
+
size_t datalen = 0;
|
162
|
+
RL_CALL(create_wal_data, RL_OK, db, &data, &datalen);
|
163
|
+
fwrite(data, sizeof(char), datalen, fp);
|
164
|
+
cleanup:
|
165
|
+
if (retval == RL_OK && _data) {
|
166
|
+
*_data = data;
|
167
|
+
*_datalen = datalen;
|
168
|
+
} else {
|
169
|
+
rl_free(data);
|
170
|
+
}
|
171
|
+
return retval;
|
172
|
+
}
|
173
|
+
int rl_write_wal(const char *wal_path, rlite *db, unsigned char **_data, size_t *_datalen) {
|
174
|
+
int retval;
|
175
|
+
FILE *fp = NULL;
|
176
|
+
fp = fopen(wal_path, "wb");
|
177
|
+
RL_CALL(rl_flock, RL_OK, fp, RLITE_FLOCK_EX);
|
178
|
+
RL_CALL(rl_write_wal_file, RL_OK, fp, db, _data, _datalen);
|
179
|
+
cleanup:
|
180
|
+
if (fp) {
|
181
|
+
fclose(fp);
|
182
|
+
}
|
183
|
+
return retval;
|
184
|
+
}
|
185
|
+
|
186
|
+
int rl_write_apply_wal(rlite *db) {
|
187
|
+
FILE *fp = NULL;
|
188
|
+
int retval = RL_OK;
|
189
|
+
long i, page_number;
|
190
|
+
rl_page *page;
|
191
|
+
char *wal_path = NULL;
|
192
|
+
unsigned char *data = NULL;
|
193
|
+
size_t datalen;
|
194
|
+
#ifdef RL_DEBUG
|
195
|
+
for (i = 0; i < db->read_pages_len; i++) {
|
196
|
+
RL_MALLOC(data, db->page_size * sizeof(unsigned char));
|
197
|
+
page = db->read_pages[i];
|
198
|
+
memset(data, 0, db->page_size);
|
199
|
+
retval = page->type->serialize(db, page->obj, data);
|
200
|
+
if (retval != RL_OK) {
|
201
|
+
goto cleanup;
|
202
|
+
}
|
203
|
+
if (memcmp(data, page->serialized_data, db->page_size) != 0) {
|
204
|
+
fprintf(stderr, "Read page %ld (%s) has changed\n", page->page_number, page->type->name);
|
205
|
+
for (i = 0; i < db->page_size; i++) {
|
206
|
+
if (page->serialized_data[i] != data[i]) {
|
207
|
+
fprintf(stderr, "Different data in position %ld (expected %d, got %d)\n", i, page->serialized_data[i], data[i]);
|
208
|
+
}
|
209
|
+
}
|
210
|
+
retval = rl_search_cache(db, page->type, page->page_number, NULL, NULL, NULL, db->write_pages, db->write_pages_len);
|
211
|
+
if (retval == RL_FOUND) {
|
212
|
+
fprintf(stderr, "Page found in write_pages\n");
|
213
|
+
}
|
214
|
+
else {
|
215
|
+
fprintf(stderr, "Page not found in write_pages\n");
|
216
|
+
}
|
217
|
+
exit(1);
|
218
|
+
}
|
219
|
+
rl_free(data);
|
220
|
+
data = NULL;
|
221
|
+
}
|
222
|
+
#endif
|
223
|
+
if (db->driver_type == RL_FILE_DRIVER) {
|
224
|
+
rl_file_driver *driver = db->driver;
|
225
|
+
wal_path = get_wal_filename(driver->filename);
|
226
|
+
if (wal_path == NULL) {
|
227
|
+
retval = RL_UNEXPECTED;
|
228
|
+
goto cleanup;
|
229
|
+
}
|
230
|
+
fp = fopen(wal_path, "wb");
|
231
|
+
if (fp == NULL) {
|
232
|
+
retval = RL_UNEXPECTED;
|
233
|
+
goto cleanup;
|
234
|
+
}
|
235
|
+
RL_CALL(rl_flock, RL_OK, fp, RLITE_FLOCK_EX);
|
236
|
+
RL_CALL(rl_write_wal_file, RL_OK, fp, db, &data, &datalen);
|
237
|
+
RL_CALL(rl_apply_wal_data, RL_OK, db, data, datalen, 1);
|
238
|
+
ftruncate(fileno(fp), 0);
|
239
|
+
fclose(fp);
|
240
|
+
fp = NULL;
|
241
|
+
RL_CALL(rl_delete_wal, RL_OK, wal_path);
|
242
|
+
if (db->write_pages_len > 0) {
|
243
|
+
fflush(driver->fp);
|
244
|
+
}
|
245
|
+
rl_free(data);
|
246
|
+
data = NULL;
|
247
|
+
}
|
248
|
+
else if (db->driver_type == RL_MEMORY_DRIVER) {
|
249
|
+
rl_memory_driver *driver = db->driver;
|
250
|
+
if (db->write_pages_len > 0) {
|
251
|
+
page = db->write_pages[db->write_pages_len - 1];
|
252
|
+
if ((page->page_number + 1) * db->page_size > driver->datalen) {
|
253
|
+
void *tmp = realloc(driver->data, (page->page_number + 1) * db->page_size * sizeof(unsigned char));
|
254
|
+
if (!tmp) {
|
255
|
+
retval = RL_OUT_OF_MEMORY;
|
256
|
+
goto cleanup;
|
257
|
+
}
|
258
|
+
driver->data = tmp;
|
259
|
+
driver->datalen = (page->page_number + 1) * db->page_size;
|
260
|
+
}
|
261
|
+
}
|
262
|
+
for (i = 0; i < db->write_pages_len; i++) {
|
263
|
+
page = db->write_pages[i];
|
264
|
+
page_number = page->page_number;
|
265
|
+
memset(&driver->data[page_number * db->page_size], 0, db->page_size);
|
266
|
+
if (page->type) {
|
267
|
+
retval = page->type->serialize(db, page->obj, (unsigned char *)&driver->data[page_number * db->page_size]);
|
268
|
+
}
|
269
|
+
}
|
270
|
+
}
|
271
|
+
cleanup:
|
272
|
+
if (fp) {
|
273
|
+
fclose(fp);
|
274
|
+
}
|
275
|
+
rl_free(data);
|
276
|
+
rl_free(wal_path);
|
277
|
+
return retval;
|
278
|
+
}
|
279
|
+
|
280
|
+
int rl_apply_wal(rlite *db) {
|
281
|
+
rl_file_driver *driver = db->driver;
|
282
|
+
int retval;
|
283
|
+
unsigned char *data = NULL;
|
284
|
+
size_t datalen;
|
285
|
+
char *wal_path = get_wal_filename(driver->filename);
|
286
|
+
if (wal_path == NULL) {
|
287
|
+
retval = RL_UNEXPECTED;
|
288
|
+
goto cleanup;
|
289
|
+
}
|
290
|
+
if (access(wal_path, F_OK) != 0) {
|
291
|
+
retval = RL_OK;
|
292
|
+
goto cleanup;
|
293
|
+
}
|
294
|
+
|
295
|
+
RL_CALL(rl_read_wal, RL_OK, wal_path, &data, &datalen);
|
296
|
+
if (data != NULL) {
|
297
|
+
// regardless the data applies or not, the wal file needs to go away
|
298
|
+
// do not goto cleanup if it fails!
|
299
|
+
rl_apply_wal_data(db, data, datalen, 0);
|
300
|
+
if ((driver->mode & RLITE_OPEN_READWRITE) != 0) {
|
301
|
+
RL_CALL(rl_delete_wal, RL_OK, wal_path);
|
302
|
+
}
|
303
|
+
}
|
304
|
+
retval = RL_OK;
|
305
|
+
cleanup:
|
306
|
+
rl_free(wal_path);
|
307
|
+
rl_free(data);
|
308
|
+
return retval;
|
309
|
+
}
|