void testCopyBSON() { cout << "testCopyBSON" << endl; BSONObj* objOrig = new BSONObj(); // Add in objOrig->add("int", 1); objOrig->add("string", (char*)"test"); objOrig->add("long", (__int64)1L); objOrig->add("double", 1.1); BSONObj rel; rel.add("innertext", (char*)"inner text"); objOrig->add("rel1", rel); BSONArrayObj array; BSONObj b1; b1.add("b1", "test"); array.add(b1); BSONObj b2; b2.add("b1", "test2"); array.add(b2); objOrig->add("array", array); BSONObj* obj = new BSONObj(*objOrig); delete objOrig; objOrig = NULL; TEST_ASSERT(obj->has("int")); TEST_ASSERT(obj->getInt("int") == 1); TEST_ASSERT(strcmp(obj->getString("string"), "test") == 0); TEST_ASSERT(obj->has("long")); TEST_ASSERT(obj->getLong("long") == 1L); TEST_ASSERT(obj->has("double")); TEST_ASSERT(obj->getDouble("double") == 1.1); BSONObj* temp = obj->getBSON("rel1"); TEST_ASSERT(temp != NULL); TEST_ASSERT(strcmp(obj->getBSON("rel1")->getString("innertext"), "inner text") == 0); TEST_ASSERT(obj->getBSONArray("array") != NULL); BSONArrayObj* arrayR = obj->getBSONArray("array"); TEST_ASSERT(arrayR != NULL); TEST_ASSERT(arrayR->length() == 2); BSONObj* el1 = arrayR->get(0); TEST_ASSERT(el1 != NULL); BSONObj* el2 = arrayR->get(1); TEST_ASSERT(el2 != NULL); delete obj; }
BSONArrayObj* DBController::find(const char* db, const char* ns, const char* select, const char* filter, const BSONObj* options) throw(ParseException) { if (_logger->isDebug()) _logger->debug(2, "DBController::find db: %s, ns: %s, select: %s, filter: %s", db, ns, select, filter); BSONArrayObj* result; FilterParser* parser = FilterParser::parse(filter); std::set<std::string> tokens = parser->tokens(); if (IndexFactory::indexFactory.containsIndex(db, ns, tokens)) { IndexAlgorithm* impl = IndexFactory::indexFactory.index(db, ns, tokens); std::list<Index*> elements = impl->find(parser); std::string filedir = _dataDir + db; filedir = filedir + FILESEPARATOR; std::stringstream ss; ss << filedir << ns << ".dat"; std::string filename = ss.str(); result = new BSONArrayObj(); FileInputStream* fis = new FileInputStream(filename.c_str(), "rb"); DBFileInputStream* dbStream = new DBFileInputStream(fis); BSONInputStream* bis = new BSONInputStream(dbStream); for (std::list<Index*>::iterator it = elements.begin(); it != elements.end(); it++) { Index* index = *it; long posData = index->posData; dbStream->seek(posData); BSONObj* obj = bis->readBSON(select); result->add(*obj); delete obj; } delete bis; delete dbStream; } else { result = findFullScan(db, ns, select, parser, options); } delete parser; return result; }
BSONArrayObj* BSONParser::parseArray(const char* chrs, __int32& pos) { BSONArrayObj* result = NULL; while (chrs[pos] == ' ') { pos++; } if (chrs[pos] != '[') { // error } else { result = new BSONArrayObj(); } while ((pos < strlen(chrs)) && (chrs[pos] != ']')) { while ((pos < strlen(chrs)) && (chrs[pos] != ']') && (chrs[pos] != '{')) pos++; if (chrs[pos] == '{') { BSONObj* bson = parseBSON(chrs, pos); result->add(*bson); delete bson; } } return result; }
void testBSON() { cout << "testBSON" << endl; BSONObj* obj = new BSONObj(); // Add in obj->add("int", 1); obj->add("string", (const char*)"test"); obj->add("long", (__int64) 10000000000L); obj->add("double", 1.1); BSONObj rel; rel.add("innertext", (char*)"inner text"); obj->add("rel1", rel); BSONArrayObj array; BSONObj b1; b1.add("b1", "test"); array.add(b1); BSONObj b2; b2.add("b1", "test2"); array.add(b2); obj->add("array", array); TEST_ASSERT(obj->has("int")); TEST_ASSERT(obj->getInt("int") == 1); TEST_ASSERT(strcmp(obj->getString("string"), "test") == 0); TEST_ASSERT(obj->has("long")); cout << "long: " << obj->getLong("long") << endl; TEST_ASSERT(obj->getLong("long") == 10000000000L); TEST_ASSERT(obj->has("double")); TEST_ASSERT(obj->getDouble("double") == 1.1); TEST_ASSERT(obj->has("rel1")); TEST_ASSERT(strcmp(obj->getBSON("rel1")->getString("innertext"), "inner text") == 0); TEST_ASSERT(obj->has("array")); BSONArrayObj* arrayR = obj->getBSONArray("array"); TEST_ASSERT(arrayR != NULL); TEST_ASSERT(arrayR->length() == 2); BSONObj* el1 = arrayR->get(0); TEST_ASSERT(el1 != NULL); BSONObj* el2 = arrayR->get(1); TEST_ASSERT(el2 != NULL); // test a non existant attribute try { obj->getLong("xx"); TEST_FAIL("The getLong should throw an exception"); } catch (BSONException e) { } try { obj->getString("xxx"); TEST_FAIL("The getString should throw an exception"); } catch (BSONException e) { } delete obj; }
BSONArrayObj* DBController::findFullScan(const char* db, const char* ns, const char* select, FilterParser* parser, const BSONObj* options) throw(ParseException) { if (_logger->isDebug()) _logger->debug(2, "DBController::findFullScan with parser db: %s, ns: %s", db, ns); std::string filedir = _dataDir + db; filedir = filedir + FILESEPARATOR; std::stringstream ss; ss << filedir << ns << ".dat"; std::string filename = ss.str(); // Execute open on streammanager, just to check that the file was alrady opened StreamManager::getStreamManager()->open(db, ns, INDEX_FTYPE); // Execute open on streammanager, just to check that the file was alrady opened StreamManager::getStreamManager()->open(db, ns, DATA_FTYPE); //FileInputStream* fis = new FileInputStream(filename.c_str(), "rb"); MMapInputStream* mmis = new MMapInputStream(filename.c_str(), 0); DBFileInputStream* dbStream = new DBFileInputStream(mmis); BSONArrayObj* result = new BSONArrayObj(); BSONInputStream* bis = new BSONInputStream(dbStream); std::set<std::string> tokens = parser->xpathTokens(); std::string filterSelect; if ((strcmp(select, "*") != 0) && (tokens.size() > 0)) { // this will reserve enough space to concat the filter tokens filterSelect.reserve(tokens.size() * 100); filterSelect.append("$'_status'"); for (std::set<std::string>::iterator i = tokens.begin(); i != tokens.end(); i++) { std::string token = *i; filterSelect.append(", "); filterSelect.append("$'"); filterSelect.append(token); filterSelect.append("'"); } } else { filterSelect = "*"; } mmis->seek(29); BSONBufferedObj* obj = NULL; __int64 maxResults = 3000; if ((options != NULL) && options->has("limit")) { BSONContent* content = options->getContent("limit"); if (content->type() == INT_TYPE) { maxResults = options->getInt("limit"); } else if (content->type() == LONG_TYPE) { maxResults = options->getLong("limit"); } } else { std::string smax = getSetting("max_results"); if (smax.length() > 0) { #ifdef WINDOWS maxResults = _atoi64(smax.c_str()); #else maxResults = atoll(smax.c_str()); #endif } } __int64 count = 0; while (!mmis->eof() && (count < maxResults)) { if (obj == NULL) { obj = new BSONBufferedObj(mmis->pointer(), mmis->length() - mmis->currentPos()); } else { obj->reset(mmis->pointer(), mmis->length() - mmis->currentPos()); } mmis->seek(mmis->currentPos() + obj->bufferLength()); // Only "active" Records if (obj->getInt("_status") == 1) { bool match = false; ExpressionResult* expresult = parser->eval(*obj); if (expresult->type() == ExpressionResult::RT_BOOLEAN) { match = *expresult; } delete expresult; if (match) { BSONObj* objSubselect = obj->select(select); result->add(*objSubselect); delete objSubselect; count++; } } } if (obj != NULL) delete obj; delete bis; dbStream->close(); delete dbStream; return result; }