src/client_resource.c | 289 ++++++++++++++++++++++++++++++++++++++
src/diskio.c | 17 --
src/main.c | 366 ++++++++++---------------------------------------
src/sanlock.h | 24 ++-
src/sanlock_internal.h | 12 -
src/sanlock_resource.h | 50 +++++-
tests/res_string.c | 80 ++++++++++
7 files changed, 499 insertions(+), 339 deletions(-)
New commits:
commit 8a887a9878871209d8cde83f249ca3bbb9ccbd1f
Author: David Teigland <teigland(a)redhat.com>
Date: Wed Mar 30 10:20:59 2011 -0500
sanlock: add resource string conversion functions
Make sanlock_inquire always return a state string,
and add api functions to convert between string and
struct resource formats. Start using these conversion
functions elsewhere to avoid string parsing and formating
in multiple places.
diff --git a/src/client_resource.c b/src/client_resource.c
index 57b9588..8bab02b 100644
--- a/src/client_resource.c
+++ b/src/client_resource.c
@@ -145,7 +145,8 @@ int sanlock_acquire(int sock, int pid, uint32_t flags, int res_count,
return rv;
}
-int sanlock_inquire(int sock, int pid, uint32_t flags, int *res_count, void **res_out)
+int sanlock_inquire(int sock, int pid, uint32_t flags, int *res_count,
+ char **res_state)
{
struct sm_header h;
char *reply_data = NULL;
@@ -153,8 +154,8 @@ int sanlock_inquire(int sock, int pid, uint32_t flags, int *res_count,
void **re
*res_count = 0;
- if (res_out)
- *res_out = NULL;
+ if (res_state)
+ *res_state = NULL;
if (sock == -1) {
/* connect to daemon and ask it to acquire a lease for
@@ -206,8 +207,8 @@ int sanlock_inquire(int sock, int pid, uint32_t flags, int *res_count,
void **re
goto out;
}
- if (res_out)
- *res_out = reply_data;
+ if (res_state)
+ *res_state = reply_data;
else
free(reply_data);
@@ -276,3 +277,281 @@ int sanlock_release(int sock, int pid, uint32_t flags, int
res_count,
return rv;
}
+/*
+ * convert from struct sanlk_resource to string with format:
+ *
<lockspace_name>:<resource_name>:<path>:<offset>[:<path>:<offset>...]:<lver>
+ */
+
+int sanlock_res_to_str(struct sanlk_resource *res, char **str_ret)
+{
+ char *str;
+ int ret, len, pos, d;
+
+ str = malloc(SANLK_MAX_RES_STR + 1);
+ if (!str)
+ return -ENOMEM;
+ memset(str, 0, SANLK_MAX_RES_STR + 1);
+
+ len = SANLK_MAX_RES_STR;
+ pos = 0;
+
+ ret = snprintf(str + pos, len - pos, "%s:%s",
+ res->lockspace_name, res->name);
+
+ if (ret >= len - pos)
+ goto fail;
+ pos += ret;
+
+ for (d = 0; d < res->num_disks; d++) {
+ ret = snprintf(str + pos, len - pos, ":%s:%llu",
+ res->disks[d].path,
+ (unsigned long long)res->disks[d].offset);
+
+ if (ret >= len - pos)
+ goto fail;
+ pos += ret;
+ }
+
+ ret = snprintf(str + pos, len - pos, ":%llu",
+ (unsigned long long)res->lver);
+
+ if (ret > len - pos)
+ goto fail;
+ pos += ret;
+
+ if (pos > len)
+ goto fail;
+
+ *str_ret = str;
+ return 0;
+
+ fail:
+ free(str);
+ return -EINVAL;
+}
+
+/*
+ * convert to struct sanlk_resource from string with format:
+ *
<lockspace_name>:<resource_name>:<path>:<offset>[:<path>:<offset>...][:<lver>]
+ */
+
+int sanlock_str_to_res(char *str, struct sanlk_resource **res_ret)
+{
+ struct sanlk_resource *res;
+ char sub[SANLK_PATH_LEN + 1];
+ int i, j, d, rv, len, sub_count, colons, num_disks, have_lver;
+
+ if (strlen(str) < 3)
+ return -ENXIO;
+
+ colons = 0;
+ for (i = 0; i < strlen(str); i++) {
+ if (str[i] == '\\') {
+ i++;
+ continue;
+ }
+
+ if (str[i] == ':')
+ colons++;
+ }
+ if (!colons || (colons == 2)) {
+ return -1;
+ }
+
+ num_disks = (colons - 1) / 2;
+ have_lver = (colons - 1) % 2;
+
+ if (num_disks > MAX_DISKS)
+ return -2;
+
+ len = sizeof(struct sanlk_resource) + num_disks * sizeof(struct sanlk_disk);
+
+ res = malloc(len);
+ if (!res)
+ return -ENOMEM;
+ memset(res, 0, len);
+
+ res->num_disks = num_disks;
+
+ d = 0;
+ sub_count = 0;
+ j = 0;
+ memset(sub, 0, sizeof(sub));
+
+ len = strlen(str);
+
+ for (i = 0; i < len + 1; i++) {
+ if (str[i] == '\\') {
+ if (i == (len - 1))
+ goto fail;
+
+ i++;
+ sub[j++] = str[i];
+ continue;
+ }
+ if (i < len && str[i] != ':') {
+ if (j >= SANLK_PATH_LEN)
+ goto fail;
+ sub[j++] = str[i];
+ continue;
+ }
+
+ /* do something with sub when we hit ':' or end of str,
+ first and second subs are lockspace and resource names,
+ then even sub is path, odd sub is offset */
+
+ if (sub_count < 2 && strlen(sub) > NAME_ID_SIZE)
+ goto fail;
+ if (sub_count >= 2 && (strlen(sub) > SANLK_PATH_LEN-1 || strlen(sub) <
1))
+ goto fail;
+
+ if (sub_count == 0) {
+ strncpy(res->lockspace_name, sub, NAME_ID_SIZE);
+
+ } else if (sub_count == 1) {
+ strncpy(res->name, sub, NAME_ID_SIZE);
+
+ } else if (!(sub_count % 2)) {
+ if (have_lver && (d == num_disks)) {
+ res->flags |= SANLK_RES_LVER;
+ res->lver = strtoull(sub, NULL, 0);
+ } else {
+ strncpy(res->disks[d].path, sub, SANLK_PATH_LEN - 1);
+ }
+ } else {
+ rv = sscanf(sub, "%llu", (unsigned long long
*)&res->disks[d].offset);
+ if (rv != 1)
+ goto fail;
+ d++;
+ }
+
+ sub_count++;
+ j = 0;
+ memset(sub, 0, sizeof(sub));
+ }
+
+ *res_ret = res;
+ return 0;
+
+ fail:
+ free(res);
+ return -1;
+}
+
+/*
+ * convert from array of struct sanlk_resource * to state string with format:
+ * "RESOURCE1 RESOURCE2 RESOURCE3 ..."
+ * RESOURCE format in sanlock_res_to_str() comment
+ */
+
+int sanlock_args_to_state(int res_count,
+ struct sanlk_resource *res_args[],
+ char **res_state)
+{
+ char *str, *state;
+ int i, rv;
+
+ state = malloc(res_count * (SANLK_MAX_RES_STR + 1));
+ if (!state)
+ return -ENOMEM;
+ memset(state, 0, res_count * (SANLK_MAX_RES_STR + 1));
+
+ for (i = 0; i < res_count; i++) {
+ str = NULL;
+
+ rv = sanlock_res_to_str(res_args[i], &str);
+ if (rv < 0 || !str) {
+ free(state);
+ return rv;
+ }
+
+ if (strlen(str) > SANLK_MAX_RES_STR) {
+ free(str);
+ free(state);
+ return -EINVAL;
+ }
+
+ /* space is str separator, so it's invalid within each str */
+
+ if (strstr(str, " ")) {
+ free(str);
+ free(state);
+ return -EINVAL;
+ }
+
+ if (i)
+ strcat(state, " ");
+ strcat(state, str);
+ free(str);
+ }
+
+ *res_state = state;
+ return 0;
+}
+
+/*
+ * convert to array of struct sanlk_resource * from state string with format:
+ * "RESOURCE1 RESOURCE2 RESOURCE3 ..."
+ * RESOURCE format in sanlock_str_to_res() comment
+ */
+
+int sanlock_state_to_args(char *res_state,
+ int *res_count,
+ struct sanlk_resource ***res_args)
+{
+ struct sanlk_resource **args;
+ struct sanlk_resource *res;
+ char str[SANLK_MAX_RES_STR + 1];
+ int count = 1, arg_count = 0;
+ int i, j, len, rv;
+
+ for (i = 0; i < strlen(res_state); i++) {
+ if (res_state[i] == ' ')
+ count++;
+ }
+
+ *res_count = count;
+
+ args = malloc(count * sizeof(*args));
+ if (!args)
+ return -ENOMEM;
+ memset(args, 0, count * sizeof(*args));
+
+ j = 0;
+ memset(str, 0, sizeof(str));
+
+ len = strlen(res_state);
+
+ for (i = 0; i < len + 1; i++) {
+ if (i < len && res_state[i] != ' ') {
+ str[j++] = res_state[i];
+ continue;
+ }
+
+ rv = sanlock_str_to_res(str, &res);
+ if (rv < 0 || !res)
+ goto fail_free;
+
+ if (arg_count == count)
+ goto fail_free;
+
+ args[arg_count++] = res;
+
+ j = 0;
+ memset(str, 0, sizeof(str));
+ }
+
+ *res_count = arg_count;
+ *res_args = args;
+ return 0;
+
+ fail_free:
+ for (i = 0; i < count; i++) {
+ if (args[i])
+ free(args[i]);
+ }
+ free(args);
+ fail:
+ return rv;
+}
+
diff --git a/src/diskio.c b/src/diskio.c
index 16b615a..3c01650 100644
--- a/src/diskio.c
+++ b/src/diskio.c
@@ -107,23 +107,6 @@ int open_disks(struct sync_disk *disks, int num_disks)
orig_offset = disk->offset;
- switch (disk->units) {
- case SANLK_UNITS_BYTES:
- break;
- case SANLK_UNITS_SECTORS:
- disk->offset = orig_offset * ss;
- break;
- case SANLK_UNITS_KB:
- disk->offset = orig_offset * 1024;
- break;
- case SANLK_UNITS_MB:
- disk->offset = orig_offset * 1024 * 1024;
- break;
- default:
- log_error("invalid offset units %d", disk->units);
- goto fail;
- }
-
if (disk->offset % disk->sector_size) {
log_error("invalid offset %llu sector size %u %s",
(unsigned long long)disk->offset,
diff --git a/src/main.c b/src/main.c
index ee4566e..9d38fc1 100644
--- a/src/main.c
+++ b/src/main.c
@@ -477,59 +477,6 @@ static void client_recv_all(int ci, struct sm_header *h_recv, int
pos)
log_debug("recv_all ci %d rem %d total %d", ci, rem, total);
}
-/* str format: "abc=123 def=456 ghi=780" */
-
-static int parse_key_val(char *str, const char *key_arg, char *val_arg, int len)
-{
- int copy_key, copy_val, i, kvi;
- char key[64], val[64];
-
- memset(val_arg, 0, len);
-
- copy_key = 1;
- copy_val = 0;
- kvi = 0;
-
- for (i = 0; i < strlen(str); i++) {
- if (str[i] == ' ') {
- if (!strcmp(key, key_arg)) {
- strncpy(val_arg, val, len);
- return 0;
- }
- memset(key, 0, sizeof(key));
- memset(val, 0, sizeof(val));
- copy_key = 1;
- copy_val = 0;
- kvi = 0;
- continue;
- }
-
- if (str[i] == '=') {
- copy_key = 0;
- copy_val = 1;
- kvi = 0;
- continue;
- }
-
- if (copy_key)
- key[kvi++] = str[i];
- else if (copy_val)
- val[kvi++] = str[i];
-
- if (kvi > 62) {
- log_error("invalid timeout parameter");
- return -1;
- }
- }
-
- if (!strcmp(key, key_arg)) {
- strncpy(val_arg, val, len);
- return 0;
- }
-
- return -1;
-}
-
static void *cmd_acquire_thread(void *args_in)
{
struct cmd_args *ca = args_in;
@@ -540,11 +487,10 @@ static void *cmd_acquire_thread(void *args_in)
struct token *new_tokens[SANLK_MAX_RESOURCES];
struct sanlk_resource res;
struct sanlk_options opt;
+ struct space space;
char *opt_str;
- char num_hosts_str[16];
uint64_t acquire_lver = 0;
- struct space space;
- int new_num_hosts = 0;
+ uint32_t new_num_hosts = 0;
int fd, rv, i, j, disks_len, num_disks, empty_slots, opened;
int alloc_count = 0, add_count = 0, open_count = 0, acquire_count = 0;
int pos = 0, pid_dead = 0;
@@ -721,21 +667,6 @@ static void *cmd_acquire_thread(void *args_in)
* all command input has been received, start doing the acquire
*/
- if (opt.flags & SANLK_OPT_NUM_HOSTS) {
- if (!opt_str)
- goto fail_free;
-
- memset(num_hosts_str, 0, sizeof(num_hosts_str));
-
- rv = parse_key_val(opt_str, "num_hosts", num_hosts_str, 15);
- if (rv < 0) {
- log_error("cmd_acquire num_hosts error");
- goto fail_free;
- }
-
- new_num_hosts = atoi(num_hosts_str);
- }
-
for (i = 0; i < new_tokens_count; i++) {
token = new_tokens[i];
rv = get_space_info(token->space_name, &space);
@@ -774,6 +705,8 @@ static void *cmd_acquire_thread(void *args_in)
if (token->acquire_flags & SANLK_RES_LVER)
acquire_lver = token->acquire_lver;
+ if (token->acquire_flags & SANLK_RES_NUM_HOSTS)
+ new_num_hosts = token->acquire_data32;
rv = acquire_token(token, acquire_lver, new_num_hosts);
if (rv < 0) {
@@ -1006,13 +939,9 @@ static void *cmd_inquire_thread(void *args_in)
total++;
}
- /*
- * struct output [sanlk_resource][sanlk_disk...][sanlk_resource][sanlk_disk...]...
- * string output "RESOURCE1 RESOURCE2 RESOURCE3 ..."
- * RESOURCE =
<lockspace_name>:<resource_name>:<path>:<offset>[:<path>:<offset>...]:<lver>
- */
+ /* TODO: use sanlock_res_to_str() */
- reply_len = total * SANLK_STATE_MAXSTR; /* rough estimate */
+ reply_len = total * SANLK_MAX_RES_STR;
reply_str = malloc(reply_len);
if (!reply_str) {
result = -ENOMEM;
@@ -1028,52 +957,36 @@ static void *cmd_inquire_thread(void *args_in)
if (!token)
continue;
- if (ca->header.cmd_flags & SANLK_INQ_STRUCT) {
- strcpy(res->lockspace_name, token->space_name);
- strcpy(res->name, token->resource_name);
- res->lver = token->leader.lver;
- res->flags |= SANLK_RES_LVER;
- res->num_disks = token->num_disks;
- pos += sizeof(struct sanlk_resource);
-
- for (d = 0; d < token->num_disks; d++) {
- strcpy(res->disks[d].path, token->disks[d].path);
- res->disks[d].offset = token->disks[d].offset;
- pos += sizeof(struct sanlk_disk);
- }
- res++;
- } else {
- ret = snprintf(reply_str + pos, reply_len - pos, "%s:%s",
- token->space_name, token->resource_name);
+ ret = snprintf(reply_str + pos, reply_len - pos, "%s:%s",
+ token->space_name, token->resource_name);
- if (ret >= reply_len - pos)
- goto out;
- pos += ret;
-
- for (d = 0; d < token->num_disks; d++) {
- ret = snprintf(reply_str + pos, reply_len - pos, ":%s:%llu",
- token->disks[d].path,
- (unsigned long long)token->disks[d].offset);
-
- if (ret >= reply_len - pos)
- goto out;
- pos += ret;
- }
+ if (ret >= reply_len - pos)
+ goto out;
+ pos += ret;
- ret = snprintf(reply_str + pos, reply_len - pos, ":%llu ",
- (unsigned long long)token->leader.lver);
+ for (d = 0; d < token->num_disks; d++) {
+ ret = snprintf(reply_str + pos, reply_len - pos, ":%s:%llu",
+ token->disks[d].path,
+ (unsigned long long)token->disks[d].offset);
if (ret >= reply_len - pos)
goto out;
pos += ret;
}
- }
- if (ca->header.cmd_flags & SANLK_INQ_STRING) {
- reply_str_len = strlen(reply_str);
- reply_str[pos++] = '\0';
+ ret = snprintf(reply_str + pos, reply_len - pos, ":%llu ",
+ (unsigned long long)token->leader.lver);
+
+ if (ret >= reply_len - pos)
+ goto out;
+ pos += ret;
}
+ /* remove trailing space */
+ pos--;
+ reply_str[pos++] = '\0';
+ reply_str_len = strlen(reply_str);
+
ret = 0;
out:
if (ret)
@@ -1778,25 +1691,6 @@ static int do_daemon(void)
return rv;
}
-static int create_sanlk_resource(int num_disks, struct sanlk_resource **res_out)
-{
- struct sanlk_resource *res;
- int len;
-
- len = sizeof(struct sanlk_resource) +
- num_disks * sizeof(struct sanlk_disk);
-
- res = malloc(sizeof(struct sanlk_resource) +
- (num_disks * sizeof(struct sanlk_disk)));
- if (!res)
- return -ENOMEM;
- memset(res, 0, len);
-
- res->num_disks = num_disks;
- *res_out = res;
- return 0;
-}
-
/* arg = <lockspace_name>:<host_id>:<path>:<offset> */
static int parse_arg_lockspace(char *arg)
@@ -1834,7 +1728,7 @@ static int parse_arg_lockspace(char *arg)
if (offset)
com.lockspace.host_id_disk.offset = atoll(offset);
- log_debug("lockspace arg %s %llu %s %llu",
+ log_debug("lockspace %s host_id %llu path %s offset %llu",
com.lockspace.name,
(unsigned long long)com.lockspace.host_id,
com.lockspace.host_id_disk.path,
@@ -1843,150 +1737,33 @@ static int parse_arg_lockspace(char *arg)
return 0;
}
-/* arg =
<lockspace_name>:<resource_name>:<path>:<offset>[:<path>:<offset>...][:<lver>]
*/
-
static int parse_arg_resource(char *arg)
{
struct sanlk_resource *res;
- char sub[SANLK_PATH_LEN + 1];
- char unit[SANLK_PATH_LEN + 1];
- int sub_count;
- int colons;
- int num_disks;
- int have_lver;
- int rv, i, j, d;
- int len = strlen(arg);
+ int rv, i;
if (com.res_count >= SANLK_MAX_RESOURCES) {
log_tool("resource args over max %d", SANLK_MAX_RESOURCES);
return -1;
}
- colons = 0;
- for (i = 0; i < strlen(arg); i++) {
- if (arg[i] == '\\') {
- i++;
- continue;
- }
-
- if (arg[i] == ':')
- colons++;
- }
- if (!colons || (colons == 2)) {
- log_tool("invalid resource arg");
- return -1;
- }
-
- num_disks = (colons - 1) / 2;
- have_lver = (colons - 1) % 2;
-
- if (num_disks > MAX_DISKS) {
- log_tool("invalid resource arg num_disks %d", num_disks);
- return -1;
- }
-
- rv = create_sanlk_resource(num_disks, &res);
+ rv = sanlock_str_to_res(arg, &res);
if (rv < 0) {
- log_tool("resource arg create error %d num_disks %d", rv, num_disks);
+ log_tool("resource arg parse error %d\n", rv);
return rv;
}
com.res_args[com.res_count] = res;
com.res_count++;
- d = 0;
- sub_count = 0;
- j = 0;
- memset(sub, 0, sizeof(sub));
-
- for (i = 0; i < len + 1; i++) {
- if (arg[i] == '\\') {
- if (i == (len - 1)) {
- log_tool("invalid resource arg string");
- goto fail;
- }
-
- i++;
- sub[j++] = arg[i];
- continue;
- }
- if (i < len && arg[i] != ':') {
- if (j >= SANLK_PATH_LEN) {
- log_tool("resource arg length error");
- goto fail;
- }
- sub[j++] = arg[i];
- continue;
- }
-
- /* do something with sub when we hit ':' or end of arg,
- first and second subs are lockspace and resource names,
- then even sub is path, odd sub is offset */
-
- if (sub_count < 2 && strlen(sub) > NAME_ID_SIZE) {
- log_tool("option arg component %s too long", sub);
- goto fail;
- }
- if (sub_count >= 2 && (strlen(sub) > SANLK_PATH_LEN-1 || strlen(sub) <
1)) {
- log_tool("option arg component %s too long", sub);
- goto fail;
- }
-
- if (sub_count == 0) {
- strncpy(res->lockspace_name, sub, NAME_ID_SIZE);
-
- } else if (sub_count == 1) {
- strncpy(res->name, sub, NAME_ID_SIZE);
-
- } else if (!(sub_count % 2)) {
- if (have_lver && (d == num_disks)) {
- res->flags |= SANLK_RES_LVER;
- res->lver = strtoull(sub, NULL, 0);
- } else {
- strncpy(res->disks[d].path, sub, SANLK_PATH_LEN - 1);
- }
- } else {
- memset(&unit, 0, sizeof(unit));
- rv = sscanf(sub, "%llu%s", (unsigned long long
*)&res->disks[d].offset, unit);
- if (!rv || rv > 2) {
- log_tool("lease arg offset error");
- goto fail;
- }
- if (rv > 1) {
- if (unit[0] == 's')
- res->disks[d].units = SANLK_UNITS_SECTORS;
- else if (unit[0] == 'K' && unit[1] == 'B')
- res->disks[d].units = SANLK_UNITS_KB;
- else if (unit[0] == 'M' && unit[1] == 'B')
- res->disks[d].units = SANLK_UNITS_MB;
- else {
- log_tool("unit unknkown: %s", unit);
- goto fail;
- }
- }
- d++;
- }
-
- sub_count++;
- j = 0;
- memset(sub, 0, sizeof(sub));
- }
-
- log_debug("resource arg %s %s num_disks %d flags %x",
- res->lockspace_name, res->name, res->num_disks, res->flags);
- if (res->flags & SANLK_RES_LVER)
- log_debug("resource lver %llu", (unsigned long long)res->lver);
+ log_debug("resource %s %s num_disks %d flags %x lver %llu",
+ res->lockspace_name, res->name, res->num_disks, res->flags,
+ (unsigned long long)res->lver);
for (i = 0; i < res->num_disks; i++) {
- log_debug("resource arg disk %s %llu %u",
- res->disks[i].path,
- (unsigned long long)res->disks[i].offset,
- res->disks[i].units);
+ log_debug("resource disk %s %llu", res->disks[i].path,
+ (unsigned long long)res->disks[i].offset);
}
return 0;
-
- fail:
- free(res);
- return -1;
}
static void set_timeout(char *key, char *val)
@@ -2186,8 +1963,7 @@ static void print_usage(void)
printf(" <lockspace_name> name of lockspace\n");
printf(" <resource_name> name of resource being leased\n");
printf(" <path> disk path where resource leases are written\n");
- printf(" <offset>[s|KB|MB] offset on disk, default unit bytes\n");
- printf(" [s = sectors, KB = 1024 bytes, MB = 1024
KB]\n");
+ printf(" <offset> offset on disk in bytes\n");
printf(" <lver> optional disk leader version of resource for
acquire\n");
printf("\n");
}
@@ -2416,10 +2192,21 @@ static int read_command_line(int argc, char *argv[])
static int do_client(void)
{
- struct sanlk_options *opt = NULL;
- char *res_str = NULL;
+ struct sanlk_resource **res_args = NULL;
+ struct sanlk_resource *res;
+ char *res_state = NULL;
int i, fd, rv = 0;
+ if (com.action == ACT_COMMAND || com.action == ACT_ACQUIRE) {
+ if (com.num_hosts) {
+ for (i = 0; i < com.res_count; i++) {
+ res = com.res_args[i];
+ res->flags |= SANLK_RES_NUM_HOSTS;
+ res->data32 = com.num_hosts;
+ }
+ }
+ }
+
switch (com.action) {
case ACT_STATUS:
rv = sanlock_status(options.debug);
@@ -2443,22 +2230,12 @@ static int do_client(void)
if (fd < 0)
goto out;
- if (com.num_hosts) {
- opt = malloc(sizeof(struct sanlk_options) + 16);
- memset(opt, 0, sizeof(struct sanlk_options) + 16);
- snprintf(opt->str, 15, "num_hosts=%d", com.num_hosts);
- opt->flags = SANLK_OPT_NUM_HOSTS;
- opt->len = strlen(opt->str);
- }
-
log_tool("acquire fd %d", fd);
- rv = sanlock_acquire(fd, -1, 0, com.res_count, com.res_args, opt);
+ rv = sanlock_acquire(fd, -1, 0, com.res_count, com.res_args, NULL);
log_tool("acquire done %d", rv);
if (rv < 0)
goto out;
- if (opt)
- free(opt);
if (!command[0]) {
while (1)
@@ -2497,29 +2274,38 @@ static int do_client(void)
case ACT_INQUIRE:
log_tool("inquire pid %d", com.pid);
- rv = sanlock_inquire(-1, com.pid, SANLK_INQ_STRING, &com.res_count, (void
*)&res_str);
+ rv = sanlock_inquire(-1, com.pid, 0, &com.res_count, &res_state);
log_tool("inquire done %d res_count %d", rv, com.res_count);
- if (res_str) {
- log_tool("%s", res_str);
- free(res_str);
- }
+ if (rv < 0)
+ break;
+ log_tool("\"%s\"", res_state);
if (!options.debug)
break;
- log_tool("inquire pid %d STRUCT", com.pid);
- rv = sanlock_inquire(-1, com.pid, SANLK_INQ_STRUCT, &com.res_count, (void
*)&com.res_args);
- log_tool("inquire done %d res_count %d", rv, com.res_count);
- if (com.res_args[0]) {
- for (i = 0; i < com.res_count; i++) {
- struct sanlk_resource *res = com.res_args[i];
- log_tool("%s:%s:%s:%llu:%llu",
- res->lockspace_name, res->name, res->disks[0].path,
- (unsigned long long)res->disks[0].offset,
- (unsigned long long)res->lver);
- free(res);
- }
+ com.res_count = 0;
+
+ rv = sanlock_state_to_args(res_state, &com.res_count, &res_args);
+ log_tool("\nstate_to_args done %d res_count %d", rv, com.res_count);
+ if (rv < 0)
+ break;
+
+ free(res_state);
+ res_state = NULL;
+
+ for (i = 0; i < com.res_count; i++) {
+ res = res_args[i];
+ log_tool("\"%s:%s:%s:%llu:%llu\"",
+ res->lockspace_name, res->name, res->disks[0].path,
+ (unsigned long long)res->disks[0].offset,
+ (unsigned long long)res->lver);
}
+
+ rv = sanlock_args_to_state(com.res_count, res_args, &res_state);
+ log_tool("\nargs_to_state done %d", rv);
+ if (rv < 0)
+ break;
+ log_tool("\"%s\"", res_state);
break;
default:
diff --git a/src/sanlock.h b/src/sanlock.h
index 063b199..c4510d2 100644
--- a/src/sanlock.h
+++ b/src/sanlock.h
@@ -21,22 +21,30 @@
#define SANLK_PATH_LEN 1024
-/* disk offset units */
+/*
+ * max length of a sanlk_resource in string format
+ *
<lockspace_name>:<resource_name>:<path>:<offset>[:<path>:<offset>...]:<lver>
+ * 48 SANLK_NAME_LEN
+ * + 1 colon
+ * + 48 SANLK_NAME_LEN
+ * + 1 colon
+ * + 4184 (4 MAX_DISKS * (1024 SANLK_PATH_LEN + 1 colon + 20 offset + 1 colon))
+ * + 20 lver
+ * ------
+ * 4302
+ */
-#define SANLK_UNITS_BYTES 0
-#define SANLK_UNITS_SECTORS 1
-#define SANLK_UNITS_KB 2
-#define SANLK_UNITS_MB 3
+#define SANLK_MAX_RES_STR 4400
struct sanlk_disk {
char path[SANLK_PATH_LEN]; /* must include terminating \0 */
uint64_t offset;
- uint32_t units;
uint32_t pad1;
uint32_t pad2;
};
-#define SANLK_RES_LVER 0x1
+#define SANLK_RES_LVER 0x1 /* lver field is set */
+#define SANLK_RES_NUM_HOSTS 0x2 /* data32 field is new num_hosts */
struct sanlk_resource {
char lockspace_name[SANLK_NAME_LEN]; /* terminating \0 not required */
@@ -54,8 +62,6 @@ struct sanlk_resource {
/* command-specific command options (can include per resource data, but
that requires the extra work of segmenting it by resource name) */
-#define SANLK_OPT_NUM_HOSTS 0x1
-
struct sanlk_options {
char owner_name[SANLK_NAME_LEN]; /* optional user friendly name */
uint32_t flags;
diff --git a/src/sanlock_internal.h b/src/sanlock_internal.h
index 71fb347..4a1a2f4 100644
--- a/src/sanlock_internal.h
+++ b/src/sanlock_internal.h
@@ -28,7 +28,7 @@
/* max disks in a single lease */
-#define MAX_DISKS 8
+#define MAX_DISKS 4
/* default max number of hosts supported */
@@ -53,15 +53,13 @@
points to 1 leader_record + 1 request_record + MAX_HOSTS paxos_dblock's =
256 blocks = 128KB, ref: lease_item_record */
+/* must mirror external sanlk_disk */
+
struct sync_disk {
- /* mirror external sanlk_disk */
char path[SANLK_PATH_LEN];
uint64_t offset;
- uint32_t units;
-
- /* internal */
- uint32_t sector_size;
- int fd;
+ uint32_t sector_size; /* sanlk_disk pad1 */
+ int fd; /* sanlk_disk pad2 */
};
/* Once token and token->disks are initialized by the main loop, the only
diff --git a/src/sanlock_resource.h b/src/sanlock_resource.h
index 12ec934..fe822fc 100644
--- a/src/sanlock_resource.h
+++ b/src/sanlock_resource.h
@@ -30,21 +30,49 @@ int sanlock_acquire(int sock, int pid, uint32_t flags, int res_count,
int sanlock_release(int sock, int pid, uint32_t flags, int res_count,
struct sanlk_resource *res_args[]);
+int sanlock_inquire(int sock, int pid, uint32_t flags, int *res_count,
+ char **res_state);
+
+
+/*
+ * Functions to convert between string and struct resource formats.
+ * All allocate space for returned data that the caller must free.
+ */
+
+
+/*
+ * convert from struct sanlk_resource to string with format:
+ *
<lockspace_name>:<resource_name>:<path>:<offset>[:<path>:<offset>...]:<lver>
+ */
+
+int sanlock_res_to_str(struct sanlk_resource *res, char **str_ret);
+
/*
- * SANLK_INQ_STRING
- * allocates and returns a state string, caller frees.
+ * convert to struct sanlk_resource from string with format:
+ *
<lockspace_name>:<resource_name>:<path>:<offset>[:<path>:<offset>...][:<lver>]
+ */
+
+int sanlock_str_to_res(char *str, struct sanlk_resource **res_ret);
+
+/*
+ * convert from array of struct sanlk_resource * to state string with format:
* "RESOURCE1 RESOURCE2 RESOURCE3 ..."
- * RESOURCE =
<lockspace_name>:<resource_name>:<path>:<offset>[:<path>:<offset>...]:<version>
- *
- * SANLK_INQ_STRUCT
- * allocates and returns an array of sanlk_resource structs, caller frees.
- * [sanlk_resource][sanlk_disk...][sanlk_resource][sanlk_disk...]...
+ * RESOURCE format in sanlock_res_to_str() comment
*/
-#define SANLK_INQ_STRING 0x1
-#define SANLK_INQ_STRUCT 0x2
+int sanlock_args_to_state(int res_count,
+ struct sanlk_resource *res_args[],
+ char **res_state);
+
+/*
+ * convert to array of struct sanlk_resource * from state string with format:
+ * "RESOURCE1 RESOURCE2 RESOURCE3 ..."
+ * RESOURCE format in sanlock_str_to_res() comment
+ */
+
+int sanlock_state_to_args(char *res_state,
+ int *res_count,
+ struct sanlk_resource ***res_args);
-int sanlock_inquire(int sock, int pid, uint32_t flags, int *res_count,
- void **res_out);
#endif
diff --git a/tests/res_string.c b/tests/res_string.c
new file mode 100644
index 0000000..d1508c8
--- /dev/null
+++ b/tests/res_string.c
@@ -0,0 +1,80 @@
+#include <inttypes.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <string.h>
+
+#include "sanlock.h"
+#include "sanlock_resource.h"
+
+void print_res(struct sanlk_resource *res)
+{
+ int i;
+
+ printf("\"%s:%s", res->lockspace_name, res->name);
+
+ for (i = 0; i < res->num_disks; i++) {
+ printf(":%s:%llu", res->disks[i].path,
+ (unsigned long long)res->disks[i].offset);
+ }
+ printf(":%llu\"\n", (unsigned long long)res->lver);
+}
+
+int main(int argc, char *argv[])
+{
+ struct sanlk_resource *res;
+ struct sanlk_resource **res_args = NULL;
+ char *state;
+ int res_count;
+ int rv, i;
+
+ state = malloc(1024 * 1024);
+ memset(state, 0, 1024 * 1024);
+
+ printf("\n");
+ printf("sanlock_str_to_res\n", rv);
+ printf("--------------------------------------------------------------------------------\n");
+
+ for (i = 1; i < argc; i++) {
+ rv = sanlock_str_to_res(argv[i], &res);
+
+ print_res(res);
+
+ free(res);
+ res = NULL;
+
+ if (i > 1)
+ strcat(state, " ");
+ strcat(state, argv[i]);
+ }
+
+ printf("\n");
+ printf("combined state\n");
+ printf("--------------------------------------------------------------------------------\n");
+ printf("\"%s\"\n", state);
+
+ rv = sanlock_state_to_args(state, &res_count, &res_args);
+
+ printf("\n");
+ printf("sanlock_state_to_args %d res_count %d\n", rv, res_count);
+ printf("--------------------------------------------------------------------------------\n");
+ for (i = 0; i < res_count; i++) {
+ res = res_args[i];
+ print_res(res);
+ }
+
+ free(state);
+ state = NULL;
+
+ rv = sanlock_args_to_state(res_count, res_args, &state);
+
+ printf("\n");
+ printf("sanlock_args_to_state %d\n", rv);
+ printf("--------------------------------------------------------------------------------\n");
+ printf("\"%s\"\n", state);
+
+ return 0;
+}
+