range* rangefunc_has(range_request* rr, range** r) { 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_values = range_get_hostnames(pool, r[1]); const char* tag_name = tag_names[0]; const char* 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); if (!cluster) return ret; range_request_disable_warns(rr); while (*cluster) { range* vals = _expand_cluster(rr, *cluster, tag_name); if (set_get(vals->nodes, tag_value) != NULL) { range_add(ret, *cluster); } cluster++; } if (warn_enabled) range_request_enable_warns(rr); return ret; }
range* rangefunc_mem(range_request* rr, range** r) { range* ret = range_new(rr); apr_pool_t* pool = range_request_pool(rr); const char** clusters = range_get_hostnames(pool, r[0]); const char* cluster = clusters[0]; const char** wanted = range_get_hostnames(pool, r[1]); range* keys = _expand_cluster(rr, cluster, "KEYS"); const char** all_sections = range_get_hostnames(pool, keys); const char** p_section = all_sections; SECTION: while (*p_section) { range* r_s = _expand_cluster(rr, cluster, *p_section); const char** p_wanted = wanted; while (*p_wanted) { if (set_get(r_s->nodes, *p_wanted) != NULL) { range_add(ret, *p_section++); goto SECTION; } ++p_wanted; } ++p_section; } return ret; }
static range* _expand_cluster(range_request* rr, const char* cluster, const char* section) { set * ret_set; MDBM * db = _open_mdbm(rr); apr_pool_t* req_pool = range_request_pool(rr); // return a range * of the section // build the key:val strncpy(fetch_key, cluster, MAX_CLUSTER_STRING); strncat(fetch_key, ":", MAX_CLUSTER_STRING); strncat(fetch_key, section, MAX_CLUSTER_STRING); // first, query the data from mdbm datum val; datum key; key.dptr = fetch_key; key.dsize = strlen(fetch_key); val = mdbm_fetch(db, key); if (val.dsize) { ret_set = set_unpack(req_pool, val.dptr); return range_from_set(rr, ret_set); } else { /* FIXME warn -- ok fixed*/ range_request_warn_type(rr, "NOCLUSTER", fetch_key); return range_new(rr); } }
static set* _get_clusters(range_request* rr) { const char** all_clusters = _all_clusters(rr); const char** p_cl = all_clusters; apr_pool_t* pool = range_request_pool(rr); set* node_cluster = set_new(pool, 40000); if(p_cl == NULL) { return node_cluster; } while (*p_cl) { range* nodes_r = _expand_cluster(rr, *p_cl, "CLUSTER"); const char** nodes = range_get_hostnames(pool, nodes_r); const char** p_nodes = nodes; while (*p_nodes) { apr_array_header_t* clusters = set_get_data(node_cluster, *p_nodes); if (!clusters) { clusters = apr_array_make(pool, 1, sizeof(char*)); set_add(node_cluster, *p_nodes, clusters); } *(const char**)apr_array_push(clusters) = *p_cl; ++p_nodes; } ++p_cl; } return node_cluster; }
range* rangefunc_clusters(range_request* rr, range** r) { 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; set* node_cluster = _get_clusters(rr); while (*p_nodes) { apr_array_header_t* clusters = set_get_data(node_cluster, *p_nodes); if (!clusters) range_request_warn_type(rr, "NO_CLUSTER", *p_nodes); else { /* get all */ int i; for (i=0; i<clusters->nelts; ++i) { const char* cluster = ((const char**)clusters->elts)[i]; range_add(ret, cluster); } } ++p_nodes; } return ret; }
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* 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; }
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; }
static vips* _empty_vips(range_request* rr) { apr_pool_t* pool = range_request_pool(rr); vips* v = apr_palloc(pool, sizeof(*v)); v->vips = v->viphosts = set_new(pool, 0); return v; }
range* range_from_set(range_request* rr, set* s) { apr_pool_t* p = range_request_pool(rr); range* r = apr_palloc(p, sizeof(range)); r->nodes = s; r->quoted = 0; return r; }
range* range_new(range_request* rr) { apr_pool_t* pool = range_request_pool(rr); range* r = apr_palloc(pool, sizeof(range)); r->nodes = set_new(pool, 0); r->quoted = 0; return r; }
static range* _expand_cluster(range_request* rr, const char* cluster, const char* section) { struct stat st; const char* res; libcrange* lr = range_request_lr(rr); set* cache = libcrange_get_cache(lr, "nodescf:cluster_keys"); apr_pool_t* req_pool = range_request_pool(rr); apr_pool_t* lr_pool = range_request_lr_pool(rr); const char* cluster_file; cache_entry* e; if (strcmp(section, "VIPS") == 0) return _cluster_vips(rr, cluster); if (strcmp(section, "VIPHOSTS") == 0) return _cluster_viphosts(rr, cluster); cluster_file = apr_psprintf(req_pool, "%s/%s/nodes.cf", nodescf_path, cluster); if (!cache) { cache = set_new(lr_pool, 0); libcrange_set_cache(lr, "nodescf:cluster_keys", cache); } if (stat(cluster_file, &st) == -1) { range_request_warn_type(rr, "NOCLUSTERDEF", cluster); return range_new(rr); } e = set_get_data(cache, cluster_file); if (!e) { e = apr_palloc(lr_pool, sizeof(struct cache_entry)); apr_pool_create(&e->pool, lr_pool); e->sections = _cluster_keys(rr, e->pool, cluster, cluster_file); e->mtime = st.st_mtime; set_add(cache, cluster_file, e); } else { time_t cached_mtime = e->mtime; if (cached_mtime != st.st_mtime) { apr_pool_clear(e->pool); e->sections = _cluster_keys(rr, e->pool, cluster, cluster_file); e->mtime = st.st_mtime; } } res = set_get_data(e->sections, section); if (!res) { char* cluster_section = apr_psprintf(req_pool, "%s:%s", cluster, section); range_request_warn_type(rr, "NOCLUSTER", cluster_section); return range_new(rr); } return do_range_expand(rr, res); }
range* range_from_diff(range_request* rr, const range* r1, const range* r2) { range* r3 = range_new(rr); apr_pool_t* pool = range_request_pool(rr); r3->nodes = set_diff(pool, r1->nodes, r2->nodes); r3->quoted = r1->quoted || r2->quoted; return r3; }
range* rangefunc_group(range_request* rr, range** r) { range* ret = range_new(rr); apr_pool_t* pool = range_request_pool(rr); const char** groups = range_get_hostnames(pool, r[0]); while (*groups) { range_union_inplace(rr, ret, _expand_cluster(rr, "GROUPS", *groups)); ++groups; } return ret; }
range* range_from_braces(range_request* rr, const range* r1, const range* r2, const range* r3) { int i, j, k; set_element** m1; set_element** m2; set_element** m3; set* temp = NULL; range* bigrange; char* bundle; apr_pool_t* pool = range_request_pool(rr); if(r1->nodes->members == 0) { if(!temp) { temp = set_new(pool, 1); set_add(temp, "", NULL); } m1 = set_members(temp); } else m1 = set_members(r1->nodes); if(r2->nodes->members == 0) { if(!temp) { temp = set_new(pool, 1); set_add(temp, "", NULL); } m2 = set_members(temp); } else m2 = set_members(r2->nodes); if(r3->nodes->members == 0) { if(!temp) { temp = set_new(pool, 1); set_add(temp, "", NULL); } m3 = set_members(temp); } else m3 = set_members(r3->nodes); bigrange = range_new(rr); for(i = 0; m1[i]; i++) for(j = 0; m2[j]; j++) for(k = 0; m3[k]; k++) { bundle = apr_pstrcat(pool, m1[i]->name, m2[j]->name, m3[k]->name, NULL); range_add(bigrange, bundle); } if (temp) set_destroy(temp); bigrange->quoted = r1->quoted || r2->quoted || r3->quoted; return bigrange; }
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; }
rangeparts *rangeparts_from_hostname(range_request* rr, const char* hostname) { pcre* re; const char* error; rangeparts* rangeparts; int offset, count; int offsets[128]; static pcre* regex_node = NULL; apr_pool_t* pool = range_request_pool(rr); if (!regex_node) regex_node = pcre_compile(NODE_RE, 0, &error, &offset, NULL); re = regex_node; count = pcre_exec(re, NULL, hostname, strlen(hostname), 0, 0, offsets, sizeof(offsets)/sizeof(int)); if (count > 0) { /* * 1 == prefix * 2 == range start * 3 == domain, maybe * 4 == range specifier: - or .. * 5 == range end * 6 == domain, maybe */ rangeparts = rangeparts_new(pool); rangeparts->prefix = libcrange_get_pcre_substring(pool, hostname, offsets, 1); rangeparts->first = libcrange_get_pcre_substring(pool, hostname, offsets, 2); rangeparts->last = libcrange_get_pcre_substring(pool, hostname, offsets, 5); if ((offsets[7] - offsets[6]) > 0) { /* if we have a domain */ rangeparts->domain = libcrange_get_pcre_substring(pool, hostname, offsets, 3); } else if ((offsets[13] - offsets[12]) > 0) { rangeparts->domain = libcrange_get_pcre_substring(pool, hostname, offsets, 6); } else { rangeparts->domain = ""; } /* if (hostname[offsets[8]] == '-') { range_request_warn_type(rr, "DEPRECATED_SYNTAX", hostname); } */ return rangeparts; } return NULL; }
range * rangefunc_group(range_request* rr, range** r) { sqlite3* db; db = _open_db(rr); range* ret = range_new(rr), *expanded; apr_pool_t* pool = range_request_pool(rr); const char** groups = range_get_hostnames(pool, r[0]); while (*groups) { expanded = _expand_cluster(rr, "GROUPS", *groups); range_union_inplace(rr, ret, expanded); ++groups; } return ret; }
static range* _python_function(range_request* rr, const char* funcname, const range** r) { range* result = range_new(rr); PyObject * pLibcrangeCallFunc; PyObject * pNodesReturned; PyObject * pMain = PyImport_AddModule("__main__"); // printf("rr: %p, funcname=%s, range**r = %p\n", rr, funcname, r); pLibcrangeCallFunc = PyObject_GetAttrString(pMain, "libcrange_call_func"); if (pLibcrangeCallFunc && PyCallable_Check(pLibcrangeCallFunc)) { PyObject * pRangeFuncName; PyObject * item; pRangeFuncName = PyString_FromString(funcname); PyObject * pFuncArgs; PyObject * pTempArgList = PyList_New(0); PyList_Append(pTempArgList, pRangeFuncName); Py_DECREF(pRangeFuncName); // build our range** into python function args const range** p_r = r; while (*p_r) { item = range_to_py_array(range_request_pool(rr), *p_r); PyList_Append(pTempArgList, item); Py_DECREF(item); p_r++; } pFuncArgs = PyList_AsTuple(pTempArgList); Py_DECREF(pTempArgList); // call the function pNodesReturned = PyObject_CallObject(pLibcrangeCallFunc, pFuncArgs); Py_DECREF(pFuncArgs); PyObject *iterator = PyObject_GetIter(pNodesReturned); if (iterator == NULL) { printf("ERROR: python function %s ran, but didn't return an iteratable object", funcname); return result; } // an iteratable object was returned, transform it into result while (item = PyIter_Next(iterator)) { // PyObject_Print(item, stdout, 0 ); range_add(result, PyString_AsString(item)); Py_DECREF(item); } Py_DECREF(pNodesReturned); } return result; }
range* rangefunc_get_groups(range_request* rr, range** r) { range* ret = range_new(rr); if (!validate_range_args(rr, r, 1)) { return ret; } range* n = r[0]; apr_pool_t* pool = range_request_pool(rr); const char** in_nodes = range_get_hostnames(pool, n); set* node_group = set_new(pool, 40000); range* groups_r = _expand_cluster(rr, "GROUPS", "KEYS"); const char** groups = range_get_hostnames(pool, groups_r); const char** p_group = groups; while (*p_group) { range* nodes_r = _expand_cluster(rr, "GROUPS", *p_group); const char** nodes = range_get_hostnames(pool, nodes_r); const char** p_nodes = nodes; while (*p_nodes) { apr_array_header_t* my_groups = set_get_data(node_group, *p_nodes); if (!my_groups) { my_groups = apr_array_make(pool, 4, sizeof(char*)); set_add(node_group, *p_nodes, my_groups); } *(const char**)apr_array_push(my_groups) = *p_group; ++p_nodes; } ++p_group; } while (*in_nodes) { apr_array_header_t* my_groups = set_get_data(node_group, *in_nodes); if (!my_groups) range_request_warn_type(rr, "NO_GROUPS", *in_nodes); else { int i; for (i=0; i<my_groups->nelts; ++i) range_add(ret, ((const char**)my_groups->elts)[i]); } in_nodes++; } return ret; }
range* rangefunc_group(range_request* rr, range** r) { range* ret = range_new(rr); if (!validate_range_args(rr, r, 1)) { return ret; } apr_pool_t* pool = range_request_pool(rr); const char** groups = range_get_hostnames(pool, r[0]); while (*groups) { if (islower(*groups[0])) range_union_inplace(rr, ret, _expand_cluster(rr, "HOSTS", *groups)); else range_union_inplace(rr, ret, _expand_cluster(rr, "GROUPS", *groups)); ++groups; } return ret; }
range* rangefunc_cluster(range_request* rr, range** r) { range* ret = range_new(rr); if (!validate_range_args(rr, r, 1)) { return ret; } apr_pool_t* pool = range_request_pool(rr); const char** clusters = range_get_hostnames(pool, r[0]); const char** p = clusters; while (*p) { const char* colon = strchr(*p, ':'); range* r1; if (colon) { int len = strlen(*p); int cluster_len = colon - *p; int section_len = len - cluster_len - 1; char* cl = apr_palloc(pool, cluster_len + 1); char* sec = apr_palloc(pool, section_len + 1); memcpy(cl, *p, cluster_len); cl[cluster_len] = '\0'; memcpy(sec, colon + 1, section_len); sec[section_len] = '\0'; r1 = _expand_cluster(rr, cl, sec); } else r1 = _expand_cluster(rr, *p, "CLUSTER"); if (range_members(r1) > range_members(ret)) { /* swap them */ range* tmp = r1; r1 = ret; ret = tmp; } range_union_inplace(rr, ret, r1); range_destroy(r1); ++p; } return ret; }
static set* _get_ignore_set(range_request* rr) { char line[32768]; apr_pool_t* pool = range_request_pool(rr); const char* ignore_path = apr_psprintf(pool, "%s/all/IGNORE", nodescf_path); set* ret = set_new(pool, 0); FILE* fp = fopen(ignore_path, "r"); if (!fp) return ret; while (fgets(line, sizeof line, fp) != NULL) { int len; char* p; line[sizeof line - 1] = '\0'; len = strlen(line); if (!len) continue; if (line[len - 1] == '\n') line[--len] = '\0'; for (p = line; *p; ++p) if (*p == '#') { *p = '\0'; len = strlen(line); break; } if (!len) continue; for (p = &line[len - 1]; isspace(*p); --p) { --len; *p = '\0'; } if (len <= 0) continue; set_add(ret, line, 0); } fclose(fp); return ret; }
range* range_from_rangeparts(range_request* rr, const rangeparts* parts) { int i; int f, l, firstlength, lastlength, length; range* r; char* pad1 = ""; char* first; char* last; char* tmpstr; apr_pool_t* pool = range_request_pool(rr); r = range_new(rr); firstlength = strlen(parts->first); lastlength = strlen(parts->last); first = parts->first; last = parts->last; if (firstlength > lastlength) { pad1 = apr_palloc(pool, firstlength - lastlength + 1); for(i=0; i < (firstlength - lastlength); i++) pad1[i] = parts->first[i]; pad1[i] = '\0'; first = parts->first + i; } f = atoi(first); l = atoi(last); length = firstlength > lastlength ? lastlength : firstlength; for(i=f; i<=l; i++) { tmpstr = apr_psprintf(pool, "%s%s%0*d%s", parts->prefix, pad1, length, i, parts->domain); range_add(r, tmpstr); } return r; }
range* rangefunc_get_admin(range_request* rr, range** r) { range* ret = range_new(rr); if (!validate_range_args(rr, r, 1)) { return ret; } range* n = r[0]; apr_pool_t* pool = range_request_pool(rr); const char** in_nodes = range_get_hostnames(pool, n); set* node_admin = set_new(pool, 40000); range* admins_r = _expand_cluster(rr, "HOSTS", "KEYS"); const char** admins = range_get_hostnames(pool, admins_r); const char** p_admin = admins; while (*p_admin) { range* nodes_r = _expand_cluster(rr, "HOSTS", *p_admin); const char** nodes = range_get_hostnames(pool, nodes_r); const char** p_nodes = nodes; while (*p_nodes) { set_add(node_admin, *p_nodes, (void*)*p_admin); ++p_nodes; } ++p_admin; } while (*in_nodes) { const char* admin = set_get_data(node_admin, *in_nodes); if (!admin) { range_request_warn_type(rr, "NO_ADMIN", *in_nodes); } else { range_add(ret, admin); } in_nodes++; } return ret; }
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; }
static vips* _parse_cluster_vips(range_request* rr, const char* cluster) { struct stat st; int ovector[30]; char line[32768]; int line_no; FILE* fp; apr_pool_t* req_pool = range_request_pool(rr); apr_pool_t* lr_pool = range_request_lr_pool(rr); libcrange* lr = range_request_lr(rr); set* cache = libcrange_get_cache(lr, "nodescf:cluster_vips"); const char* vips_path = apr_psprintf(req_pool, "%s/%s/vips.cf", nodescf_path, cluster); vips* v; if (!cache) { cache = set_new(lr_pool, 0); libcrange_set_cache(lr, "nodescf:cluster_vips", cache); } if (stat(vips_path, &st) == -1) { range_request_warn_type(rr, "NOVIPS", cluster); return _empty_vips(rr); } v = set_get_data(cache, vips_path); if (!v) { v = apr_palloc(lr_pool, sizeof(struct vips)); apr_pool_create(&v->pool, lr_pool); v->vips = set_new(v->pool, 0); v->viphosts = set_new(v->pool, 0); v->mtime = st.st_mtime; set_add(cache, vips_path, v); } else { time_t cached_mtime = v->mtime; if (cached_mtime != st.st_mtime) { apr_pool_clear(v->pool); v->vips = set_new(v->pool, 0); v->viphosts = set_new(v->pool, 0); v->mtime = st.st_mtime; } else /* current cached copy is good */ return v; } /* create / update the current cached copy */ fp = fopen(vips_path, "r"); if (!fp) { range_request_warn_type(rr, "NOVIPS", cluster); return _empty_vips(rr); } if (!vips_re) { const char* error; vips_re = pcre_compile("^(\\S+)\\s+(\\S+)\\s+(\\S+)\\s*$", 0, &error, ovector, NULL); assert(vips_re); } line_no = 0; while (fgets(line, sizeof line, fp)) { int len; int count; char* p; 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", vips_path, 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; /* 68.142.248.161 as301000 eth0:1 */ count = pcre_exec(vips_re, NULL, line, len, 0, 0, ovector, 30); if (count == 4) { line[ovector[3]] = '\0'; line[ovector[5]] = '\0'; line[ovector[7]] = '\0'; set_add(v->vips, &line[ovector[2]], 0); set_add(v->viphosts, &line[ovector[4]], 0); } } fclose(fp); return v; }
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; }
range* rangefunc_group(range_request* rr, range** r) { range* ret; const char** members; int i, err; sqlite3* db; sqlite3_stmt* tag_stmt; sqlite3_stmt* all_nodes_stmt; apr_pool_t* pool = range_request_pool(rr); libcrange* lr = range_request_lr(rr); ret = range_new(rr); members = range_get_hostnames(pool, r[0]); if (!(db = libcrange_get_cache(lr, "sqlite:nodes"))) { const char* 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) { fprintf(stderr, "%s: %s\n", sqlite_db_path, sqlite3_errmsg(db)); return ret; } libcrange_set_cache(lr, "sqlite:nodes", db); } /* prepare our selects */ err = sqlite3_prepare(db, ALL_NODES_SQL, strlen(ALL_NODES_SQL), &all_nodes_stmt, NULL); if (err != SQLITE_OK) { fprintf(stderr, "%s: %s\n", ALL_NODES_SQL, sqlite3_errmsg(db)); abort(); } err = sqlite3_prepare(db, RANGE_FROM_TAGS, strlen(RANGE_FROM_TAGS), &tag_stmt, NULL); assert(err == SQLITE_OK); /* for each group */ for (i = 0; members[i]; ++i) { sqlite3_stmt* stmt; if (strcmp(members[i], "ALL") == 0) { stmt = all_nodes_stmt; } else { stmt = tag_stmt; /* bind the current group name */ sqlite3_bind_text(tag_stmt, 1, members[i], strlen(members[i]), SQLITE_STATIC); } while (sqlite3_step(stmt) == SQLITE_ROW) { range* this_group; const char* result = (const char*)sqlite3_column_text(stmt, 0); if (stmt == all_nodes_stmt) { range_add(ret, result); } else { this_group = do_range_expand(rr, result); set_union_inplace(ret->nodes, this_group->nodes); } } sqlite3_reset(stmt); } sqlite3_finalize(all_nodes_stmt); sqlite3_finalize(tag_stmt); return ret; }
/* 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; }