static void collect_data(int options) { int i; g_max_hits = get_max_hits(); DBG("pike: collect_data"); // maybe try_lock first and than do the rest? for(i=0;i<MAX_IP_BRANCHES;i++) { if (get_tree_branch(i)==0) continue; DBG("pike: collect_data: branch %d", i); lock_tree_branch(i); if (get_tree_branch(i)) traverse_subtree( get_tree_branch(i), 0, options ); unlock_tree_branch(i); } }
int traverse(const char path[], subtree_visitor visitor, void *param) { /* Duplication with traverse_subtree(), but this way traverse_subtree() can * use information from dirent structure to save some operations. */ if(is_symlink(path)) { /* Tread symbolic links to directories as files as well. */ return visitor(path, VA_FILE, param); } else if(is_dir(path)) { return traverse_subtree(path, visitor, param); } else { return visitor(path, VA_FILE, param); } }
static void traverse_subtree( struct ip_node *node, int depth, int options ) { static unsigned char ip_addr[MAX_DEPTH]; struct ip_node *foo; DBG("pike:rpc traverse_subtree, depth: %d, byte: %d", depth, node->byte); assert( depth < MAX_DEPTH ); ip_addr[depth] = node->byte; if ( node->flags & NODE_IPLEAF_FLAG ) { int ns = node_status(node); DBG("pike:traverse_subtree: options: 0x%02x, node status: 0x%02x", options, ns); /* add to the result list if it has requested status */ switch (options) { case NODE_STATUS_HOT: if ( ns & NODE_STATUS_HOT ) pike_top_add_entry(ip_addr, depth+1, node->leaf_hits, node->hits, node->expires - get_ticks(), ns); break; case NODE_STATUS_ALL: pike_top_add_entry(ip_addr, depth+1, node->leaf_hits, node->hits, node->expires - get_ticks(), ns); break; } } else if (! node->kids) { /* TODO non IP leaf of ip_tree - it is possible to report WARM nodes here */ /* if ( options == ns ) pike_top_add_entry(ip_addr, depth+1, node->leaf_hits, node->hits, node->expires - get_ticks(), ns); */ } else { /* not a any kind of leaf - inner node */ DBG("pike:rpc traverse_subtree, not IP leaf, depth: %d, ip: %d.%d.%d.%d hits[%d,%d], expires: %d", depth, ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3], node->hits[0], node->hits[1], node->expires - get_ticks()); } foo = node->kids; while (foo) { traverse_subtree( foo, depth + 1, options ); foo = foo->next; } }
/* A generic subtree traversing. Returns zero on success, otherwise non-zero is * returned. */ static int traverse_subtree(const char path[], subtree_visitor visitor, void *param) { DIR *dir; struct dirent *d; int result; VisitResult enter_result; dir = os_opendir(path); if(dir == NULL) { return 1; } enter_result = visitor(path, VA_DIR_ENTER, param); if(enter_result == VR_ERROR) { (void)os_closedir(dir); return 1; } result = 0; while((d = os_readdir(dir)) != NULL) { char *full_path; if(is_builtin_dir(d->d_name)) { continue; } full_path = join_paths(path, d->d_name); if(entry_is_link(full_path, d)) { /* Treat symbolic links to directories as files as well. */ result = visitor(full_path, VA_FILE, param); } else if(entry_is_dir(full_path, d)) { result = traverse_subtree(full_path, visitor, param); } else { result = visitor(full_path, VA_FILE, param); } free(full_path); if(result != 0) { break; } } (void)os_closedir(dir); if(result == 0 && enter_result != VR_SKIP_DIR_LEAVE && enter_result != VR_CANCELLED) { result = visitor(path, VA_DIR_LEAVE, param); } return result; }