void BSONOutputStream::writeBSON(const BSONObj& bson) { Logger* log = getLogger(NULL); if (log->isDebug()) log->debug("BSONOutputStream::writeBSON bson elements: %d", bson.length()); _outputStream->writeLong(bson.length()); for (std::map<t_keytype, BSONContent* >::const_iterator i = bson.begin(); i != bson.end(); i++) { t_keytype key = i->first; if (log->isDebug()) log->debug("BSONOutputStream::writeBSON name: %s", key.c_str()); _outputStream->writeString(key); BSONContent* cont = i->second; // If the type is PTRCHAR_TYPE change it to string_type, to remove this type in future _outputStream->writeLong(cont->type() != PTRCHAR_TYPE? cont->type(): STRING_TYPE); char* text; BSONObj* inner; switch (cont->type()) { case BSON_TYPE: inner = (BSONObj*)cont->_element; writeBSON(*inner); break; case INT_TYPE: _outputStream->writeInt(*((int*)cont->_element)); break; case LONG_TYPE: _outputStream->writeLong(*((long*)cont->_element)); break; case DOUBLE_TYPE: _outputStream->writeDoubleIEEE(*((double*)cont->_element)); break; case PTRCHAR_TYPE: text = (char*)cont->_element; _outputStream->writeString(std::string(text)); break; case STRING_TYPE: { string* str = (string*)cont->_element; _outputStream->writeString(*str); break; } case BSONARRAY_TYPE: { BSONArrayObj* array = (BSONArrayObj*)cont->_element; writeBSONArray(array); break; } } } delete log; }
BSONContent* BSONObj::getContent(std::string key, BSONTYPE ttype) const { BSONContent* content = getContent(key); if (content != NULL) { if (content->type() != ttype) { throw "type does not match"; } } return content; }
BSONArrayObj* BSONObj::getBSONArray(std::string key) const throw(BSONException) { BSONContent* content = getContent(key); if ((content != NULL) && (content->type() == BSONARRAY_TYPE)) { BSONContentBSONArray* bbson = (BSONContentBSONArray*)content; return *bbson; } else { throw BSONException(format("key not found %s", key.c_str()).c_str()); } }
__int64 BSONObj::getLong(std::string key) const throw(BSONException) { BSONContent* content = getContent(key); if ((content != NULL) && (content->type() == LONG_TYPE)) { BSONContentLong* blong = (BSONContentLong*)content; return *blong; } else { throw BSONException(format("key not found %s", key.c_str()).c_str()); } }
double BSONObj::getDouble(std::string key) const throw(BSONException) { BSONContent* content = getContent(key); if ((content != NULL) && (content->type() == DOUBLE_TYPE)) { BSONContentDouble* bdouble = (BSONContentDouble*)content; return *bdouble; } else { throw BSONException(format("key not found %s", key.c_str()).c_str()); } }
__int32 BSONObj::getInt(std::string key) const throw(BSONException) { BSONContent* content = getContent(key); if ((content != NULL) && (content->type() == INT_TYPE)) { BSONContentInt* bint = (BSONContentInt*)content; return *bint; } else { throw BSONException(format("key not found %s", key.c_str()).c_str()); } }
bool BSONObj::getBoolean(std::string key) const throw(BSONException) { BSONContent* content = getContent(key); if ((content != NULL) && (content->type() == BOOL_TYPE)) { BSONContentBoolean* bb = (BSONContentBoolean*)content; return *bb; } else { throw BSONException(format("key not found %s", key.c_str()).c_str()); } }
const djondb::string BSONObj::getDJString(std::string key) const throw(BSONException) { BSONContent* content = getContent(key); if ((content != NULL) && (content->type() == PTRCHAR_TYPE)) { BSONContentString* bstring = (BSONContentString*)content; djondb::string s = *bstring; return s; } else { throw BSONException(format("key not found %s", key.c_str()).c_str()); } }
BSONTYPE BSONObj::type(std::string key) const { BSONContent* content = NULL; for (std::map<std::string, BSONContent* >::const_iterator it = _elements.begin(); it != _elements.end(); it++) { std::string itKey = it->first; if (itKey.compare(key) == 0) { content = it->second; break; } } if (content != NULL) { return content->type(); } else { return UNKNOWN_TYPE; } }
BSONObj::BSONObj(const BSONObj& orig) { for (std::map<std::string, BSONContent* >::const_iterator i = orig._elements.begin(); i != orig._elements.end(); i++) { std::string key = i->first; BSONContent* origContent = i->second; BSONContent* content; switch (origContent->type()) { case BOOL_TYPE: { content = new BSONContentBoolean(*(BSONContentBoolean*)origContent); break; } case INT_TYPE: { content = new BSONContentInt(*(BSONContentInt*)origContent); break; } case LONG_TYPE: { content = new BSONContentLong(*(BSONContentLong*)origContent); break; } case DOUBLE_TYPE: { content = new BSONContentDouble(*(BSONContentDouble*)origContent); break; } case PTRCHAR_TYPE: { content = new BSONContentString(*(BSONContentString*)origContent); break; } case BSON_TYPE: { content = new BSONContentBSON(*(BSONContentBSON*)origContent); break; } case BSONARRAY_TYPE: { content = new BSONContentBSONArray(*(BSONContentBSONArray*)origContent); break; } } this->_elements.insert(pair<std::string, BSONContent* >(i->first, content)); } if (orig._cBSON != NULL) { this->_cBSON = strcpy(orig._cBSON); } else { this->_cBSON = NULL; } }
BSONContent* BSONObj::getXpath(const std::string& xpath) const { __int32 posDot = xpath.find('.'); BSONContent* result = NULL; if (posDot == string::npos) { result = getContent(xpath); } else { std::string path = xpath.substr(0, posDot); result = getContent(path); if ((result != NULL) && (result->type() == BSON_TYPE)) { BSONContentBSON* bcontent = (BSONContentBSON*)result; BSONObj* inner = (BSONObj*)*bcontent; result = inner->getXpath(xpath.substr(posDot + 1)); } } if (result != NULL) { return result->clone(); } else { return NULL; } }
BSONObj* BSONObj::select(const char* sel) const { std::set<std::string> columns = bson_splitSelect(sel); bool include_all = (strcmp(sel, "*") == 0); BSONObj* result = new BSONObj(); for (std::map<std::string, BSONContent* >::const_iterator i = this->_elements.begin(); i != this->_elements.end(); i++) { std::string key = i->first; if (include_all || (columns.find(key) != columns.end())) { BSONContent* origContent = i->second; switch (origContent->type()) { case BSON_TYPE: { BSONContentBSON* bbson = (BSONContentBSON*)origContent; BSONObj* inner = (BSONObj*)*bbson; if (!include_all) { char* subselect = bson_subselect(sel, key.c_str()); BSONObj* innerSubSelect = inner->select(subselect); result->add(key, *innerSubSelect); delete innerSubSelect; } else { result->add(key, *inner); } break; } case BSONARRAY_TYPE: { BSONContentBSONArray* bbsonarray = (BSONContentBSONArray*)origContent; BSONArrayObj* innerArray = (BSONArrayObj*)*bbsonarray; if (!include_all) { char* subselect = bson_subselect(sel, key.c_str()); BSONArrayObj* innerSubArray = innerArray->select(subselect); result->add(key, *innerSubArray); delete innerSubArray; } else { result->add(key, *innerArray); } break; } case BOOL_TYPE: { BSONContentBoolean* bb = (BSONContentBoolean*)origContent; bool val = *bb; result->add(key, val); break; } case INT_TYPE: { BSONContentInt* bint = (BSONContentInt*)origContent; __int32 val = *bint; result->add(key, val); break; } case LONG_TYPE: { BSONContentLong* blong = (BSONContentLong*)origContent; __int64 val = *blong; result->add(key, val); break; } case DOUBLE_TYPE: { BSONContentDouble* bdouble = (BSONContentDouble*)origContent; double val = *bdouble; result->add(key, val); break; } case PTRCHAR_TYPE: case STRING_TYPE: { BSONContentString* bstring = (BSONContentString*)origContent; djondb::string str = *bstring; const char* val = str.c_str(); __int32 len = str.length(); result->add(key, const_cast<char*>(val), len); break; } } } } return result; }
bool BSONObj::operator !=(const BSONObj& obj) const { if (this->has("_id") && obj.has("_id")) { BSONContent* idThis = this->getContent("_id"); BSONContent* idOther = obj.getContent("_id"); return (*idThis != *idOther); } // Element count if (this->length() != obj.length()) { return true; } for (BSONObj::const_iterator it = this->begin(); it != this->end(); it++) { std::string key = it->first; BSONContent* content = it->second; BSONContent* other = obj.getContent(key); if (other == NULL) { return true; } if (content->type() != other->type()) { return true; } bool result; switch (content->type()) { case BOOL_TYPE: { result = *((BSONContentBoolean*)content) != *((BSONContentBoolean*)other); break; } case INT_TYPE: { result = *((BSONContentInt*)content) != *((BSONContentInt*)other); break; } case DOUBLE_TYPE: { result = *((BSONContentDouble*)content) != *((BSONContentDouble*)other); break; } case LONG64_TYPE: case LONG_TYPE: { result = *((BSONContentLong*)content) != *((BSONContentLong*)other); break; } case PTRCHAR_TYPE: case STRING_TYPE: { result = *((BSONContentString*)content) != *((BSONContentString*)other); break; } case BSON_TYPE: { result = *((BSONContentBSON*)content) != *((BSONContentBSON*)other); break; } case BSONARRAY_TYPE: { result = *((BSONContentBSONArray*)content) != *((BSONContentBSONArray*)other); break; } case NULL_TYPE: { result = true; break; } case UNKNOWN_TYPE: default: { result = *((BSONContentInt*)content) != *((BSONContentInt*)other); break; } } if (result) { return result; } } return false; }
char* BSONObj::toChar() { // if the toChar was already calculated before use it if (_cBSON != NULL) { return strcpy(_cBSON); } Logger* log = getLogger(NULL); char* result = (char*)malloc(MAX_BSONOBJ_BUFFER); memset(result, 0, MAX_BSONOBJ_BUFFER); __int32 pos = 0; result[0] = '{'; pos += 1; bool first = true; for (std::map<std::string, BSONContent* >::const_iterator i = _elements.begin(); i != _elements.end(); i++) { if (!first) { result[pos] = ','; pos++; } first = false; BSONContent* content = i->second; std::string key = i->first; sprintf(result + pos, " \"%s\" : ", key.c_str()); pos += key.length() + 6; //ss << "\"" << key << "\" :"; char* chr; const char* cstr; switch (content->type()) { case BSON_TYPE: { BSONContentBSON* bbson = (BSONContentBSON*)content; BSONObj* bson = (BSONObj*)*bbson; char* chrbson = bson->toChar(); sprintf(result + pos, "%s", chrbson); free(chrbson); break; } case BSONARRAY_TYPE: { BSONContentBSONArray* bbsonarray = (BSONContentBSONArray*)content; BSONArrayObj* bsonarray = (BSONArrayObj*)*bbsonarray; char* chrbsonarray = bsonarray->toChar(); sprintf(result + pos, "%s", chrbsonarray); free(chrbsonarray); break; } case BOOL_TYPE: { BSONContentBoolean* bb = (BSONContentBoolean*)content; sprintf(result + pos, "%s", ((bool)*bb?"true": "false")); break; } case INT_TYPE: { BSONContentInt* bint = (BSONContentInt*)content; sprintf(result + pos, "%d", (__int32)*bint); break; } case LONG_TYPE: { BSONContentLong* blong = (BSONContentLong*)content; sprintf(result + pos, "%ld", (__int64)*blong); break; } case DOUBLE_TYPE: { BSONContentDouble* bdouble = (BSONContentDouble*)content; sprintf(result + pos, "%f", (double)*bdouble); break; } case STRING_TYPE: case PTRCHAR_TYPE: { BSONContentString* bstring = (BSONContentString*)content; djondb::string s = *bstring; sprintf(result + pos, "\"%.*s\"", s.length(), s.c_str()); break; } } pos = strlen(result); assert(pos < MAX_BSONOBJ_BUFFER); } result[pos] = '}'; result[pos+1] = 0; pos++; __int32 len = strlen(result); // Saves the value to cache the calculated value _cBSON = result; char* cresult = strcpy(result); if (log->isDebug()) log->debug("toChar result: %s", cresult); return cresult; }
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; }