static int __may_fail query_create_schema_impl (query_result *r, char *name, int strict) { __returns_int; // make checks __precondition(NULL != r); schema *s = datastore_get_schema_by_name(name); parser_assert_err(QUERY_ERR_SCHEMA_EEXISTS, !(strict && s), name); // handle query if (s) return 0; __checked_call(NULL != (s = schema_create(name))); __checked_call(0 == datastore_add_schema(s), schema_destroy(s); );
/* * schema_fromascii - input a converted schema ASCII string into a schema * * - memory is allocated for the schema, application shall later call * schema_destroy to clean up * - assume the ascii string is produced by schema_toascii * - return a pointer to the initialized schema if OK, NULL on error * */ schema_t *schema_fromascii(const char *asc_schema) { int fieldind; char *buf, *saveptr; char *endian, *fieldnum, *name, *size, *offset, *type; schema_t *schema; if ((schema = schema_create(NULL)) == NULL) { fprintf(stderr, "schema_fromascii: cannot create schema stub\n"); return NULL; } if ((buf = strdup(asc_schema)) == NULL) { perror("schema_fromascii: strdup"); return NULL; } endian = (char *)strtok_r(buf, " ", &saveptr); if (strcmp(endian, "L") == 0) schema->endian = little; else if (strcmp(endian, "B") == 0) schema->endian = big; else { fprintf(stderr, "schema_fromascii: unknown endianness %s\n", endian); free(schema); return NULL; } fieldnum = (char *)strtok_r(NULL, " ", &saveptr); if (fieldnum == NULL) { fprintf(stderr, "schema_fromascii: missing fieldnum %s\n", asc_schema); free(schema); return NULL; } if (sscanf(fieldnum, "%d", &schema->fieldnum) != 1) { fprintf(stderr, "schema_fromascii: unknown fieldnum specifier %s\n", fieldnum); } /* allocate the field table */ schema->field = (field_t *)malloc(schema->fieldnum * sizeof(field_t)); if (schema->field == NULL) { perror("schema_fromascii: malloc field table"); free(schema); return NULL; } for (fieldind = 0 ; fieldind < schema->fieldnum; fieldind++) { name = (char *)strtok_r((char *)NULL, " ", &saveptr); type = (char *)strtok_r((char *)NULL, " ", &saveptr); size = (char *)strtok_r((char *)NULL, " ", &saveptr); offset = (char *)strtok_r((char *)NULL, " ", &saveptr); if ((name == NULL) || (type == NULL) || (size == NULL) || (offset == NULL)) { fprintf(stderr, "schema_fromascii: incomplete ascii schema %s\n", asc_schema); break; } if (sscanf(size, "%d", &schema->field[fieldind].size) != 1) { fprintf(stderr, "schema_fromascii: unknown size specifier %s\n", size); break; } if (sscanf(offset, "%d", &schema->field[fieldind].offset) != 1) { fprintf(stderr, "schema_fromascii: unknown offset specifer %s\n", offset); break; } if ((schema->field[fieldind].name = strdup(name)) == NULL) { perror("schema_fromascii: strdup field name"); break; } if ((schema->field[fieldind].type = strdup(type)) == NULL) { perror("schema_fromascii: strdup field type"); break; } } free(buf); /* we need to free the memory */ if (fieldind < schema->fieldnum) { /* break out of the loop because of error here is a trick to guarantee the proper behavior of schema_destroy */ schema->fieldnum = fieldind; schema_destroy(schema); return NULL; } return schema; }
/* * returns a pointer to a schema, or NULL if fails */ static struct schema *schema_create_from_hash(uint64_t hash, const char *bucket_name) { struct schema *schema = NULL; char buf[1024]; snprintf(buf, sizeof(buf), "%s/schemas/%016"PRIx64, bucket_name, hash); log_notice("read schema from file [%s]", buf); FILE *f = fopen(buf, "r"); if (f == NULL) { // legacy file path snprintf(buf, sizeof(buf), "schemas/%016"PRIx64, hash); log_notice("read schema from file [%s]", buf); f = fopen(buf, "r"); } if (f == NULL) { log_notice("read schema failed"); return NULL; } schema = schema_create(); if (!schema) { log_error("can't create schema"); goto fail; } while (fgets(buf, sizeof(buf), f)) { char *saveptr; char *token = strtok_r(buf, " \n\r\t", &saveptr); uint8_t is_primary_key = 0; uint8_t is_signed = 0; char *name = NULL; uint16_t nbits = 0; if (strcmp(token, "upgrade_to") == 0) { token = next_token(&saveptr); if (token == NULL) goto fail; if (sscanf(token, "%"SCNx64, &schema->upgrade_to) != 1) goto fail; if (schema->upgrade_to == 0) goto fail; } else { /* backward compat */ if (strcmp(token, "field") == 0) token = next_token(&saveptr); while (token) { if (token[0] >= '1' && token[1] <= '9') nbits = atoi(token); else if (strcmp(token, "primary_key") == 0) is_primary_key = 1; else if (strcmp(token, "signed") == 0) is_signed = 1; else if (token[0] == '[') { // field name size_t len = strlen(token); if (token[len - 1] == ']') { token[len - 1] = '\0'; name = &token[1]; if (!is_valid_name(name)) goto fail; } else goto fail; } else goto fail; token = next_token(&saveptr); } int res = schema_field_add(schema, name, is_signed, nbits, is_primary_key); if (res != 0) goto fail; } } fclose(f); schema->hash = hash; return schema; fail: fclose(f); if (schema) slab_free(schema); log_error("schema file %016"PRIx64" is invalid", hash); return NULL; }