/** * Converts a path to a simple conjunctive query. * * @param path The (not necessarily canonical) path to be parsed. * @returns A pointer to a tree structure representing the query, or NULL if an * error occurred. If an error occurs, \c errno is set appropriately. */ qelem *path_to_query(const char *path) { if (!path) return NULL; char *dup = get_canonical_path(path); DEBUG("Canonical path: \"%s\"", path); if (!dup || errno) { DEBUG("Error in get_canonical_path()"); if (dup) ifree(dup); errno=ENOENT; return NULL; } char *tmp = dup; qelem *qroot=NULL; /* remove leading slash characters */ while (*tmp && *tmp=='/') tmp++; /* If we have a zero-length path, then that matches any tag */ if (!*tmp) { DEBUG("Top-level ISANY"); qroot = _qtree_make_isany(); } else { int res = strsplitmap(tmp, '/', _path_to_query_proc, (unsigned long)&qroot); if (res==0) { DEBUG("Success"); } else if (res==-ENOENT) { DEBUG("A component of the path does not exist"); qtree_free(&qroot, 1); ifree(dup); errno=ENOENT; return NULL; } else { DEBUG("Problem with strsplitmap"); qtree_free(&qroot, 1); ifree(dup); errno=-res; return NULL; } if (_qtree_contains(qroot, QUERY_IS_INODE) && !query_inode_count(qroot)) { /* cannot find that inode with the query */ DEBUG("Could not find the given file"); qtree_free(&qroot, 1); ifree(dup); errno=ENOENT; return NULL; } } DEBUG("Dumping tree..."); _qtree_dump(qroot, 0); DEBUG("Tree dump done."); ifree(dup); return qroot; }
/** * Recursively free a query tree. * * @param root The address of the root element to be freed. * @param free_tags If true, will also free tags (if non-null). */ void qtree_free(qelem **root, int free_tags) { /* trivial cases */ if (!root) return; if (!*root) return; if (free_tags && (*root)->tag) { ifree((*root)->tag); } qtree_free(&((*root)->next[0]), free_tags); qtree_free(&((*root)->next[1]), free_tags); ifree(*root); *root=NULL; }
static void generate_grid(DATA *d, double samplespacing, int neighbourhood) { DPOINT pt; int i, j, n; d->n_list = d->n_sel = 0; qtree_free(d->qtree_root); d->qtree_root = NULL; pt.z = 0.0; pt.attr = 0.0; n = floor(sqrt(neighbourhood)) / 2 + 1; d->maxX = d->maxY = n * samplespacing; d->minX = d->minY = -n * samplespacing; gl_split = 4 * n * n; for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { pt.x = (i + 0.5) * samplespacing; pt.y = (j + 0.5) * samplespacing; push_point(d, &pt); /* NE */ pt.y *= -1; push_point(d, &pt); /* SE */ pt.x *= -1; push_point(d, &pt); /* SW */ pt.y *= -1; push_point(d, &pt); /* NE */ } } d->sel_max = neighbourhood; return; }
/** * Small procedure to create a basic conjunctive query tree from a tokenised path. * * @param str Incoming path token. * @param data A qelem** in disguise that should be updated. * @return Always zero. */ static int _path_to_query_proc(const char *str, unsigned long data) { DEBUG("str: \"%s\"", str); qelem *newnode=NULL; qelem **qroot=(qelem**)data; int is_tag = get_tag(str); unsigned long path_hash = hash_path(str); int is_file = have_file_by_hash(path_hash); if (is_tag) { tdata dblock; if (tree_read(is_tag, (tblock*)&dblock)) { PMSG(LOG_ERR, "I/O error reading block\n"); qtree_free(qroot, 1); return -EIO; } if (dblock.flags & DATA_FLAGS_NOSUB) { newnode=_qtree_make_is_nosub(str); } else { newnode=_qtree_make_is(str); } } else if (is_file) { newnode=_qtree_make_is_inode(path_hash); } else { DEBUG("Tag \"%s\" does not exist"); qtree_free(qroot, 1); return -ENOENT; } if (*qroot) { *qroot=_qtree_make_and(newnode, *qroot); } else { *qroot=newnode; } return 0; }
void qtree_free(QTREE_NODE *node) { /* * If a push or search fails, you might want to consider getting rid of * whole tree and default to exhaustive search. (SJ) * [If you ever get so far, exhaustive search will take * a nearly infinite amount of time. Instead, tweek gl_split. --EJP] */ int i; if (node == NULL) return; if (!is_leaf(node)) { for (i = 0; i < N_NODES(node); i++) qtree_free(node->u.node[i]); efree(node->u.node); } else efree(node->u.list); efree(node); return; }
void free_data(DATA *d) { int i; assert(d); if (DEBUG_FORCE) /* let atexit(qtree_print) do it's job... */ return; if (d->P_base) { /* segmented: */ efree(d->P_base); if (d->n_X && d->X_base) efree(d->X_base); } else { /* non-segmented */ if (d->list) /* CW at all MV on output both P_base and d_list are 0 */ for (i = d->n_list - 1; i >= 0; i--) pop_point(d, i); } if (d->sel != NULL && d->sel != d->list) efree(d->sel); if (d->list) efree(d->list); if (d->colX) efree(d->colX); if (d->qtree_root != NULL) qtree_free(d->qtree_root); if (d->lm) free_lm(d->lm); if (d->glm) free_glm(d->glm); if (d->grid) free_data_gridmap(d->grid); if (d->point_ids) for (i = d->n_list - 1; i >= 0; i--) efree(d->point_ids[i]); efree(d); return; }