hirlite 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/LICENSE +28 -0
- data/Rakefile +51 -0
- data/ext/hirlite_ext/extconf.rb +33 -0
- data/ext/hirlite_ext/hirlite_ext.c +14 -0
- data/ext/hirlite_ext/hirlite_ext.h +38 -0
- data/ext/hirlite_ext/rlite.c +351 -0
- data/lib/hirlite/rlite.rb +1 -0
- data/lib/hirlite/version.rb +3 -0
- data/lib/hirlite.rb +2 -0
- data/vendor/rlite/Makefile +6 -0
- data/vendor/rlite/deps/crc64.c +191 -0
- data/vendor/rlite/deps/crc64.h +3 -0
- data/vendor/rlite/deps/endianconv.h +73 -0
- data/vendor/rlite/deps/hyperloglog.c +1547 -0
- data/vendor/rlite/deps/hyperloglog.h +14 -0
- data/vendor/rlite/deps/lzf.h +100 -0
- data/vendor/rlite/deps/lzfP.h +159 -0
- data/vendor/rlite/deps/lzf_c.c +295 -0
- data/vendor/rlite/deps/lzf_d.c +150 -0
- data/vendor/rlite/deps/sha1.c +227 -0
- data/vendor/rlite/deps/sha1.h +19 -0
- data/vendor/rlite/deps/utilfromredis.c +397 -0
- data/vendor/rlite/deps/utilfromredis.h +11 -0
- data/vendor/rlite/src/Makefile +79 -0
- data/vendor/rlite/src/constants.h +15 -0
- data/vendor/rlite/src/dump.c +191 -0
- data/vendor/rlite/src/dump.h +3 -0
- data/vendor/rlite/src/hirlite.c +3985 -0
- data/vendor/rlite/src/hirlite.h +186 -0
- data/vendor/rlite/src/page_btree.c +1556 -0
- data/vendor/rlite/src/page_btree.h +133 -0
- data/vendor/rlite/src/page_key.c +283 -0
- data/vendor/rlite/src/page_key.h +25 -0
- data/vendor/rlite/src/page_list.c +718 -0
- data/vendor/rlite/src/page_list.h +70 -0
- data/vendor/rlite/src/page_long.c +61 -0
- data/vendor/rlite/src/page_long.h +14 -0
- data/vendor/rlite/src/page_multi_string.c +538 -0
- data/vendor/rlite/src/page_multi_string.h +18 -0
- data/vendor/rlite/src/page_skiplist.c +689 -0
- data/vendor/rlite/src/page_skiplist.h +70 -0
- data/vendor/rlite/src/page_string.c +55 -0
- data/vendor/rlite/src/page_string.h +12 -0
- data/vendor/rlite/src/pqsort.c +185 -0
- data/vendor/rlite/src/pqsort.h +40 -0
- data/vendor/rlite/src/restore.c +401 -0
- data/vendor/rlite/src/restore.h +3 -0
- data/vendor/rlite/src/rlite.c +1309 -0
- data/vendor/rlite/src/rlite.h +159 -0
- data/vendor/rlite/src/sort.c +530 -0
- data/vendor/rlite/src/sort.h +18 -0
- data/vendor/rlite/src/status.h +19 -0
- data/vendor/rlite/src/type_hash.c +607 -0
- data/vendor/rlite/src/type_hash.h +29 -0
- data/vendor/rlite/src/type_list.c +477 -0
- data/vendor/rlite/src/type_list.h +23 -0
- data/vendor/rlite/src/type_set.c +796 -0
- data/vendor/rlite/src/type_set.h +34 -0
- data/vendor/rlite/src/type_string.c +613 -0
- data/vendor/rlite/src/type_string.h +34 -0
- data/vendor/rlite/src/type_zset.c +1147 -0
- data/vendor/rlite/src/type_zset.h +50 -0
- data/vendor/rlite/src/util.c +334 -0
- data/vendor/rlite/src/util.h +71 -0
- metadata +151 -0
@@ -0,0 +1,70 @@
|
|
1
|
+
#ifndef _RL_PAGE_LIST_H
|
2
|
+
#define _RL_PAGE_LIST_H
|
3
|
+
|
4
|
+
struct rlite;
|
5
|
+
struct rl_list;
|
6
|
+
struct rl_list_node;
|
7
|
+
|
8
|
+
#define rl_list_nocache_destroy(db, list) rl_list_destroy(db, list)
|
9
|
+
#define rl_list_node_nocache_destroy(db, node) rl_list_node_destroy(db, node)
|
10
|
+
|
11
|
+
typedef struct {
|
12
|
+
struct rl_data_type *list_type;
|
13
|
+
struct rl_data_type *list_node_type;
|
14
|
+
int element_size;
|
15
|
+
int (*cmp)(void *v1, void *v2);
|
16
|
+
#ifdef DEBUG
|
17
|
+
int (*formatter)(void *v, char **str, int *size);
|
18
|
+
#endif
|
19
|
+
} rl_list_type;
|
20
|
+
|
21
|
+
extern rl_list_type rl_list_type_long;
|
22
|
+
|
23
|
+
typedef struct rl_list_node {
|
24
|
+
long size;
|
25
|
+
long left;
|
26
|
+
long right;
|
27
|
+
void **elements;
|
28
|
+
} rl_list_node;
|
29
|
+
|
30
|
+
typedef struct rl_list {
|
31
|
+
long max_node_size; // maximum number of elements in a node
|
32
|
+
long size;
|
33
|
+
rl_list_type *type;
|
34
|
+
long left;
|
35
|
+
long right;
|
36
|
+
} rl_list;
|
37
|
+
|
38
|
+
typedef struct rl_list_iterator {
|
39
|
+
struct rlite *db;
|
40
|
+
rl_list *list;
|
41
|
+
rl_list_node *node;
|
42
|
+
int direction; // 1 for right, -1 for left
|
43
|
+
long node_position;
|
44
|
+
} rl_list_iterator;
|
45
|
+
|
46
|
+
void rl_list_init();
|
47
|
+
int rl_list_create(struct rlite *db, rl_list **_list, rl_list_type *type);
|
48
|
+
int rl_list_destroy(struct rlite *db, void *list);
|
49
|
+
int rl_list_node_destroy(struct rlite *db, void *node);
|
50
|
+
int rl_list_get_element(struct rlite *db, rl_list *list, void **element, long position);
|
51
|
+
int rl_list_add_element(struct rlite *db, rl_list *list, long list_page, void *element, long position);
|
52
|
+
int rl_list_remove_element(struct rlite *db, rl_list *list, long list_page, long position);
|
53
|
+
int rl_list_find_element(struct rlite *db, rl_list *list, void *element, void **found_element, long *position, rl_list_node **found_node, long *found_node_page);
|
54
|
+
int rl_list_iterator_create(struct rlite *db, rl_list_iterator **iterator, rl_list *list, int direction);
|
55
|
+
int rl_list_iterator_destroy(struct rlite *db, rl_list_iterator *iterator);
|
56
|
+
int rl_list_iterator_next(rl_list_iterator *iterator, void **element);
|
57
|
+
int rl_print_list(struct rlite *db, rl_list *list);
|
58
|
+
int rl_list_is_balanced(struct rlite *db, rl_list *list);
|
59
|
+
int rl_flatten_list(struct rlite *db, rl_list *list, void **elements);
|
60
|
+
|
61
|
+
int rl_list_serialize(struct rlite *db, void *obj, unsigned char *data);
|
62
|
+
int rl_list_deserialize(struct rlite *db, void **obj, void *context, unsigned char *data);
|
63
|
+
|
64
|
+
int rl_list_node_serialize_long(struct rlite *db, void *obj, unsigned char *data);
|
65
|
+
int rl_list_node_deserialize_long(struct rlite *db, void **obj, void *context, unsigned char *data);
|
66
|
+
|
67
|
+
int rl_list_pages(struct rlite *db, rl_list *list, short *pages);
|
68
|
+
int rl_list_delete(struct rlite *db, rl_list *list);
|
69
|
+
|
70
|
+
#endif
|
@@ -0,0 +1,61 @@
|
|
1
|
+
#include <stdlib.h>
|
2
|
+
#include <string.h>
|
3
|
+
#include "rlite.h"
|
4
|
+
#include "page_long.h"
|
5
|
+
#include "util.h"
|
6
|
+
|
7
|
+
int rl_long_serialize(rlite *UNUSED(db), void *obj, unsigned char *data)
|
8
|
+
{
|
9
|
+
put_4bytes(data, *(long *)obj);
|
10
|
+
return RL_OK;
|
11
|
+
}
|
12
|
+
|
13
|
+
int rl_long_deserialize(rlite *UNUSED(db), void **obj, void *UNUSED(context), unsigned char *data)
|
14
|
+
{
|
15
|
+
int retval;
|
16
|
+
long *value;
|
17
|
+
RL_MALLOC(value, sizeof(long));
|
18
|
+
*value = get_4bytes(data);
|
19
|
+
*obj = value;
|
20
|
+
retval = RL_OK;
|
21
|
+
cleanup:
|
22
|
+
return retval;
|
23
|
+
}
|
24
|
+
|
25
|
+
int rl_long_destroy(rlite *UNUSED(db), void *obj)
|
26
|
+
{
|
27
|
+
free(obj);
|
28
|
+
return RL_OK;
|
29
|
+
}
|
30
|
+
|
31
|
+
int rl_long_set(rlite *db, long value, long number)
|
32
|
+
{
|
33
|
+
int retval;
|
34
|
+
long *val;
|
35
|
+
RL_MALLOC(val, sizeof(*val));
|
36
|
+
*val = value;
|
37
|
+
RL_CALL(rl_write, RL_OK, db, &rl_data_type_long, number, val);
|
38
|
+
|
39
|
+
retval = RL_OK;
|
40
|
+
cleanup:
|
41
|
+
return retval;
|
42
|
+
}
|
43
|
+
|
44
|
+
int rl_long_create(struct rlite *db, long value, long *number)
|
45
|
+
{
|
46
|
+
if (number) {
|
47
|
+
*number = db->next_empty_page;
|
48
|
+
}
|
49
|
+
return rl_long_set(db, value, db->next_empty_page);
|
50
|
+
}
|
51
|
+
|
52
|
+
int rl_long_get(rlite *db, long *value, long number)
|
53
|
+
{
|
54
|
+
void *data;
|
55
|
+
int retval;
|
56
|
+
RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_long, number, NULL, &data, 1);
|
57
|
+
*value = *(long *)data;
|
58
|
+
retval = RL_OK;
|
59
|
+
cleanup:
|
60
|
+
return retval;
|
61
|
+
}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
#ifndef _RL_PAGE_LONG_H
|
2
|
+
#define _RL_PAGE_LONG_H
|
3
|
+
|
4
|
+
struct rlite;
|
5
|
+
|
6
|
+
int rl_long_serialize(struct rlite *db, void *obj, unsigned char *data);
|
7
|
+
int rl_long_deserialize(struct rlite *db, void **obj, void *context, unsigned char *data);
|
8
|
+
int rl_long_destroy(struct rlite *db, void *obj);
|
9
|
+
int rl_long_create(struct rlite *db, long value, long *number);
|
10
|
+
int rl_long_get(struct rlite *db, long *value, long number);
|
11
|
+
int rl_long_set(struct rlite *db, long value, long number);
|
12
|
+
|
13
|
+
#endif
|
14
|
+
|
@@ -0,0 +1,538 @@
|
|
1
|
+
#include <stdlib.h>
|
2
|
+
#include <string.h>
|
3
|
+
#include "../deps/sha1.h"
|
4
|
+
#include "rlite.h"
|
5
|
+
#include "page_list.h"
|
6
|
+
#include "page_string.h"
|
7
|
+
#include "page_multi_string.h"
|
8
|
+
#include "util.h"
|
9
|
+
|
10
|
+
int rl_normalize_string_range(long totalsize, long *start, long *stop)
|
11
|
+
{
|
12
|
+
if (*start < 0) {
|
13
|
+
*start += totalsize;
|
14
|
+
if (*start < 0) {
|
15
|
+
*start = 0;
|
16
|
+
}
|
17
|
+
}
|
18
|
+
if (*stop < 0) {
|
19
|
+
*stop += totalsize;
|
20
|
+
if (*stop < 0) {
|
21
|
+
*stop = 0;
|
22
|
+
}
|
23
|
+
}
|
24
|
+
if (*start >= totalsize) {
|
25
|
+
*start = totalsize;
|
26
|
+
}
|
27
|
+
if (*stop >= totalsize) {
|
28
|
+
*stop = totalsize - 1;
|
29
|
+
}
|
30
|
+
return RL_OK;
|
31
|
+
}
|
32
|
+
|
33
|
+
int rl_multi_string_cmp(struct rlite *db, long p1, long p2, int *cmp)
|
34
|
+
{
|
35
|
+
rl_list *list1 = NULL, *list2 = NULL;
|
36
|
+
rl_list_node *node1 = NULL, *node2 = NULL;
|
37
|
+
void *_list, *_node;
|
38
|
+
unsigned char *str1, *str2;
|
39
|
+
|
40
|
+
int retval;
|
41
|
+
RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_list_long, p1, &rl_list_type_long, &_list, 0);
|
42
|
+
list1 = _list;
|
43
|
+
RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_list_long, p2, &rl_list_type_long, &_list, 0);
|
44
|
+
list2 = _list;
|
45
|
+
|
46
|
+
long node_number1 = list1->left, node_number2 = list2->left, i;
|
47
|
+
int first = 1;
|
48
|
+
while (1) {
|
49
|
+
if (node_number1 == 0 || node_number2 == 0) {
|
50
|
+
if (node_number1 == 0 && node_number2 == 0) {
|
51
|
+
*cmp = 0;
|
52
|
+
}
|
53
|
+
else if (node_number1 == 0) {
|
54
|
+
*cmp = -1;
|
55
|
+
}
|
56
|
+
else {
|
57
|
+
*cmp = 1;
|
58
|
+
}
|
59
|
+
retval = RL_OK;
|
60
|
+
goto cleanup;
|
61
|
+
}
|
62
|
+
RL_CALL(rl_read, RL_FOUND, db, list1->type->list_node_type, node_number1, list1, &_node, 0);
|
63
|
+
node1 = _node;
|
64
|
+
RL_CALL(rl_read, RL_FOUND, db, list2->type->list_node_type, node_number2, list2, &_node, 0);
|
65
|
+
node2 = _node;
|
66
|
+
if (first) {
|
67
|
+
if (*(long *)node1->elements[0] == 0) {
|
68
|
+
*cmp = -1;
|
69
|
+
retval = RL_OK;
|
70
|
+
goto cleanup;
|
71
|
+
}
|
72
|
+
if (*(long *)node2->elements[0] == 0) {
|
73
|
+
*cmp = 1;
|
74
|
+
retval = RL_OK;
|
75
|
+
goto cleanup;
|
76
|
+
}
|
77
|
+
}
|
78
|
+
for (i = first ? 1 : 0; i < node1->size; i++) {
|
79
|
+
first = 0;
|
80
|
+
RL_CALL(rl_string_get, RL_OK, db, &str1, *(long *)node1->elements[i]);
|
81
|
+
RL_CALL(rl_string_get, RL_OK, db, &str2, *(long *)node2->elements[i]);
|
82
|
+
*cmp = memcmp(str1, str2, db->page_size);
|
83
|
+
if (*cmp != 0) {
|
84
|
+
if (*cmp < 0) {
|
85
|
+
*cmp = -1;
|
86
|
+
}
|
87
|
+
else {
|
88
|
+
*cmp = 1;
|
89
|
+
}
|
90
|
+
goto cleanup;
|
91
|
+
}
|
92
|
+
}
|
93
|
+
node_number1 = node1->right;
|
94
|
+
node_number2 = node2->right;
|
95
|
+
rl_list_node_nocache_destroy(db, node1);
|
96
|
+
rl_list_node_nocache_destroy(db, node2);
|
97
|
+
node1 = node2 = NULL;
|
98
|
+
}
|
99
|
+
cleanup:
|
100
|
+
rl_list_nocache_destroy(db, list1);
|
101
|
+
rl_list_nocache_destroy(db, list2);
|
102
|
+
if (node1) {
|
103
|
+
rl_list_node_nocache_destroy(db, node1);
|
104
|
+
}
|
105
|
+
if (node2) {
|
106
|
+
rl_list_node_nocache_destroy(db, node2);
|
107
|
+
}
|
108
|
+
return retval;
|
109
|
+
}
|
110
|
+
|
111
|
+
int rl_multi_string_cmp_str(struct rlite *db, long p1, unsigned char *str, long len, int *cmp)
|
112
|
+
{
|
113
|
+
rl_list *list1 = NULL;
|
114
|
+
rl_list_node *node1 = NULL;
|
115
|
+
void *_list, *_node;
|
116
|
+
unsigned char *str1;
|
117
|
+
|
118
|
+
int retval;
|
119
|
+
RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_list_long, p1, &rl_list_type_long, &_list, 0);
|
120
|
+
list1 = _list;
|
121
|
+
|
122
|
+
long node_number1 = list1->left, i, pos = 0;
|
123
|
+
int first = 1;
|
124
|
+
long cmplen;
|
125
|
+
long stored_length = 0;
|
126
|
+
*cmp = 0;
|
127
|
+
do {
|
128
|
+
if (node_number1 == 0) {
|
129
|
+
*cmp = len == 0 ? 0 : -1;
|
130
|
+
break;
|
131
|
+
}
|
132
|
+
RL_CALL(rl_read, RL_FOUND, db, list1->type->list_node_type, node_number1, list1, &_node, 0);
|
133
|
+
node1 = _node;
|
134
|
+
if (first) {
|
135
|
+
stored_length = *(long *)node1->elements[0];
|
136
|
+
if (stored_length == 0) {
|
137
|
+
*cmp = len == 0 ? 0 : -1;
|
138
|
+
}
|
139
|
+
}
|
140
|
+
for (i = first ? 1 : 0; i < node1->size; i++) {
|
141
|
+
RL_CALL(rl_string_get, RL_OK, db, &str1, *(long *)node1->elements[i]);
|
142
|
+
cmplen = db->page_size < len - pos ? db->page_size : len - pos;
|
143
|
+
if (cmplen == 0) {
|
144
|
+
// finished with str, the page_multi_string starts with str
|
145
|
+
*cmp = 1;
|
146
|
+
break;
|
147
|
+
}
|
148
|
+
*cmp = memcmp(str1, &str[pos], cmplen);
|
149
|
+
if (*cmp != 0) {
|
150
|
+
if (*cmp < 0) {
|
151
|
+
*cmp = -1;
|
152
|
+
}
|
153
|
+
else {
|
154
|
+
*cmp = 1;
|
155
|
+
}
|
156
|
+
goto cleanup;
|
157
|
+
}
|
158
|
+
pos += cmplen;
|
159
|
+
}
|
160
|
+
if (*cmp == 0 && len == pos && stored_length != len) {
|
161
|
+
*cmp = stored_length > len ? 1 : -1;
|
162
|
+
}
|
163
|
+
first = 0;
|
164
|
+
node_number1 = node1->right;
|
165
|
+
rl_list_node_nocache_destroy(db, node1);
|
166
|
+
node1 = NULL;
|
167
|
+
}
|
168
|
+
while (len > pos);
|
169
|
+
retval = RL_OK;
|
170
|
+
cleanup:
|
171
|
+
rl_list_nocache_destroy(db, list1);
|
172
|
+
if (node1) {
|
173
|
+
rl_list_node_nocache_destroy(db, node1);
|
174
|
+
}
|
175
|
+
return retval;
|
176
|
+
}
|
177
|
+
|
178
|
+
static int append(struct rlite *db, rl_list *list, long list_page_number, const unsigned char *data, long size)
|
179
|
+
{
|
180
|
+
int retval = RL_OK;
|
181
|
+
long *page;
|
182
|
+
long pos = 0, to_copy;
|
183
|
+
unsigned char *string = NULL;
|
184
|
+
while (pos < size) {
|
185
|
+
RL_MALLOC(page, sizeof(*page));
|
186
|
+
retval = rl_string_create(db, &string, page);
|
187
|
+
if (retval != RL_OK) {
|
188
|
+
goto cleanup;
|
189
|
+
}
|
190
|
+
to_copy = db->page_size;
|
191
|
+
if (pos + to_copy > size) {
|
192
|
+
to_copy = size - pos;
|
193
|
+
}
|
194
|
+
memcpy(string, &data[pos], sizeof(unsigned char) * to_copy);
|
195
|
+
string = NULL;
|
196
|
+
RL_CALL(rl_list_add_element, RL_OK, db, list, list_page_number, page, -1);
|
197
|
+
page = NULL;
|
198
|
+
pos += to_copy;
|
199
|
+
}
|
200
|
+
cleanup:
|
201
|
+
rl_free(string);
|
202
|
+
rl_free(page);
|
203
|
+
return retval;
|
204
|
+
}
|
205
|
+
|
206
|
+
int rl_multi_string_append(struct rlite *db, long number, const unsigned char *data, long datasize, long *newlength)
|
207
|
+
{
|
208
|
+
rl_list *list = NULL;
|
209
|
+
unsigned char *tmp_data;
|
210
|
+
void *tmp;
|
211
|
+
int retval;
|
212
|
+
long size, cpsize;
|
213
|
+
long string_page_number;
|
214
|
+
|
215
|
+
RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_list_long, number, &rl_list_type_long, &tmp, 0);
|
216
|
+
list = tmp;
|
217
|
+
|
218
|
+
RL_CALL(rl_list_get_element, RL_FOUND, db, list, &tmp, 0);
|
219
|
+
size = *(long *)tmp;
|
220
|
+
RL_MALLOC(tmp, sizeof(long));
|
221
|
+
*(long *)tmp = size + datasize;
|
222
|
+
RL_CALL(rl_list_add_element, RL_OK, db, list, number, tmp, 0);
|
223
|
+
RL_CALL(rl_list_remove_element, RL_OK, db, list, number, 1);
|
224
|
+
if (newlength) {
|
225
|
+
*newlength = size + datasize;
|
226
|
+
}
|
227
|
+
|
228
|
+
size = size % db->page_size;
|
229
|
+
|
230
|
+
if (size > 0) {
|
231
|
+
RL_CALL(rl_list_get_element, RL_FOUND, db, list, &tmp, -1);
|
232
|
+
string_page_number = *(long *)tmp;
|
233
|
+
RL_CALL(rl_string_get, RL_OK, db, &tmp_data, string_page_number);
|
234
|
+
cpsize = db->page_size - size;
|
235
|
+
if (cpsize > datasize) {
|
236
|
+
cpsize = datasize;
|
237
|
+
}
|
238
|
+
memcpy(&tmp_data[size], data, cpsize * sizeof(unsigned char));
|
239
|
+
RL_CALL(rl_write, RL_OK, db, &rl_data_type_string, string_page_number, tmp_data);
|
240
|
+
data = &data[cpsize];
|
241
|
+
datasize -= cpsize;
|
242
|
+
}
|
243
|
+
|
244
|
+
if (datasize > 0) {
|
245
|
+
RL_CALL(append, RL_OK, db, list, number, data, datasize);
|
246
|
+
}
|
247
|
+
|
248
|
+
retval = RL_OK;
|
249
|
+
cleanup:
|
250
|
+
return retval;
|
251
|
+
}
|
252
|
+
|
253
|
+
int rl_multi_string_getrange(struct rlite *db, long number, unsigned char **_data, long *size, long start, long stop)
|
254
|
+
{
|
255
|
+
long totalsize;
|
256
|
+
rl_list *list = NULL;
|
257
|
+
rl_list_node *node = NULL;
|
258
|
+
void *_list, *tmp;
|
259
|
+
unsigned char *data = NULL;
|
260
|
+
int retval;
|
261
|
+
RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_list_long, number, &rl_list_type_long, &_list, 0);
|
262
|
+
list = _list;
|
263
|
+
unsigned char *tmp_data;
|
264
|
+
long i, pos = 0, pagesize, pagestart;
|
265
|
+
|
266
|
+
RL_CALL(rl_list_get_element, RL_FOUND, db, list, &tmp, 0);
|
267
|
+
totalsize = *(long *)tmp;
|
268
|
+
if (totalsize == 0) {
|
269
|
+
*size = 0;
|
270
|
+
if (_data) {
|
271
|
+
*_data = NULL;
|
272
|
+
}
|
273
|
+
retval = RL_OK;
|
274
|
+
goto cleanup;
|
275
|
+
}
|
276
|
+
rl_normalize_string_range(totalsize, &start, &stop);
|
277
|
+
if (stop < start) {
|
278
|
+
*size = 0;
|
279
|
+
if (_data) {
|
280
|
+
*_data = NULL;
|
281
|
+
}
|
282
|
+
retval = RL_OK;
|
283
|
+
goto cleanup;
|
284
|
+
}
|
285
|
+
*size = stop - start + 1;
|
286
|
+
if (!_data) {
|
287
|
+
retval = RL_OK;
|
288
|
+
goto cleanup;
|
289
|
+
}
|
290
|
+
|
291
|
+
RL_MALLOC(data, sizeof(unsigned char) * (*size + 1));
|
292
|
+
|
293
|
+
i = start / db->page_size;
|
294
|
+
pagestart = start % db->page_size;
|
295
|
+
// pos = i * db->page_size + pagestart;
|
296
|
+
// the first element in the list is the length of the array, skip to the second
|
297
|
+
for (i++; i < list->size; i++) {
|
298
|
+
RL_CALL(rl_list_get_element, RL_FOUND, db, list, &tmp, i);
|
299
|
+
RL_CALL(rl_string_get, RL_OK, db, &tmp_data, *(long *)tmp);
|
300
|
+
pagesize = db->page_size - pagestart;
|
301
|
+
if (pos + pagesize > *size) {
|
302
|
+
pagesize = *size - pos;
|
303
|
+
}
|
304
|
+
memcpy(&data[pos], &tmp_data[pagestart], sizeof(unsigned char) * pagesize);
|
305
|
+
pos += pagesize;
|
306
|
+
pagestart = 0;
|
307
|
+
}
|
308
|
+
data[*size] = 0;
|
309
|
+
*_data = data;
|
310
|
+
retval = RL_OK;
|
311
|
+
cleanup:
|
312
|
+
if (retval != RL_OK) {
|
313
|
+
rl_free(data);
|
314
|
+
}
|
315
|
+
if (list) {
|
316
|
+
rl_list_nocache_destroy(db, list);
|
317
|
+
}
|
318
|
+
if (node) {
|
319
|
+
rl_list_node_nocache_destroy(db, node);
|
320
|
+
}
|
321
|
+
return retval;
|
322
|
+
}
|
323
|
+
|
324
|
+
int rl_multi_string_get(struct rlite *db, long number, unsigned char **_data, long *size)
|
325
|
+
{
|
326
|
+
return rl_multi_string_getrange(db, number, _data, size, 0, -1);
|
327
|
+
}
|
328
|
+
|
329
|
+
int rl_multi_string_set(struct rlite *db, long *number, const unsigned char *data, long size)
|
330
|
+
{
|
331
|
+
int retval;
|
332
|
+
long *page = NULL;
|
333
|
+
rl_list *list = NULL;
|
334
|
+
RL_CALL(rl_list_create, RL_OK, db, &list, &rl_list_type_long);
|
335
|
+
*number = db->next_empty_page;
|
336
|
+
RL_CALL(rl_write, RL_OK, db, &rl_data_type_list_long, *number, list);
|
337
|
+
RL_MALLOC(page, sizeof(*page));
|
338
|
+
*page = size;
|
339
|
+
RL_CALL(rl_list_add_element, RL_OK, db, list, *number, page, -1);
|
340
|
+
page = NULL;
|
341
|
+
RL_CALL(append, RL_OK, db, list, *number, data, size);
|
342
|
+
cleanup:
|
343
|
+
return retval;
|
344
|
+
}
|
345
|
+
int rl_multi_string_setrange(struct rlite *db, long number, const unsigned char *data, long size, long offset, long *newlength)
|
346
|
+
{
|
347
|
+
long oldsize, newsize;
|
348
|
+
rl_list *list = NULL;
|
349
|
+
void *_list, *tmp;
|
350
|
+
int retval;
|
351
|
+
RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_list_long, number, &rl_list_type_long, &_list, 1);
|
352
|
+
list = _list;
|
353
|
+
unsigned char *tmp_data;
|
354
|
+
long i, pagesize, pagestart, page;
|
355
|
+
if (offset < 0) {
|
356
|
+
retval = RL_INVALID_PARAMETERS;
|
357
|
+
goto cleanup;
|
358
|
+
}
|
359
|
+
|
360
|
+
RL_CALL(rl_list_get_element, RL_FOUND, db, list, &tmp, 0);
|
361
|
+
oldsize = *(long *)tmp;
|
362
|
+
if (oldsize > offset) {
|
363
|
+
i = offset / db->page_size;
|
364
|
+
pagestart = offset % db->page_size;
|
365
|
+
|
366
|
+
newsize = offset + size;
|
367
|
+
if (newsize > (list->size - 1) * db->page_size) {
|
368
|
+
newsize = (list->size - 1) * db->page_size;
|
369
|
+
}
|
370
|
+
if (newsize > oldsize) {
|
371
|
+
RL_CALL(rl_list_remove_element, RL_OK, db, list, number, 0);
|
372
|
+
RL_MALLOC(tmp, sizeof(long));
|
373
|
+
*(long *)tmp = newsize;
|
374
|
+
RL_CALL(rl_list_add_element, RL_OK, db, list, number, tmp, 0);
|
375
|
+
}
|
376
|
+
|
377
|
+
for (i++; size > 0 && i < list->size; i++) {
|
378
|
+
RL_CALL(rl_list_get_element, RL_FOUND, db, list, &tmp, i);
|
379
|
+
page = *(long *)tmp;
|
380
|
+
RL_CALL(rl_string_get, RL_OK, db, &tmp_data, page);
|
381
|
+
pagesize = db->page_size - pagestart;
|
382
|
+
if (pagesize > size) {
|
383
|
+
pagesize = size;
|
384
|
+
}
|
385
|
+
memcpy(&tmp_data[pagestart], data, sizeof(char) * pagesize);
|
386
|
+
RL_CALL(rl_write, RL_OK, db, &rl_data_type_string, page, tmp_data);
|
387
|
+
|
388
|
+
// if there's more bytes that did not enter in this page it will be caught with an append
|
389
|
+
if (oldsize < pagesize + pagestart) {
|
390
|
+
oldsize = pagesize + pagestart;
|
391
|
+
}
|
392
|
+
data += pagesize;
|
393
|
+
offset += pagesize;
|
394
|
+
size -= pagesize;
|
395
|
+
pagestart = 0;
|
396
|
+
}
|
397
|
+
if (newlength) {
|
398
|
+
*newlength = oldsize;
|
399
|
+
}
|
400
|
+
}
|
401
|
+
|
402
|
+
if (oldsize < offset) {
|
403
|
+
RL_MALLOC(tmp_data, sizeof(char) * (size + offset - oldsize));
|
404
|
+
memset(tmp_data, 0, offset - oldsize);
|
405
|
+
memcpy(&tmp_data[offset - oldsize], data, sizeof(char) * size);
|
406
|
+
RL_CALL(rl_multi_string_append, RL_OK, db, number, tmp_data, size + offset - oldsize, newlength);
|
407
|
+
rl_free(tmp_data);
|
408
|
+
}
|
409
|
+
else if (oldsize == offset && size > 0) {
|
410
|
+
RL_CALL(rl_multi_string_append, RL_OK, db, number, data, size, newlength);
|
411
|
+
}
|
412
|
+
retval = RL_OK;
|
413
|
+
cleanup:
|
414
|
+
return retval;
|
415
|
+
}
|
416
|
+
|
417
|
+
|
418
|
+
int rl_multi_string_sha1(struct rlite *db, unsigned char digest[20], long number)
|
419
|
+
{
|
420
|
+
unsigned char *data;
|
421
|
+
long datalen;
|
422
|
+
SHA1_CTX sha;
|
423
|
+
SHA1Init(&sha);
|
424
|
+
|
425
|
+
void *tmp;
|
426
|
+
rl_list *list;
|
427
|
+
rl_list_iterator *iterator = NULL;
|
428
|
+
int retval;
|
429
|
+
RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_list_long, number, &rl_list_type_long, &tmp, 0);
|
430
|
+
list = tmp;
|
431
|
+
|
432
|
+
RL_CALL(rl_list_iterator_create, RL_OK, db, &iterator, list, 1);
|
433
|
+
|
434
|
+
long size = 0;
|
435
|
+
while ((retval = rl_list_iterator_next(iterator, &tmp)) == RL_OK) {
|
436
|
+
if (size == 0) {
|
437
|
+
size = *(long *)tmp;
|
438
|
+
rl_free(tmp);
|
439
|
+
continue;
|
440
|
+
}
|
441
|
+
RL_CALL(rl_string_get, RL_OK, db, &data, *(long *)tmp);
|
442
|
+
datalen = size > db->page_size ? db->page_size : size;
|
443
|
+
SHA1Update(&sha, data, datalen);
|
444
|
+
size -= datalen;
|
445
|
+
rl_free(tmp);
|
446
|
+
}
|
447
|
+
iterator = NULL;
|
448
|
+
|
449
|
+
if (retval != RL_END) {
|
450
|
+
goto cleanup;
|
451
|
+
}
|
452
|
+
|
453
|
+
RL_CALL(rl_list_nocache_destroy, RL_OK, db, list);
|
454
|
+
|
455
|
+
SHA1Final(digest, &sha);
|
456
|
+
retval = RL_OK;
|
457
|
+
cleanup:
|
458
|
+
if (iterator) {
|
459
|
+
rl_list_iterator_destroy(db, iterator);
|
460
|
+
}
|
461
|
+
return retval;
|
462
|
+
}
|
463
|
+
|
464
|
+
int rl_multi_string_pages(struct rlite *db, long page, short *pages)
|
465
|
+
{
|
466
|
+
void *tmp;
|
467
|
+
rl_list *list;
|
468
|
+
rl_list_iterator *iterator = NULL;
|
469
|
+
int retval;
|
470
|
+
RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_list_long, page, &rl_list_type_long, &tmp, 0);
|
471
|
+
list = tmp;
|
472
|
+
|
473
|
+
RL_CALL(rl_list_pages, RL_OK, db, list, pages);
|
474
|
+
RL_CALL(rl_list_iterator_create, RL_OK, db, &iterator, list, 1);
|
475
|
+
|
476
|
+
int first = 1;
|
477
|
+
while ((retval = rl_list_iterator_next(iterator, &tmp)) == RL_OK) {
|
478
|
+
if (first) {
|
479
|
+
first = 0;
|
480
|
+
}
|
481
|
+
else {
|
482
|
+
pages[*(long *)tmp] = 1;
|
483
|
+
}
|
484
|
+
rl_free(tmp);
|
485
|
+
}
|
486
|
+
iterator = NULL;
|
487
|
+
|
488
|
+
if (retval != RL_END) {
|
489
|
+
goto cleanup;
|
490
|
+
}
|
491
|
+
|
492
|
+
RL_CALL(rl_list_nocache_destroy, RL_OK, db, list);
|
493
|
+
|
494
|
+
retval = RL_OK;
|
495
|
+
cleanup:
|
496
|
+
if (iterator) {
|
497
|
+
rl_list_iterator_destroy(db, iterator);
|
498
|
+
}
|
499
|
+
return retval;
|
500
|
+
}
|
501
|
+
|
502
|
+
int rl_multi_string_delete(struct rlite *db, long page)
|
503
|
+
{
|
504
|
+
void *tmp;
|
505
|
+
rl_list *list;
|
506
|
+
rl_list_iterator *iterator = NULL;
|
507
|
+
int retval;
|
508
|
+
RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_list_long, page, &rl_list_type_long, &tmp, 1);
|
509
|
+
list = tmp;
|
510
|
+
|
511
|
+
RL_CALL(rl_list_iterator_create, RL_OK, db, &iterator, list, 1);
|
512
|
+
|
513
|
+
int first = 1;
|
514
|
+
while ((retval = rl_list_iterator_next(iterator, &tmp)) == RL_OK) {
|
515
|
+
if (first) {
|
516
|
+
first = 0;
|
517
|
+
}
|
518
|
+
else {
|
519
|
+
RL_CALL(rl_delete, RL_OK, db, *(long *)tmp);
|
520
|
+
}
|
521
|
+
rl_free(tmp);
|
522
|
+
}
|
523
|
+
iterator = NULL;
|
524
|
+
|
525
|
+
if (retval != RL_END) {
|
526
|
+
goto cleanup;
|
527
|
+
}
|
528
|
+
|
529
|
+
RL_CALL(rl_list_delete, RL_OK, db, list);
|
530
|
+
RL_CALL(rl_delete, RL_OK, db, page);
|
531
|
+
|
532
|
+
retval = RL_OK;
|
533
|
+
cleanup:
|
534
|
+
if (iterator) {
|
535
|
+
rl_list_iterator_destroy(db, iterator);
|
536
|
+
}
|
537
|
+
return retval;
|
538
|
+
}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#ifndef _RL_OBJ_STRING_H
|
2
|
+
#define _RL_OBJ_STRING_H
|
3
|
+
|
4
|
+
struct rlite;
|
5
|
+
|
6
|
+
int rl_normalize_string_range(long totalsize, long *start, long *stop);
|
7
|
+
int rl_multi_string_cmp(struct rlite *db, long p1, long p2, int *cmp);
|
8
|
+
int rl_multi_string_cmp_str(struct rlite *db, long p1, unsigned char *str, long len, int *cmp);
|
9
|
+
int rl_multi_string_getrange(struct rlite *db, long number, unsigned char **_data, long *size, long start, long stop);
|
10
|
+
int rl_multi_string_get(struct rlite *db, long number, unsigned char **data, long *size);
|
11
|
+
int rl_multi_string_setrange(struct rlite *db, long number, const unsigned char *data, long size, long offset, long *newlength);
|
12
|
+
int rl_multi_string_set(struct rlite *db, long *number, const unsigned char *data, long size);
|
13
|
+
int rl_multi_string_append(struct rlite *db, long number, const unsigned char *data, long datasize, long *newlength);
|
14
|
+
int rl_multi_string_sha1(struct rlite *db, unsigned char data[20], long number);
|
15
|
+
int rl_multi_string_pages(struct rlite *db, long page, short *pages);
|
16
|
+
int rl_multi_string_delete(struct rlite *db, long page);
|
17
|
+
|
18
|
+
#endif
|