implement get tunable and add get regression
[libdht.git] / regress / scale.c
blob6146428da6e44df7bf15cd61de48ef6a52b008fe
1 /*
2 * Copyright (c) 2016 Mohamed Aslan <maslan@sce.carleton.ca>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <dht.h>
21 #include <hashtab.h>
22 #include <pthread.h>
23 #include <err.h>
24 #include <errno.h>
25 #include <time.h>
26 #include <unistd.h>
27 #include <sys/wait.h>
30 #define PORT_BASE 5000
31 #define N_NODES 50
32 #define N_REPLICAS N_NODES
34 #define MAX_KEYS 1
35 struct v_node {
36 char *id;
37 char *ip;
38 int port;
39 int n_keys;
40 char *keys[MAX_KEYS];
41 char *vals[MAX_KEYS];
42 } *vnodes;
44 struct args {
45 int nidx;
46 struct dht_node *node;
49 #define TOTAL_KV (N_NODES * MAX_KEYS)
50 char *all_keys[TOTAL_KV];
51 char *all_vals[TOTAL_KV];
53 void *
54 test_thread(void *arg)
56 int i, fail = 0;
57 int me = ((struct args *)arg)->nidx;
58 struct dht_node *n = ((struct args *)arg)->node;
59 struct hashtab *ht = (struct hashtab *)n->ht;
60 struct timespec ts;
61 char *key, *val;
62 size_t val_size;
64 while (!n->ready);
66 sleep(5);
67 (void)clock_gettime(CLOCK_REALTIME, &ts);
68 for (i = 0 ; i < vnodes[me].n_keys ; i++) {
69 if (!dht_put_tunable(n, vnodes[me].keys[i], vnodes[me].vals[i], &ts, N_REPLICAS))
70 printf("FAILED [%s] dht_put_tunable.\n", n->id);
73 sleep(20);
74 for (i = 0 ; i < TOTAL_KV ; i++) {
75 if (hashtab_get(ht, all_keys[i], strlen(all_keys[i]) + 1, (void **)&val, &val_size) && !strcmp(val, all_vals[i])) {
76 /*printf("OK\n");*/
77 } else {
78 fail++;
79 printf("FAILED [%s] %s -> %s, got: %s -> %s\n", n->id, all_keys[i], all_vals[i], key, val);
82 printf("SUCCESS [%s] %d/%d\n", n->id, TOTAL_KV - fail, TOTAL_KV);
84 _exit(fail);
85 /* NOTREACHED */
86 return NULL;
89 int
90 node(int me)
92 int i;
93 struct dht_node *n;
94 struct args *a;
95 pthread_t tp, tt;
97 n = malloc(sizeof(struct dht_node));
98 if (!dht_init(n, vnodes[me].id, vnodes[me].port, N_REPLICAS, 0, NULL))
99 err(1, "dht_init");
101 for (i = 0 ; i < N_NODES ; i++)
102 if (i != me)
103 dht_add_peer(n, vnodes[i].id, vnodes[i].ip, vnodes[i].port);
105 a = malloc(sizeof(struct args));
106 a->node = n;
107 a->nidx = me;
108 if (pthread_create(&tt, NULL, test_thread, a))
109 err(1, "pthread_create");
111 dht_event_loop(n);
112 errx(1, "should not reach here!");
113 return 0;
117 main(int argc, char **argv)
119 int i, status, fail = 0;
120 uint32_t k, v;
121 pid_t pid;
123 /* generate nodes */
124 vnodes = calloc(N_NODES, sizeof(struct v_node));
125 for (i = 0 ; i < N_NODES ; i++) {
126 asprintf(&(vnodes[i].id), "N%d", i);
127 if (vnodes[i].id == NULL)
128 err(1, "asprintf");
129 vnodes[i].ip = strdup("127.0.0.1");
130 if (vnodes[i].ip == NULL)
131 err(1, "strdup");
132 vnodes[i].port = PORT_BASE + i; /* FIXME: check */
133 k = arc4random();
134 v = arc4random();
135 /* TODO: add support to more than 1 KV per node */
136 vnodes[i].n_keys = 1;
137 asprintf(&(vnodes[i].keys[0]), "%ud", k);
138 asprintf(&(vnodes[i].vals[0]), "%ud", v);
139 if (vnodes[i].keys[0] == NULL || vnodes[i].vals[0] == NULL)
140 err(1, "asprintf");
141 all_keys[i] = strdup(vnodes[i].keys[0]);
142 all_vals[i] = strdup(vnodes[i].vals[0]);
145 for (i = 0 ; i < N_NODES ; i++) {
146 if (!fork()) {
147 node(i);
148 return 0;
151 while (1) {
152 pid = wait(&status);
153 if (pid == -1) {
154 if (errno == ECHILD)
155 break;
156 else
157 err(1, "wait");
158 } else {
159 if (WIFEXITED(status) && WEXITSTATUS(status))
160 fail++;
163 sleep(5);
164 return fail;