range* rangefunc_get_groups(range_request* rr, range** r) { sqlite3* db; sqlite3_stmt* stmt; int err; range* ret = range_new(rr); apr_pool_t* pool = range_request_pool(rr); const char** tag_names = range_get_hostnames(pool, r[0]); const char* tag_name = tag_names[0]; int warn_enabled = range_request_warn_enabled(rr); if (NULL == tag_name) { return ret; } db = _open_db(rr); err = sqlite3_prepare(db, GROUPS_SQL, strlen(GROUPS_SQL), &stmt, NULL); if (err != SQLITE_OK) { range_request_warn(rr, "?%s: cannot query sqlite db", tag_name ); return ret; } assert(err == SQLITE_OK); sqlite3_bind_text(stmt, 1, tag_name, strlen(tag_name), SQLITE_STATIC); while(sqlite3_step(stmt) == SQLITE_ROW) { const char* answer = (const char*)sqlite3_column_text(stmt, 0); range_add(ret, answer); } sqlite3_finalize(stmt); return ret; }
sqlite3* _open_db(range_request* rr) { char * sqlite_db_path; sqlite3* db; sqlite3_stmt* stmt; libcrange* lr = range_request_lr(rr); int err; /* open the db */ if (!(db = libcrange_get_cache(lr, "sqlite:nodes"))) { sqlite_db_path = libcrange_getcfg(lr, "sqlitedb"); if (!sqlite_db_path) sqlite_db_path = DEFAULT_SQLITE_DB; err = sqlite3_open(sqlite_db_path, &db); if (err != SQLITE_OK) { return NULL; } assert(err == SQLITE_OK); /* set mmap pragma */ err = sqlite3_prepare(db, MMAP_PRAGMA_SQL, strlen(MMAP_PRAGMA_SQL), &stmt, NULL); if (err != SQLITE_OK) { range_request_warn(rr, "allclusters(): cannot query sqlite db"); return NULL; } assert(err == SQLITE_OK); while(sqlite3_step(stmt) == SQLITE_ROW) { // do nothing. Is this even necessary for the mmap_size pragma? docs are unclear } /* end mmap pragma setup */ libcrange_set_cache(lr, "sqlite:nodes", db); } return db; }
range* rangefunc_clusters(range_request* rr, range** r) { sqlite3* db; sqlite3_stmt* stmt; int err; range* ret = range_new(rr); apr_pool_t* pool = range_request_pool(rr); const char** nodes = range_get_hostnames(pool, r[0]); const char** p_nodes = nodes; db = _open_db(rr); err = sqlite3_prepare(db, CLUSTERS_SQL, strlen(CLUSTERS_SQL), &stmt, NULL); if (err != SQLITE_OK) { range_request_warn(rr, "clusters(): cannot query sqlite db"); return ret; } while (*p_nodes) { char * node_name = *p_nodes; sqlite3_bind_text(stmt, 1, node_name, strlen(node_name), SQLITE_STATIC); while(sqlite3_step(stmt) == SQLITE_ROW) { const char* answer = (const char*)sqlite3_column_text(stmt, 0); range_add(ret, answer); } sqlite3_reset(stmt); sqlite3_clear_bindings(stmt); ++p_nodes; } sqlite3_finalize(stmt); return ret; }
range* do_range_expand(range_request* rr, const char* text) { yyscan_t scanner; struct range_extras extra; int result; if (text == NULL) { range* r = range_new(rr); range_request_set(rr, r); return r; } current_rr = rr; extra.rr = rr; yylex_init(&scanner); yyset_extra(&extra, scanner); yy_scan_string(text, scanner); result = yyparse(scanner); yylex_destroy(scanner); current_rr = NULL; if (result != 0) { range* r = range_new(rr); range_request_warn(rr, "parsing [%s]", text); range_request_set(rr, r); return r; } range_request_set(rr, range_evaluate(rr, extra.theast)); return range_request_results(rr); }
range* range_from_match(range_request* rr, const range* r, const char* regex) { range* ret; int i; int err_offset; int ovector[30]; int count; const char* error; const char** members; pcre* re; apr_pool_t* pool = range_request_pool(rr); members = range_get_hostnames(pool, r); ret = range_new(rr); re = pcre_compile(regex, 0, &error, &err_offset, NULL); if (!re) { range_request_warn(rr, "regex [%s] [%s]", regex, error); return ret; } for (i = 0; members[i]; i++) { count = pcre_exec(re, NULL, members[i], strlen(members[i]), 0, 0, ovector, 30); if (count > 0) /* it matched */ range_add(ret, members[i]); } pcre_free(re); return ret; }
range* _do_has_mem(range_request* rr, range** r, char* sql_query) { sqlite3* db; sqlite3_stmt* stmt; int err; range* ret = range_new(rr); apr_pool_t* pool = range_request_pool(rr); if (NULL == r[0]) { // don't attempt anything without arg #1 (key) return ret; } const char** tag_names = range_get_hostnames(pool, r[0]); const char* tag_name = tag_names[0]; if (NULL == tag_name) { return ret; } const char** tag_values; const char* tag_value; if (NULL == r[1]) { // if we don't have arg #2 (val) then search for keys with empty string value tag_value = EMPTY_STRING; } else { tag_values = range_get_hostnames(pool, r[1]); tag_value = tag_values[0]; } const char** all_clusters = _all_clusters(rr); const char** cluster = all_clusters; int warn_enabled = range_request_warn_enabled(rr); db = _open_db(rr); err = sqlite3_prepare(db, sql_query, strlen(sql_query), &stmt, NULL); if (err != SQLITE_OK) { range_request_warn(rr, "has(%s,%s): cannot query sqlite db", tag_name, tag_value); return ret; } assert(err == SQLITE_OK); sqlite3_bind_text(stmt, 1, tag_name, strlen(tag_name), SQLITE_STATIC); sqlite3_bind_text(stmt, 2, tag_value, strlen(tag_value), SQLITE_STATIC); while(sqlite3_step(stmt) == SQLITE_ROW) { const char* answer = (const char*)sqlite3_column_text(stmt, 0); range_add(ret, answer); } sqlite3_finalize(stmt); return ret; }
MDBM * _open_mdbm(range_request* rr) { const char * mdbm_db_path; if (!mdbm_cache) { libcrange* lr = range_request_lr(rr); mdbm_db_path = libcrange_getcfg(lr, "mdbmdb"); if (!mdbm_db_path) mdbm_db_path = DEFAULT_MDBM_DB; mdbm_cache = mdbm_open(mdbm_db_path, MDBM_O_RDONLY, 0, 0, 0); if (!mdbm_cache) { range_request_warn(rr, "cannot open mdbm"); } assert(mdbm_cache); } return mdbm_cache; }
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; }
const char* do_range_compress(range_request* rr, const range* r) { int i; #define MAX_NUM_GROUPS 65536 const char* groups[MAX_NUM_GROUPS]; int num_groups = 0; int count; char* result; char* presult; int result_size; const char** sorted_nodes; int n = r->nodes->members; apr_pool_t* pool = range_request_pool(rr); node_parts_int* prev = init_prev_parts(pool); int prev_num_str_len = -1; if (n == 0) return ""; sorted_nodes = do_range_sort(rr, r); init_range_parts(); count = 0; for (i=0; i<n; ++i) { node_parts_int* parts = node_to_parts(pool, sorted_nodes[i]); if (strcmp(parts->prefix, prev->prefix) == 0 && strcmp(parts->domain, prev->domain) == 0 && (parts->num == prev->num + count + 1) && strlen(parts->num_str) == prev_num_str_len) count++; else { if (*prev->full_name) { if (count > 0) groups[num_groups] = fmt_group(pool, prev, count); else groups[num_groups] = prev->full_name; ++num_groups; if (num_groups == MAX_NUM_GROUPS) { range_request_warn(rr, "%s\n", "too many compressed groups"); return ""; } } prev = parts; if (prev->num_str) prev_num_str_len = strlen(prev->num_str); count = 0; } } if (count > 0) groups[num_groups] = fmt_group(pool, prev, count); else groups[num_groups] = prev->full_name; /* num_groups is 1 less than the # of groups */ result_size = num_groups; /* commas */ for (i=0; i<=num_groups; ++i) result_size += strlen(groups[i]); presult = result = apr_palloc(pool, result_size + 1); for (i=0; i<num_groups; ++i) { strcpy(presult, groups[i]); presult += strlen(groups[i]); *presult++ = ','; } /* add the last one */ strcpy(presult, groups[num_groups]); return result; }
void yyerror (YYLTYPE *locp, void * scanner, char const *msg) { range_request_warn(current_rr, "%s", msg); }