static set* _cluster_keys(range_request* rr, apr_pool_t* pool, const char* cluster) { set* sections; sqlite3* db; sqlite3_stmt* stmt; int err; db = _open_db(rr); /* our return set */ sections = set_new(pool, 0); /* prepare our select */ err = sqlite3_prepare(db, KEYVALUE_SQL, strlen(KEYVALUE_SQL), &stmt, NULL); if (err != SQLITE_OK) { range_request_warn(rr, "%s: cannot query sqlite db", cluster); return sections; } assert(err == SQLITE_OK); /* for each key/value pair in cluster */ sqlite3_bind_text(stmt, 1, cluster, strlen(cluster), SQLITE_STATIC); while(sqlite3_step(stmt) == SQLITE_ROW) { /* add it to the return */ const char* key = (const char*)sqlite3_column_text(stmt, 0); const char* value = (const char*)sqlite3_column_text(stmt, 1); if (NULL == value) { value = EMPTY_STRING; } set_add(sections, key, apr_psprintf(pool, "%s", _substitute_dollars(pool, cluster, value) )); } /* Add the magic "KEYS" index */ set_add(sections, "KEYS", _join_elements(pool, ',', sections)); sqlite3_finalize(stmt); return sections; }
/* this is where the magic happens */ static set* _cluster_keys(range_request* rr, apr_pool_t* pool, const char* cluster, const char* cluster_file) { apr_array_header_t* working_range; set* sections; char* section; char* cur_section; apr_pool_t* req_pool = range_request_pool(rr); yaml_node_t *node; yaml_node_t *rootnode; yaml_node_t *keynode; yaml_node_t *valuenode; yaml_parser_t parser; yaml_node_item_t *item; yaml_node_pair_t *pair; yaml_document_t document; FILE* fp = fopen(cluster_file, "r"); /* make sure we can open the file and parse it */ if (!fp) { range_request_warn(rr, "%s: %s not readable", cluster, cluster_file); return set_new(pool, 0); } if (!yaml_parser_initialize(&parser)) { range_request_warn(rr, "%s: cannot initialize yaml parser", cluster); fclose(fp); return set_new(pool, 0); } yaml_parser_set_input_file(&parser, fp); if(!yaml_parser_load(&parser, &document)) { range_request_warn(rr, "%s: malformatted cluster definition %s", cluster, cluster_file); fclose(fp); yaml_parser_delete(&parser); return set_new(pool, 0); } fclose(fp); rootnode = yaml_document_get_root_node(&document); /* make sure it's just a simple dictionary */ if(rootnode->type != YAML_MAPPING_NODE) { range_request_warn(rr, "%s: malformatted cluster definition %s", cluster, cluster_file); yaml_document_delete(&document); yaml_parser_delete(&parser); return set_new(pool, 0); } /* "sections" refers to cluster sections - %cluster:SECTION it's what we're going to return */ sections = set_new(pool, 0); section = cur_section = NULL; for(pair = rootnode->data.mapping.pairs.start; pair < rootnode->data.mapping.pairs.top; pair++) { /* these are the keys */ keynode = yaml_document_get_node(&document, pair->key); /* cur_section is the keyname - the WHATEVER in %cluster:WHATEVER */ cur_section = apr_pstrdup(pool, (char *)(keynode->data.scalar.value)); valuenode = yaml_document_get_node(&document, pair->value); /* if the value is a scalar, that's our answer */ if(valuenode->type == YAML_SCALAR_NODE) { set_add(sections, cur_section, apr_psprintf(pool, "%s", valuenode->data.scalar.value)); } else if (valuenode->type == YAML_SEQUENCE_NODE) { /* otherwise, glue together all the values in the list */ working_range = apr_array_make(req_pool, 1, sizeof(char*)); for(item = valuenode->data.sequence.items.start; item < valuenode->data.sequence.items.top; item++) { node = yaml_document_get_node(&document, (int)*item); if(node->type != YAML_SCALAR_NODE) { /* only scalars allowed */ range_request_warn(rr, "%s: malformed cluster definition %s", cluster, cluster_file); yaml_document_delete(&document); yaml_parser_delete(&parser); return set_new(pool, 0); } else { /* add to the working set */ /* include it in () because we're going to comma it together later */ *(char**)apr_array_push(working_range) = apr_psprintf(pool, "(%s)", _substitute_dollars(pool, cluster, node->data.scalar.value)); } } /* glue the list items together with commas */ set_add(sections, cur_section, apr_array_pstrcat(pool, working_range, ',')); } } /* Add a "KEYS" toplevel key that lists all the other keys */ /* TODO: make an error if somebody tries to specify KEYS manually? */ set_add(sections, "KEYS", _join_elements(pool, ',', sections)); yaml_document_delete(&document); yaml_parser_delete(&parser); return sections; }
static set* _cluster_keys(range_request* rr, apr_pool_t* pool, const char* cluster, const char* cluster_file) { char line[32768]; char* p; int ovector[30]; apr_array_header_t* working_range; set* sections; char* section; char* cur_section; apr_pool_t* req_pool = range_request_pool(rr); int line_no; FILE* fp = fopen(cluster_file, "r"); if (!fp) { range_request_warn(rr, "%s: %s not readable", cluster, cluster_file); return set_new(pool, 0); } if (!include_re) { const char* error; include_re = pcre_compile(INCLUDE_RE, 0, &error, ovector, NULL); assert(include_re); exclude_re = pcre_compile(EXCLUDE_RE, 0, &error, ovector, NULL); assert(exclude_re); } sections = set_new(pool, 0); section = cur_section = NULL; working_range = apr_array_make(req_pool, 1, sizeof(char*)); line_no = 0; while (fgets(line, sizeof line, fp)) { int len; int count; line_no++; line[sizeof line - 1] = '\0'; len = strlen(line); if (len+1 >= sizeof(line) && line[len - 1] != '\n') { /* incomplete line */ fprintf(stderr, "%s:%d lines > 32767 chars not supported\n", cluster_file, line_no); exit(-1); } line[--len] = '\0'; /* get rid of the \n */ for (p = line; *p; ++p) if (*p == '#') { *p = '\0'; break; } len = strlen(line); if (len == 0) continue; for (p = &line[len - 1]; isspace(*p); --p) { *p = '\0'; --len; } if (!*line) continue; if (!(isspace(*line))) { cur_section = apr_pstrdup(pool, line); continue; } if (section && strcmp(cur_section, section) != 0) { set_add(sections, section, apr_array_pstrcat(pool, working_range, ',')); working_range = apr_array_make(req_pool, 1, sizeof(char*)); } section = cur_section; count = pcre_exec(include_re, NULL, line, len, 0, 0, ovector, 30); if (count > 0) { line[ovector[3]] = '\0'; *(char**)apr_array_push(working_range) = apr_psprintf(pool, "(%s)", _substitute_dollars(pool, cluster, &line[ovector[2]])); continue; } count = pcre_exec(exclude_re, NULL, line, len, 0, 0, ovector, 30); if (count > 0) { line[ovector[3]] = '\0'; *(char**)apr_array_push(working_range) = apr_psprintf(pool, "-(%s)", _substitute_dollars(pool, cluster, &line[ovector[2]])); } } fclose(fp); if (cur_section) set_add(sections, cur_section, apr_array_pstrcat(pool, working_range, ',')); set_add(sections, "KEYS", _join_elements(pool, ',', sections)); set_add(sections, "UP", set_get_data(sections, "CLUSTER")); if (set_get(sections, "ALL") && set_get(sections, "CLUSTER")) set_add(sections, "DOWN", apr_psprintf(pool, "(%s)-(%s)", (char*)set_get_data(sections, "ALL"), (char*)set_get_data(sections, "CLUSTER"))); return sections; }