Skip to content
Snippets Groups Projects
Commit b5e73e3f authored by Dmitry Simonenko's avatar Dmitry Simonenko
Browse files

connector-c-lite: reply parsing and tuple/field iterations added.

parent 6a734900
No related branches found
No related tags found
No related merge requests found
...@@ -5,6 +5,9 @@ ...@@ -5,6 +5,9 @@
* TP - Tarantool Protocol request constructor * TP - Tarantool Protocol request constructor
* (http://tarantool.org) * (http://tarantool.org)
* *
* protocol description:
* https://github.com/mailru/tarantool/blob/master/doc/box-protocol.txt
*
* Copyright (c) 2012-2013 Mail.Ru Group * Copyright (c) 2012-2013 Mail.Ru Group
* *
* Redistribution and use in source and binary forms, with or * Redistribution and use in source and binary forms, with or
...@@ -41,6 +44,7 @@ ...@@ -41,6 +44,7 @@
#define tp_function_unused __attribute__((unused)) #define tp_function_unused __attribute__((unused))
#define tp_packed __attribute__((packed)) #define tp_packed __attribute__((packed))
#define tp_inline __attribute__((forceinline))
#define tp_noinline __attribute__((noinline)) #define tp_noinline __attribute__((noinline))
#define tp_likely(expr) __builtin_expect(!! (expr), 1) #define tp_likely(expr) __builtin_expect(!! (expr), 1)
...@@ -101,6 +105,7 @@ struct tp { ...@@ -101,6 +105,7 @@ struct tp {
char *s, *p, *e; char *s, *p, *e;
char *t, *f, *u; char *t, *f, *u;
char *c; char *c;
uint32_t tsz, fsz, tc;
uint32_t code; uint32_t code;
uint32_t cnt; uint32_t cnt;
tp_resizer resizer; tp_resizer resizer;
...@@ -124,11 +129,17 @@ tp_unused(struct tp *p) { ...@@ -124,11 +129,17 @@ tp_unused(struct tp *p) {
tp_function_unused static char* tp_function_unused static char*
tp_reallocator(struct tp *p, size_t req, size_t *size) { tp_reallocator(struct tp *p, size_t req, size_t *size) {
size_t nsz = tp_size(p) * 2; size_t toalloc = tp_size(p) * 2;
if (tp_unlikely(nsz < req)) if (tp_unlikely(toalloc < req))
nsz = req; toalloc = req;
*size = nsz; *size = toalloc;
return realloc(p->s, nsz); return realloc(p->s, toalloc);
}
tp_function_unused static char*
tp_reallocator_noloss(struct tp *p, size_t req, size_t *size) {
*size = tp_size(p) + (req - tp_unused(p));
return realloc(p->s, *size);
} }
static inline void static inline void
...@@ -142,6 +153,8 @@ tp_init(struct tp *p, char *buf, size_t size, ...@@ -142,6 +153,8 @@ tp_init(struct tp *p, char *buf, size_t size,
p->u = NULL; p->u = NULL;
p->c = NULL; p->c = NULL;
p->h = NULL; p->h = NULL;
p->tsz = 0;
p->fsz = 0;
p->cnt = 0; p->cnt = 0;
p->code = 0; p->code = 0;
p->resizer = resizer; p->resizer = resizer;
...@@ -159,9 +172,10 @@ tp_ensure(struct tp *p, size_t size) { ...@@ -159,9 +172,10 @@ tp_ensure(struct tp *p, size_t size) {
if (tp_unlikely(np == NULL)) if (tp_unlikely(np == NULL))
return -1; return -1;
p->p = np + (p->p - p->s); p->p = np + (p->p - p->s);
p->t = np + (p->t - p->s);
if (tp_likely(p->h)) if (tp_likely(p->h))
p->h = (struct tp_h*)(np + (((char*)p->h) - p->s)); p->h = (struct tp_h*)(np + (((char*)p->h) - p->s));
if (tp_likely(p->t))
p->t = np + (p->t - p->s);
if (tp_unlikely(p->f)) if (tp_unlikely(p->f))
p->f = (np + (p->f - p->s)); p->f = (np + (p->f - p->s));
if (tp_unlikely(p->u)) if (tp_unlikely(p->u))
...@@ -171,13 +185,18 @@ tp_ensure(struct tp *p, size_t size) { ...@@ -171,13 +185,18 @@ tp_ensure(struct tp *p, size_t size) {
return sz; return sz;
} }
static inline ssize_t
tp_use(struct tp *p, size_t size) {
p->p += size;
return tp_used(p);
}
static inline ssize_t static inline ssize_t
tp_append(struct tp *p, void *data, size_t size) { tp_append(struct tp *p, void *data, size_t size) {
if (tp_unlikely(tp_ensure(p, size) == -1)) if (tp_unlikely(tp_ensure(p, size) == -1))
return -1; return -1;
memcpy(p->p, data, size); memcpy(p->p, data, size);
p->p += size; return tp_use(p, size);
return tp_used(p);
} }
static inline void static inline void
...@@ -239,6 +258,46 @@ tp_leb128save(struct tp *p, uint32_t value) { ...@@ -239,6 +258,46 @@ tp_leb128save(struct tp *p, uint32_t value) {
*(p->p++) = ((value) & 0x7F); *(p->p++) = ((value) & 0x7F);
} }
static tp_noinline int
tp_leb128load_slowpath(struct tp *p, uint32_t *value) {
if (tp_likely(! (p->f[2] & 0x80))) {
*value = (p->f[0] & 0x7f) << 14 |
(p->f[1] & 0x7f) << 7 |
(p->f[2] & 0x7f);
p->f += 3;
} else
if (! (p->f[3] & 0x80)) {
*value = (p->f[0] & 0x7f) << 21 |
(p->f[1] & 0x7f) << 14 |
(p->f[2] & 0x7f) << 7 |
(p->f[3] & 0x7f);
p->f += 4;
} else
if (! (p->f[4] & 0x80)) {
*value = (p->f[0] & 0x7f) << 28 |
(p->f[1] & 0x7f) << 21 |
(p->f[2] & 0x7f) << 14 |
(p->f[3] & 0x7f) << 7 |
(p->f[4] & 0x7f);
p->f += 5;
} else
return -1;
return 0;
}
static inline int
tp_leb128load(struct tp *p, uint32_t *value) {
if (tp_likely(! (p->f[0] & 0x80))) {
*value = *(p->f++) & 0x7f;
} else
if (tp_likely(! (p->f[1] & 0x80))) {
*value = (p->f[0] & 0x7f) << 7 | (p->f[1] & 0x7f);
p->f += 2;
} else
return tp_leb128load_slowpath(p, value);
return 0;
}
static inline ssize_t static inline ssize_t
tp_field(struct tp *p, char *data, size_t size) { tp_field(struct tp *p, char *data, size_t size) {
assert(p->h != NULL); assert(p->h != NULL);
...@@ -424,9 +483,10 @@ tp_sz(struct tp *p, char *sz) { ...@@ -424,9 +483,10 @@ tp_sz(struct tp *p, char *sz) {
static ssize_t static ssize_t
tp_required(struct tp *p) { tp_required(struct tp *p) {
size_t used = tp_used(p); register size_t used = tp_used(p);
if (tp_unlikely(used < sizeof(struct tp_h))) if (tp_unlikely(used < sizeof(struct tp_h)))
return sizeof(struct tp_h) - used; return sizeof(struct tp_h) - used;
used -= sizeof(struct tp_h);
register struct tp_h *h = (struct tp_h*)p->s; register struct tp_h *h = (struct tp_h*)p->s;
return (tp_likely(used < h->len)) ? return (tp_likely(used < h->len)) ?
h->len - used : used - h->len; h->len - used : used - h->len;
...@@ -450,6 +510,11 @@ tp_replyerror(struct tp *p) { ...@@ -450,6 +510,11 @@ tp_replyerror(struct tp *p) {
return p->c; return p->c;
} }
static inline int
tp_replyerrorlen(struct tp *p) {
return tp_unfetched(p) + tp_required(p);
}
static inline uint32_t static inline uint32_t
tp_replycount(struct tp *p) { tp_replycount(struct tp *p) {
return p->cnt; return p->cnt;
...@@ -489,56 +554,85 @@ tp_reply(struct tp *p) { ...@@ -489,56 +554,85 @@ tp_reply(struct tp *p) {
if (tp_unlikely(tp_unfetched(p) == 0)) if (tp_unlikely(tp_unfetched(p) == 0))
return p->code; return p->code;
p->cnt = *(uint32_t*)tp_fetch(p, sizeof(uint32_t)); p->cnt = *(uint32_t*)tp_fetch(p, sizeof(uint32_t));
p->t = p->c;
return p->code; return p->code;
} }
static inline void static inline void
tp_rewind(struct tp *p) { tp_rewind(struct tp *p) {
p->t = p->c; p->t = NULL;
p->f = NULL;
} }
static inline void static inline void
tp_rewindfield(struct tp *p) { tp_rewindfield(struct tp *p) {
p->f = p->t; p->f = NULL;
} }
static inline uint32_t static inline uint32_t
tp_fqtuplesize(char *p) { tp_tuplesize(struct tp *p) {
return *(uint32_t*)p; return *(uint32_t*)(p->t - 4);
} }
static inline uint32_t static inline char*
tp_fqtuplecount(char *p) { tp_tupleend(struct tp *p) {
return *(uint32_t*)(p + 4); /* tuple_size + p->t + cardinaltiy_size +
* fields_size */
return p->t + p->tsz + 4;
}
static inline int
tp_hasdata(struct tp *p) {
return tp_unfetched(p) > 0;
}
static inline int
tp_hasnext(struct tp *p) {
assert(p->t != NULL);
return (p->e - tp_tupleend(p)) >= 4;
}
static inline int
tp_hasnextfield(struct tp *p) {
assert(p->t != NULL);
register char *f = p->f + p->fsz;
if (tp_unlikely(p->f == NULL))
f = p->t + 4;
return (tp_tupleend(p) - f) >= 1;
} }
static inline char* static inline char*
tp_next(struct tp *p) { tp_next(struct tp *p) {
assert(p->t != NULL); if (tp_unlikely(p->t == NULL)) {
if ((p->t - p->e) < sizeof(uint32_t)) if (tp_unlikely(! tp_hasdata(p)))
return NULL;
p->t = p->c + 4;
goto fetch;
}
if (tp_unlikely(! tp_hasnext(p)))
return NULL; return NULL;
char *c = p->t; p->t = tp_tupleend(p) + 4;
uint32_t size = tp_fqtuplesize(c); fetch:
/* tuple size + tuple cardinality */ p->tsz = *(uint32_t*)(p->t - 4);
p->f = p->t + 8; p->f = NULL;
p->t += size; return p->t;
return c;
} }
static inline char* static inline char*
tp_nextfield(struct tp *p, size_t *sz) { tp_nextfield(struct tp *p, uint32_t *sz) {
assert(p->t != NULL); assert(p->t != NULL);
assert(p->f != NULL); if (tp_unlikely(p->f == NULL)) {
if ((p->f - p->t) <= 1) p->f = p->t + 4;
goto fetch;
}
if (tp_unlikely(! tp_hasnextfield(p)))
return NULL;
p->f += p->fsz;
fetch:;
register int rc = tp_leb128load(p, &p->fsz);
if (tp_unlikely(rc == -1))
return NULL; return NULL;
(void)sz; *sz = p->fsz;
/* loadsize return p->f;
* set size
* set return data
* inc pointer
*/
return NULL;
} }
#endif /* TP_H_INCLUDED */ #endif /* TP_H_INCLUDED */
...@@ -2,26 +2,90 @@ ...@@ -2,26 +2,90 @@
#include <stdio.h> #include <stdio.h>
#include <tp.h> #include <tp.h>
int main(void) static void reply_print(struct tp *rep) {
char *tu;
while ((tu = tp_next(rep))) {
printf("tuple fields: %d\n", tp_tuplecount(rep));
printf("tuple size: %d\n", tp_tuplesize(rep));
printf("[");
char *field;
uint32_t field_size;
while ((field = tp_nextfield(rep, &field_size))) {
printf("%-.*s", field_size, field);
if (tp_hasnextfield(rep))
printf(", ");
}
printf("]\n");
}
}
static int reply(void) {
struct tp rep;
tp_init(&rep, NULL, 0, tp_reallocator_noloss, NULL);
while (1) {
ssize_t to_read = tp_required(&rep);
printf("to_read: %zu\n", to_read);
if (to_read <= 0)
break;
ssize_t new_size = tp_ensure(&rep, to_read);
printf("new_size: %zu\n", new_size);
if (new_size == -1)
return -1;
int rc = fread(rep.p, to_read, 1, stdin);
if (rc != 1)
return 1;
tp_use(&rep, to_read);
}
ssize_t server_code = tp_reply(&rep);
printf("op: %d\n", tp_replyop(&rep));
printf("count: %d\n", tp_replycount(&rep));
printf("code: %zu\n", server_code);
if (server_code != 0) {
printf("error: %-.*s\n", tp_replyerrorlen(&rep),
tp_replyerror(&rep));
return 1;
}
reply_print(&rep);
/*
tp_rewind(&rep);
reply_print(&rep);
*/
return 0;
}
int
main(int argc, char *argv[])
{ {
char buf[128]; if (argc == 2 && !strcmp(argv[1], "--reply"))
return reply();
char buf[128];
struct tp req; struct tp req;
tp_init(&req, buf, sizeof(buf), NULL, NULL); tp_init(&req, buf, sizeof(buf), NULL, NULL);
/*tp_ping(&req);*/
/* /*
tp_insert(&req, 0, 0); tp_insert(&req, 0, TP_FRET);
tp_tuple(&req); tp_tuple(&req);
tp_sz(&req, "key"); tp_sz(&req, "key");
tp_sz(&req, "value"); tp_sz(&req, "value");
*/ */
/* /*
tp_select(&req, 0, 0, 0, 1); tp_ping(&req);
*/
tp_select(&req, 0, 1, 0, 10);
tp_tuple(&req); tp_tuple(&req);
tp_sz(&req, "key"); tp_sz(&req, "key");
tp_sz(&req, "key");
/*
*/ */
/* /*
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment