diff options
Diffstat (limited to 'xlators/cluster/nsr-server/src/etcd-sim.c')
-rw-r--r-- | xlators/cluster/nsr-server/src/etcd-sim.c | 280 |
1 files changed, 280 insertions, 0 deletions
diff --git a/xlators/cluster/nsr-server/src/etcd-sim.c b/xlators/cluster/nsr-server/src/etcd-sim.c new file mode 100644 index 000000000..d0bea12c7 --- /dev/null +++ b/xlators/cluster/nsr-server/src/etcd-sim.c @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2014, Red Hat + * All rights reserved. + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. Redistributions in binary + * form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials + * provided with the distribution. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <sys/file.h> + +#include "mem-pool.h" + +/* + * Mock implementation of etcd + * The etcd file is simulated in /tmp/<server-names> + * Writes from Multiple writers are protected using file lock. +*/ + +#include "etcd-api.h" +#define MAX_KEY_LEN 64 +#define MAX_VALUE_LEN 64 +#define MAX_EXPIRE_LEN 16 + +etcd_session +etcd_open (etcd_server *server_list) +{ + return NULL; +} + +typedef struct _etcd_sim_s { + char *path; +} etcd_sim_t; + +void +etcd_close (etcd_session this) +{ + etcd_sim_t *sim = (etcd_sim_t *)this; + free(sim->path); + free(this); +} + + +char * +etcd_get_1 (FILE *stream, char *key) +{ + char *str = NULL; + size_t len; + unsigned long expires; + char *ret; + + // Read the file + while(1) { + if(str) { + free(str); + str = NULL; + } + if (getline((char **)&str, &len,stream) == -1) { + break; + } + if (!strncmp(str, key, strlen(key))) { + char k[256], s[256]; + sscanf(str,"%s %s %lu",k, s, &expires); + // check if key is expired. + if (time(NULL) > expires) { + /* Keep looking for an unexpired entry. */ + continue; + } + ret = calloc(1, strlen(s) + 1); + strcpy(ret,s); + free(str); + return(ret); + } + } + return NULL; +} + + +char * +etcd_get (etcd_session this, char *key) +{ + etcd_sim_t *sim = (etcd_sim_t *)this; + int fd; + FILE *stream; + char *retval; + + fd = open(sim->path,O_RDONLY); + if (!fd) { + return NULL; + } + + stream = fdopen(fd,"r"); + (void)flock(fd,LOCK_SH); + retval = etcd_get_1(stream,key); + (void)flock(fd,LOCK_UN); + fclose(stream); /* closes fd as well */ + + return retval; +} + + +etcd_result +etcd_set_1 (FILE *stream, char *key, char *value, + char *precond, unsigned int ttl) +{ + char *str = NULL; + char tp[255]; + size_t len; + unsigned long expires; + + while(1) { + if(str) { + free(str); + str = NULL; + } + if (getline((char **)&str, &len,stream) == -1) { + break; + } + if (!strncmp(str, key, strlen(key))) { + char k[256], s[256]; + sscanf(str,"%s %s %lu",k, s, &expires); + // check if the present key is expired + if (time(NULL) > expires) { + /* Keep looking for an unexpired entry. */ + continue; + } + /* + * The only case in which we should fail here is if a + * precondition was specified and does not match the + * current (non-expired) value. + */ + if (precond && strcmp(precond, s)) { + free(str); + return ETCD_WTF; + } + fseek(stream, -strlen(str), SEEK_CUR); + free(str); + goto here; + } + } +here: + memset(tp, 0, 255); + sprintf(tp,"%*s %*s %*lu\n", + -MAX_KEY_LEN, key, -MAX_VALUE_LEN, value, + -MAX_EXPIRE_LEN, ttl ? time(NULL) + ttl : ~0); + if (fwrite(tp, 1,strlen(tp), stream) != strlen(tp)) { + return ETCD_WTF; + } + fflush(stream); + fsync(fileno(stream)); + return ETCD_OK; +} + + +etcd_result +etcd_set (etcd_session this, char *key, char *value, + char *precond, unsigned int ttl) +{ + etcd_sim_t *sim = (etcd_sim_t *)this; + int fd; + FILE *stream; + etcd_result retval; + + fd = open(sim->path,O_RDWR); + if (fd < 0) { + return ETCD_WTF; + } + + stream = fdopen(fd,"r+"); + (void)flock(fd,LOCK_EX); + retval = etcd_set_1(stream,key,value,precond,ttl); + (void)flock(fd,LOCK_UN); + fclose(stream); /* closes fd as well */ + + return retval; +} + + +etcd_session +etcd_open_str (char *server_names) +{ + etcd_sim_t *sim; + int fd; + + sim = calloc(1, sizeof(etcd_sim_t)); + (void)asprintf(&sim->path,"/tmp/%s",server_names); + + fd = open(sim->path, O_RDWR | O_CREAT, 0777); + if (fd == -1) { + free(sim->path); + free(sim); + return NULL; + } + + close(fd); + return ((void *)sim); +} + + +void +etcd_close_str (etcd_session this) +{ + etcd_close(this); +} + +etcd_result +etcd_delete (etcd_session this, char *key) +{ + return ETCD_WTF; +} + +char * +etcd_leader (etcd_session this_as_void) +{ + return NULL; +} + +etcd_result +etcd_watch (etcd_session this, char *pfx, char **keyp, char **valuep, + int *index_in, int *index_out) +{ + return ETCD_WTF; +} + +etcd_result +etcd_lock (etcd_session session_as_void, char *key, unsigned int ttl, + char *index_in, char **index_out) +{ + char *path; + int fd; + + if (!index_in) { + if (gf_asprintf(&path,"/var/tmp/%s",key) < 0) { + return ETCD_WTF; + } + fd = open(path,O_RDWR|O_CREAT,0666); + GF_FREE(path); + if (fd < 0) { + return ETCD_WTF; + } + if (flock(fd,LOCK_EX) < 0) { + close(fd); + return ETCD_WTF; + } + *index_out = strdup("42"); + } + + /* + * Yes, we leak an fd by not closing it here (and nobody else even + * knows about it). That would be awful in any other context, but + * for test scripts it won't matter. + */ + return ETCD_OK; +} + |