00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <assert.h>
00004 #include <string.h>
00005 #include <libmemcached/memcached.h>
00006
00007 #include <syslog.h>
00008 #include <errno.h>
00009 #include <unistd.h>
00010
00011
00012 #include <sys/types.h>
00013 #include <sys/socket.h>
00014
00015
00016 #include <fcntl.h>
00017
00018 #include <netinet/in.h>
00019 #include <arpa/inet.h>
00020
00021
00022 #include <time.h>
00023
00024 #include <pthread.h>
00025
00026 #include <signal.h>
00027
00028 #include <libmemcached/memcached.h>
00029
00030 pthread_t * thread;
00031 int attack;
00032
00033 int single_mode;
00034 int binary_mode;
00035
00036 int admin_port;
00037 char ** server_names;
00038 int server_count;
00039
00040 char** keys;
00041 char** values;
00042
00043 int* keyLength;
00044 int* valueLength;
00045
00046 int count = 0;
00047 int threadCount;
00048 int getsPerSet;
00049
00050 int reqSent;
00051 int valReqSent;
00052
00053 int timeout;
00054
00055 pthread_t * thread;
00056
00061 struct statistics {
00062 unsigned long long wrongAnswerCount;
00063 unsigned long long correctAnswerCount;
00064 unsigned long long hitCount;
00065 unsigned long long missCount;
00066 unsigned long long sentSetsCount;
00067 unsigned long long sentGetsCount;
00068 unsigned long long storedCount;
00069 unsigned long long notStoredCount;
00070 double totalTime;
00071 double totalSetResponseTime;
00072 double totalGetResponseTime;
00073 };
00074
00075 struct timespec start, stop, getSent, getResp, setSent, setResp;
00076
00077 #define TOTAL_STATS_SIZE sizeof(struct statistics)
00078
00079 struct statistics stats;
00080
00081 void init_objects(const char * file_name) {
00082 FILE *fp = NULL;
00083 if ((fp = fopen(file_name, "rb")) == NULL) {
00084 fprintf(stderr, "Unable to open file.\n");
00085 return;
00086 }
00087
00088 fread(&count, sizeof(int), 1, fp);
00089
00090 printf("Read %d input values.\n", count);
00091
00092 keys = (char**) malloc(count * sizeof(char*));
00093 values = (char**) malloc(count * sizeof(char*));
00094
00095 keyLength = (int*) malloc(count * sizeof(int));
00096 valueLength = (int*) malloc(count * sizeof(int));
00097
00098 int i;
00099 for (i = 0; i < count; i++) {
00100 fread(&keyLength[i], sizeof(int), 1, fp);
00101 fread(&valueLength[i], sizeof(int), 1, fp);
00102 keys[i] = (char*) malloc((keyLength[i] + 1) * sizeof(char));
00103 fread(keys[i], keyLength[i], 1, fp);
00104 values[i] = (char*) malloc((valueLength[i] + 1) * sizeof(char));
00105 fread(values[i], valueLength[i], 1, fp);
00106 keys[i][keyLength[i]] = '\0';
00107 values[i][valueLength[i]] = '\0';
00108
00109 }
00110
00111 fclose(fp);
00112 }
00113
00114 void nothing(int n) {
00115 }
00116
00117 void * worker(void * arg) {
00118
00119 static int num = 0;
00120 int i;
00121
00122 struct sigaction action;
00123
00124 action.sa_handler = nothing;
00125 sigemptyset(&action.sa_mask);
00126 action.sa_flags = SA_NOCLDSTOP;
00127
00128 if (sigaction(SIGUSR1, &action, NULL)) {
00129 perror("sigaction");
00130 exit(1);
00131 }
00132
00133 usleep(rand() % 100000);
00134 fprintf(stderr, "start thread %d\n", ++num);
00135
00136
00137
00138 memcached_return rc;
00139
00140 memcached_server_st **servers = malloc(server_count * sizeof(memcached_server_st *));
00141 memcached_st ** memc = malloc(server_count * sizeof(memcached_st *));
00142
00143 for (i = 0; i < 2 * server_count; i += 2) {
00144 memc[i] = memcached_create(NULL);
00145 if (binary_mode){
00146 memcached_behavior_set(memc[i], MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1);
00147 }
00148 servers[i]
00149 = memcached_server_list_append(NULL, server_names[0], atoi(server_names[1]), &rc);
00150 memcached_server_push(memc[i], servers[i]);
00151 }
00152
00153
00154 printf("atacking thread pauses...\n");
00155
00156
00157
00158 while (1) {
00159 if (!attack) {
00160 pause();
00161 printf("atacking thread continues to attack!\n");
00162 clock_gettime(CLOCK_REALTIME, &start);
00163 }
00164
00165 int index = rand() % count;
00166
00167 if (single_mode) {
00168 for (i = 0; i < 2 * server_count; i += 2) {
00169 memcached_quit(memc[i]);
00170 }
00171 }
00172
00173 static struct timespec start, stop;
00174 if (getsPerSet == -1 || (rand() % (getsPerSet + 1))) {
00175 uint32_t flags;
00176 size_t objSize;
00177 for (i = 0; i < server_count; i++) {
00178 clock_gettime(CLOCK_REALTIME, &start);
00179 char * ret = memcached_get(memc[i], keys[index], keyLength[index], &objSize,
00180 &flags, &rc);
00181 clock_gettime(CLOCK_REALTIME, &stop);
00182 stats.totalGetResponseTime += (double) (stop.tv_sec - start.tv_sec)
00183 + (double) (stop.tv_nsec - start.tv_nsec) / 1000000000.0;
00184 if (ret) {
00185 if (!strncmp(values[index], ret, valueLength[index])) {
00186 stats.hitCount++;
00187 stats.correctAnswerCount++;
00188 } else {
00189 stats.wrongAnswerCount++;
00190 }
00191 } else {
00192 stats.missCount++;
00193 stats.correctAnswerCount++;
00194 }
00195 stats.sentGetsCount++;
00196 free((void*) ret);
00197
00198 }
00199 } else {
00200
00201 for (i = 0; i < server_count; i++) {
00202 clock_gettime(CLOCK_REALTIME, &start);
00203 rc = memcached_set(memc[i], keys[index], keyLength[index], values[index],
00204 valueLength[index], (time_t) (rand() % timeout + 1),
00205 (uint32_t) index);
00206 clock_gettime(CLOCK_REALTIME, &stop);
00207 stats.totalSetResponseTime += (double) (stop.tv_sec - start.tv_sec)
00208 + (double) (stop.tv_nsec - start.tv_nsec) / 1000000000.0;
00209
00210 stats.sentSetsCount++;
00211 if (rc == MEMCACHED_SUCCESS) {
00212 stats.storedCount++;
00213 stats.correctAnswerCount++;
00214 } else {
00215 stats.notStoredCount++;
00216 stats.correctAnswerCount++;
00217 }
00218 }
00219
00220 }
00221
00222
00223
00224
00225 }
00226
00227
00228
00229
00230
00231 return NULL;
00232 }
00233
00234 void * admin(void* arg) {
00235 struct sockaddr_in serv_addr, cli_addr;
00236 int fd, cli_fd;
00237
00238 fd = socket(AF_INET, SOCK_STREAM, 0);
00239 memset(&serv_addr, 0, sizeof(serv_addr));
00240 serv_addr.sin_family = AF_INET;
00241 serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
00242 serv_addr.sin_port = htons(admin_port);
00243
00244 int flag = 1;
00245 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)) < 0) {
00246 perror("setsockopt(SO_REUSEADDR)");
00247 }
00248
00249 if (bind(fd, (struct sockaddr*) &serv_addr, sizeof(serv_addr))) {
00250 perror("bind");
00251 exit(1);
00252 }
00253
00254 if (listen(fd, 1)) {
00255 perror("listen");
00256 exit(1);
00257 }
00258
00259 socklen_t cli_len;
00260 cli_len = sizeof(struct sockaddr_in);
00261
00262 printf("Started admin channel.\n");
00263
00264 while (1) {
00265 cli_fd = accept(fd, (struct sockaddr*) &cli_addr, &cli_len);
00266
00267 #define START '1'
00268 #define STOP '9'
00269 #define STATS '5'
00270
00271 char type;
00272 if (recv(cli_fd, (void*) &type, 1, 0) == 1) {
00273
00274 switch (type) {
00275 case START:
00276 printf("waking threads...\n");
00277 attack = 1;
00278 int i;
00279 for (i = 0; i < threadCount; i++) {
00280 pthread_kill(thread[i], SIGUSR1);
00281 }
00282 break;
00283 case STOP:
00284 printf("stopping...\n");
00285 attack = 0;
00286 clock_gettime(CLOCK_REALTIME, &stop);
00287 stats.totalTime += (double) (stop.tv_sec - start.tv_sec)
00288 + (double) (stop.tv_nsec - start.tv_nsec) / 1000000000.0;
00289 break;
00290 case STATS:
00291 printf("Stats requested.\n");
00292
00293 char sendBuf[TOTAL_STATS_SIZE];
00294
00295 memcpy((void*) (sendBuf), (void*) &stats, TOTAL_STATS_SIZE);
00296
00297 if (send(cli_fd, (void*) sendBuf, TOTAL_STATS_SIZE, 0) == TOTAL_STATS_SIZE) {
00298 printf("Stats sent.\n");
00299 }
00300
00301 break;
00302 }
00303 }
00304
00305 close(cli_fd);
00306 }
00307
00308 close(fd);
00309 }
00310
00311 int main(int argc, char** argv) {
00312
00313 attack = 0;
00314
00315 srand(time(NULL));
00316
00317 if (argc < 10) {
00318 printf("Usage: ./client admin_port fileName threadCount "
00319 "getsPerSet timeout single_mode binary_mode host port [host port ...]\n");
00320 return 1;
00321 }
00322
00323 single_mode = atoi(argv[6]);
00324 binary_mode = atoi(argv[7]);
00325
00326 admin_port = atoi(argv[1]);
00327
00328 server_names = argv + 8;
00329 server_count = (argc - 8) / 2;
00330
00331 pthread_t adminThread;
00332
00333 pthread_create(&adminThread, NULL, admin, NULL);
00334
00335 memset((void*) &stats, 0, TOTAL_STATS_SIZE);
00336
00337 reqSent = 0;
00338 valReqSent = 0;
00339
00340 threadCount = atoi(argv[3]);
00341 getsPerSet = atoi(argv[4]);
00342 timeout = atoi(argv[5]);
00343
00344 init_objects(argv[2]);
00345
00346 int i;
00347
00348 thread = malloc(threadCount * sizeof(pthread_t));
00349
00350 for (i = 0; i < threadCount; i++)
00351 pthread_create(&thread[i], NULL, worker, NULL);
00352
00353 char c;
00354 scanf("%c", &c);
00355
00356 return 0;
00357 }