1 #include <stdio.h>
2 #include <string.h>
3 #include <stddef.h>
4 #include <inttypes.h>
5 #include <assert.h>
6 #include <stdint.h>
7
8 #include <msgpuck.h>
9
10 #include <tarantool/tnt_reply.h>
11 #include <tarantool/tnt_stream.h>
12 #include <tarantool/tnt_buf.h>
13 #include <tarantool/tnt_object.h>
14 #include <tarantool/tnt_proto.h>
15 #include <tarantool/tnt_schema.h>
16 #include <tarantool/tnt_mem.h>
17 #include <tarantool/tnt_select.h>
18
19 #include "tnt_assoc.h"
20
21 static inline void
tnt_schema_ival_free(struct tnt_schema_ival * val)22 tnt_schema_ival_free(struct tnt_schema_ival *val) {
23 if (val) tnt_mem_free((void *)val->name);
24 tnt_mem_free(val);
25 }
26
27 static inline void
tnt_schema_index_free(struct mh_assoc_t * schema)28 tnt_schema_index_free(struct mh_assoc_t *schema) {
29 mh_int_t pos = 0;
30 mh_int_t index_slot = 0;
31 mh_foreach(schema, pos) {
32 struct tnt_schema_ival *ival =
33 (*mh_assoc_node(schema, pos))->data;
34 struct assoc_val *av1 = NULL, *av2 = NULL;
35 do {
36 struct assoc_key key_number = {
37 (void *)&(ival->number),
38 sizeof(uint32_t)
39 };
40 index_slot = mh_assoc_find(schema, &key_number, NULL);
41 if (index_slot == mh_end(schema))
42 break;
43 av1 = *mh_assoc_node(schema, index_slot);
44 mh_assoc_del(schema, index_slot, NULL);
45 } while (0);
46 do {
47 struct assoc_key key_string = {
48 ival->name,
49 ival->name_len
50 };
51 index_slot = mh_assoc_find(schema, &key_string, NULL);
52 if (index_slot == mh_end(schema))
53 break;
54 av2 = *mh_assoc_node(schema, index_slot);
55 mh_assoc_del(schema, index_slot, NULL);
56 } while (0);
57 tnt_schema_ival_free(ival);
58 if (av1) tnt_mem_free((void *)av1);
59 if (av2) tnt_mem_free((void *)av2);
60 }
61 }
62
63 static inline void
tnt_schema_sval_free(struct tnt_schema_sval * val)64 tnt_schema_sval_free(struct tnt_schema_sval *val) {
65 if (val) {
66 tnt_mem_free(val->name);
67 if (val->index) {
68 tnt_schema_index_free(val->index);
69 mh_assoc_delete(val->index);
70 }
71 }
72 tnt_mem_free(val);
73 }
74
75 static inline void
tnt_schema_space_free(struct mh_assoc_t * schema)76 tnt_schema_space_free(struct mh_assoc_t *schema) {
77 mh_int_t pos = 0;
78 mh_int_t space_slot = 0;
79 mh_foreach(schema, pos) {
80 struct tnt_schema_sval *sval = NULL;
81 sval = (*mh_assoc_node(schema, pos))->data;
82 struct assoc_val *av1 = NULL, *av2 = NULL;
83 do {
84 struct assoc_key key_number = {
85 (void *)&(sval->number),
86 sizeof(uint32_t)
87 };
88 space_slot = mh_assoc_find(schema, &key_number, NULL);
89 if (space_slot == mh_end(schema))
90 break;
91 av1 = *mh_assoc_node(schema, space_slot);
92 mh_assoc_del(schema, space_slot, NULL);
93 } while (0);
94 do {
95 struct assoc_key key_string = {
96 sval->name,
97 sval->name_len
98 };
99 space_slot = mh_assoc_find(schema, &key_string, NULL);
100 if (space_slot == mh_end(schema))
101 break;
102 av2 = *mh_assoc_node(schema, space_slot);
103 mh_assoc_del(schema, space_slot, NULL);
104 } while (0);
105 tnt_schema_sval_free(sval);
106 if (av1) tnt_mem_free((void *)av1);
107 if (av2) tnt_mem_free((void *)av2);
108 }
109 }
110
111 static inline int
tnt_schema_add_space(struct mh_assoc_t * schema,const char ** data)112 tnt_schema_add_space(struct mh_assoc_t *schema, const char **data)
113 {
114 struct tnt_schema_sval *space = NULL;
115 struct assoc_val *space_string = NULL, *space_number = NULL;
116 const char *tuple = *data;
117 if (mp_typeof(*tuple) != MP_ARRAY)
118 goto error;
119 uint32_t tuple_len = mp_decode_array(&tuple); (void )tuple_len;
120 space = tnt_mem_alloc(sizeof(struct tnt_schema_sval));
121 if (!space)
122 goto error;
123 memset(space, 0, sizeof(struct tnt_schema_sval));
124 if (mp_typeof(*tuple) != MP_UINT)
125 goto error;
126 space->number = mp_decode_uint(&tuple);
127 mp_next(&tuple); /* skip owner id */
128 if (mp_typeof(*tuple) != MP_STR)
129 goto error;
130 const char *name_tmp = mp_decode_str(&tuple, &space->name_len);
131 space->name = tnt_mem_alloc(space->name_len);
132 if (!space->name)
133 goto error;
134 memcpy(space->name, name_tmp, space->name_len);
135
136 space->index = mh_assoc_new();
137 if (!space->index)
138 goto error;
139 space_string = tnt_mem_alloc(sizeof(struct assoc_val));
140 if (!space_string)
141 goto error;
142 space_string->key.id = space->name;
143 space_string->key.id_len = space->name_len;
144 space_string->data = space;
145 space_number = tnt_mem_alloc(sizeof(struct assoc_val));
146 if (!space_number)
147 goto error;
148 space_number->key.id = (void *)&(space->number);
149 space_number->key.id_len = sizeof(space->number);
150 space_number->data = space;
151 mh_assoc_put(schema, (const struct assoc_val **)&space_string,
152 NULL, NULL);
153 mh_assoc_put(schema, (const struct assoc_val **)&space_number,
154 NULL, NULL);
155 mp_next(data);
156 return 0;
157 error:
158 mp_next(data);
159 tnt_schema_sval_free(space);
160 if (space_string) tnt_mem_free(space_string);
161 if (space_number) tnt_mem_free(space_number);
162 return -1;
163 }
164
tnt_schema_add_spaces(struct tnt_schema * schema_obj,struct tnt_reply * r)165 int tnt_schema_add_spaces(struct tnt_schema *schema_obj, struct tnt_reply *r) {
166 struct mh_assoc_t *schema = schema_obj->space_hash;
167 const char *tuple = r->data;
168 if (mp_check(&tuple, tuple + (r->data_end - r->data)))
169 return -1;
170 tuple = r->data;
171 if (mp_typeof(*tuple) != MP_ARRAY)
172 return -1;
173 uint32_t space_count = mp_decode_array(&tuple);
174 while (space_count-- > 0) {
175 if (tnt_schema_add_space(schema, &tuple))
176 return -1;
177 }
178 return 0;
179 }
180
181 static inline int
tnt_schema_add_index(struct mh_assoc_t * schema,const char ** data)182 tnt_schema_add_index(struct mh_assoc_t *schema, const char **data) {
183 const struct tnt_schema_sval *space = NULL;
184 struct tnt_schema_ival *index = NULL;
185 struct assoc_val *index_number = NULL, *index_string = NULL;
186 const char *tuple = *data;
187 if (mp_typeof(*tuple) != MP_ARRAY)
188 goto error;
189 int64_t tuple_len = mp_decode_array(&tuple); (void )tuple_len;
190 uint32_t space_number = mp_decode_uint(&tuple);
191 if (mp_typeof(*tuple) != MP_UINT)
192 goto error;
193 struct assoc_key space_key = {
194 (void *)&(space_number),
195 sizeof(uint32_t)
196 };
197 mh_int_t space_slot = mh_assoc_find(schema, &space_key, NULL);
198 if (space_slot == mh_end(schema))
199 return -1;
200 space = (*mh_assoc_node(schema, space_slot))->data;
201 index = tnt_mem_alloc(sizeof(struct tnt_schema_ival));
202 if (!index)
203 goto error;
204 memset(index, 0, sizeof(struct tnt_schema_ival));
205 if (mp_typeof(*tuple) != MP_UINT)
206 goto error;
207 index->number = mp_decode_uint(&tuple);
208 if (mp_typeof(*tuple) != MP_STR)
209 goto error;
210 const char *name_tmp = mp_decode_str(&tuple, &index->name_len);
211 index->name = tnt_mem_alloc(index->name_len);
212 if (!index->name)
213 goto error;
214 memcpy((void *)index->name, name_tmp, index->name_len);
215
216 index_string = tnt_mem_alloc(sizeof(struct assoc_val));
217 if (!index_string) goto error;
218 index_string->key.id = index->name;
219 index_string->key.id_len = index->name_len;
220 index_string->data = index;
221 index_number = tnt_mem_alloc(sizeof(struct assoc_val));
222 if (!index_number) goto error;
223 index_number->key.id = (void *)&(index->number);
224 index_number->key.id_len = sizeof(uint32_t);
225 index_number->data = index;
226 mh_assoc_put(space->index, (const struct assoc_val **)&index_string,
227 NULL, NULL);
228 mh_assoc_put(space->index, (const struct assoc_val **)&index_number,
229 NULL, NULL);
230 mp_next(data);
231 return 0;
232 error:
233 mp_next(data);
234 if (index_string) tnt_mem_free(index_string);
235 if (index_number) tnt_mem_free(index_number);
236 tnt_schema_ival_free(index);
237 return -1;
238 }
239
tnt_schema_add_indexes(struct tnt_schema * schema_obj,struct tnt_reply * r)240 int tnt_schema_add_indexes(struct tnt_schema *schema_obj, struct tnt_reply *r) {
241 struct mh_assoc_t *schema = schema_obj->space_hash;
242 const char *tuple = r->data;
243 if (mp_check(&tuple, tuple + (r->data_end - r->data)))
244 return -1;
245 tuple = r->data;
246 if (mp_typeof(*tuple) != MP_ARRAY)
247 return -1;
248 uint32_t space_count = mp_decode_array(&tuple);
249 while (space_count-- > 0) {
250 if (tnt_schema_add_index(schema, &tuple))
251 return -1;
252 }
253 return 0;
254 }
255
tnt_schema_stosid(struct tnt_schema * schema_obj,const char * name,uint32_t name_len)256 int32_t tnt_schema_stosid(struct tnt_schema *schema_obj, const char *name,
257 uint32_t name_len) {
258 struct mh_assoc_t *schema = schema_obj->space_hash;
259 struct assoc_key space_key = {name, name_len};
260 mh_int_t space_slot = mh_assoc_find(schema, &space_key, NULL);
261 if (space_slot == mh_end(schema))
262 return -1;
263 const struct tnt_schema_sval *space =
264 (*mh_assoc_node(schema, space_slot))->data;
265 return space->number;
266 }
267
tnt_schema_stoiid(struct tnt_schema * schema_obj,uint32_t sid,const char * name,uint32_t name_len)268 int32_t tnt_schema_stoiid(struct tnt_schema *schema_obj, uint32_t sid,
269 const char *name, uint32_t name_len) {
270 struct mh_assoc_t *schema = schema_obj->space_hash;
271 struct assoc_key space_key = {(void *)&sid, sizeof(uint32_t)};
272 mh_int_t space_slot = mh_assoc_find(schema, &space_key, NULL);
273 if (space_slot == mh_end(schema))
274 return -1;
275 const struct tnt_schema_sval *space =
276 (*mh_assoc_node(schema, space_slot))->data;
277 struct assoc_key index_key = {name, name_len};
278 mh_int_t index_slot = mh_assoc_find(space->index, &index_key, NULL);
279 if (index_slot == mh_end(space->index))
280 return -1;
281 const struct tnt_schema_ival *index =
282 (*mh_assoc_node(space->index, index_slot))->data;
283 return index->number;
284 }
285
tnt_schema_new(struct tnt_schema * s)286 struct tnt_schema *tnt_schema_new(struct tnt_schema *s) {
287 int alloc = (s == NULL);
288 if (!s) {
289 s = tnt_mem_alloc(sizeof(struct tnt_schema));
290 if (!s) return NULL;
291 }
292 s->space_hash = mh_assoc_new();
293 s->alloc = alloc;
294 return s;
295 }
296
tnt_schema_flush(struct tnt_schema * obj)297 void tnt_schema_flush(struct tnt_schema *obj) {
298 tnt_schema_space_free(obj->space_hash);
299 }
300
tnt_schema_free(struct tnt_schema * obj)301 void tnt_schema_free(struct tnt_schema *obj) {
302 if (obj == NULL)
303 return;
304 tnt_schema_space_free(obj->space_hash);
305 mh_assoc_delete(obj->space_hash);
306 }
307
308 ssize_t
tnt_get_space(struct tnt_stream * s)309 tnt_get_space(struct tnt_stream *s)
310 {
311 struct tnt_stream *obj = tnt_object(NULL);
312 if (obj == NULL)
313 return -1;
314
315 tnt_object_add_array(obj, 0);
316 ssize_t retval = tnt_select(s, tnt_vsp_space, tnt_vin_name,
317 UINT32_MAX, 0, TNT_ITER_ALL, obj);
318 tnt_stream_free(obj);
319 return retval;
320 }
321
322 ssize_t
tnt_get_index(struct tnt_stream * s)323 tnt_get_index(struct tnt_stream *s)
324 {
325 struct tnt_stream *obj = tnt_object(NULL);
326 if (obj == NULL)
327 return -1;
328
329 tnt_object_add_array(obj, 0);
330 ssize_t retval = tnt_select(s, tnt_vsp_index, tnt_vin_name,
331 UINT32_MAX, 0, TNT_ITER_ALL, obj);
332 tnt_stream_free(obj);
333 return retval;
334 }
335