void FileIndex::indexTree(const std::string& root) { indexDirectory(root); DIR* dp = opendir(root.c_str()); dirent* ep; if ( dp == NULL ) { throw std::runtime_error("Unable to open directory: " + root); } while( (ep = readdir(dp)) ) { std::string filepath = root +"/"+ ep->d_name; bool isDirectory = false; if (ep->d_type != DT_UNKNOWN) { isDirectory = ep->d_type == DT_DIR; } else { struct stat filedata; if (stat(filepath.c_str(), &filedata) == 0) { isDirectory = S_ISDIR(filedata.st_mode); } } if (isDirectory && ep->d_name[0] != '.') { indexTree(filepath); } } closedir(dp); }
Status QueryPlanner::cacheDataFromTaggedTree(const MatchExpression* const taggedTree, const vector<IndexEntry>& relevantIndices, PlanCacheIndexTree** out) { // On any early return, the out-parameter must contain NULL. *out = NULL; if (NULL == taggedTree) { return Status(ErrorCodes::BadValue, "Cannot produce cache data: tree is NULL."); } auto_ptr<PlanCacheIndexTree> indexTree(new PlanCacheIndexTree()); if (NULL != taggedTree->getTag()) { IndexTag* itag = static_cast<IndexTag*>(taggedTree->getTag()); if (itag->index >= relevantIndices.size()) { mongoutils::str::stream ss; ss << "Index number is " << itag->index << " but there are only " << relevantIndices.size() << " relevant indices."; return Status(ErrorCodes::BadValue, ss); } // Make sure not to cache solutions which use '2d' indices. // A 2d index that doesn't wrap on one query may wrap on another, so we have to // check that the index is OK with the predicate. The only thing we have to do // this for is 2d. For now it's easier to move ahead if we don't cache 2d. // // TODO: revisit with a post-cached-index-assignment compatibility check if (is2DIndex(relevantIndices[itag->index].keyPattern)) { return Status(ErrorCodes::BadValue, "can't cache '2d' index"); } IndexEntry* ientry = new IndexEntry(relevantIndices[itag->index]); indexTree->entry.reset(ientry); indexTree->index_pos = itag->pos; } for (size_t i = 0; i < taggedTree->numChildren(); ++i) { MatchExpression* taggedChild = taggedTree->getChild(i); PlanCacheIndexTree* indexTreeChild; Status s = cacheDataFromTaggedTree(taggedChild, relevantIndices, &indexTreeChild); if (!s.isOK()) { return s; } indexTree->children.push_back(indexTreeChild); } *out = indexTree.release(); return Status::OK(); }