repoUUID RepoBSON::getUUIDField(const std::string &label) const{ repoUUID uuid; if (hasField(label)) { const mongo::BSONElement bse = getField(label); if (bse.type() == mongo::BSONType::BinData && (bse.binDataType() == mongo::bdtUUID || bse.binDataType() == mongo::newUUID)) { int len = static_cast<int>(bse.size() * sizeof(boost::uint8_t)); const char *binData = bse.binData(len); memcpy(uuid.data, binData, len); } else { repoError << "Field " << label << " is not of type UUID!"; uuid = generateUUID(); // failsafe } } else { repoError << "Field " << label << " does not exist!"; uuid = generateUUID(); // failsafe } return uuid; }
bool isUuidType(const mongo::BSONElement &elem) { if (elem.type() != mongo::BinData) return false; mongo::BinDataType binType = elem.binDataType(); return (binType == mongo::newUUID || binType == mongo::bdtUUID); }
Datum convert_element<int>(PG_FUNCTION_ARGS, const mongo::BSONElement e) { if(e.type() == mongo::NumberInt) { PG_RETURN_INT32(e._numberInt()); } else { throw convertion_error("int4"); } }
std::string MongoSchema::getType(mongo::BSONElement belem){ if(belem.isABSONObj()) { return "BSON"; }else if(belem.isSimpleType()){ // Simple Type: Number, String, Date, Bool or OID if(belem.isNumber()){ return "Number"; }else if(belem.type() == mongo::String){ return "String"; }else if(belem.type() == mongo::Date){ return "Date"; }else if(belem.type() == mongo::Bool){ return "Boolean"; }else{ return "Other"; } }else{ return "Unknown"; } }
Datum convert_element<std::string>(PG_FUNCTION_ARGS, const mongo::BSONElement e) { std::stringstream ss; switch(e.type()) { case mongo::String: case mongo::DBRef: case mongo::Symbol: return return_string(std::string(e.valuestr(), e.valuestrsize()-1)); case mongo::NumberDouble: ss << e._numberDouble(); break; case mongo::jstOID: ss << e.__oid().str(); break; case mongo::Bool: ss << std::boolalpha << e.boolean(); break; case mongo::Date: return return_string( to_iso_extended_string( boost::posix_time::ptime( boost::gregorian::date(1970, 1, 1), boost::posix_time::milliseconds(e.date().millis) ) ) ); case mongo::RegEx: ss << e.regex(); break; case mongo::NumberInt: ss << e._numberInt(); break; case mongo::NumberLong: ss << e._numberLong(); break; default: throw convertion_error("text"); } return return_string(ss.str()); }
Datum convert_element<int64>(PG_FUNCTION_ARGS, const mongo::BSONElement e) { switch(e.type()) { case mongo::NumberLong: PG_RETURN_INT64(e._numberLong()); // this conversion has to be imlicitly allowedm, otherwise defining object form json would be pain int the ass case mongo::NumberInt: PG_RETURN_INT64(static_cast<int64>(e._numberInt())); default: throw convertion_error("int8"); } }
bool GroupCache::Replicate(const mongo::BSONElement& id) { if (id.type() != 16) return true; acl::GroupID gid = id.Int(); try { SafeConnection conn; auto fields = BSON("gid" << 1 << "name" << 1); auto data = conn.QueryOne<GroupPair>("groups", QUERY("gid" << gid), &fields); if (data) { // group found, refresh cached data { std::lock_guard<std::mutex> lock(gidsMutex); gids[data->name] = data->gid; } { std::lock_guard<std::mutex> lock(namesMutex); names[data->gid] = data->name; } } else { // group not found, must be deleted, remove from cache std::lock(gidsMutex, namesMutex); std::lock_guard<std::mutex> gidsLock(gidsMutex, std::adopt_lock); std::lock_guard<std::mutex> namesLock(namesMutex, std::adopt_lock); auto it = names.find(gid); if (it != names.end()) { gids.erase(it->second); names.erase(it); } } } catch (const DBError&) { return false; } return true; }
bool UserCache::Replicate(const mongo::BSONElement& id) { if (id.type() != 16) return true; acl::UserID uid = id.Int(); updatedCallback(uid); try { SafeConnection conn; auto fields = BSON("uid" << 1 << "name" << 1 << "primary gid" << 1); auto data = conn.QueryOne<UserTriple>("users", QUERY("uid" << uid), &fields); if (data) { // user found, refresh cached data { std::lock_guard<std::mutex> lock(uidsMutex); uids[data->name] = data->uid; } { std::lock_guard<std::mutex> lock(namesMutex); names[data->uid] = data->name; } { std::lock_guard<std::mutex> lock(primaryGidsMutex); primaryGids[data->uid] = data->primaryGid; } auto masks = LookupIPMasks(conn, uid); { std::lock_guard<std::mutex> lock(ipMasksMutex); ipMasks[data->uid] = std::move(masks); } } else { // user not found, must be deleted, remove from cache { std::lock(uidsMutex, namesMutex); std::lock_guard<std::mutex> uidsLock(uidsMutex, std::adopt_lock); std::lock_guard<std::mutex> namesLock(namesMutex, std::adopt_lock); auto it = names.find(uid); if (it != names.end()) { uids.erase(it->second); names.erase(it); } } { std::lock_guard<std::mutex> lock(primaryGidsMutex); primaryGids.erase(uid); } { std::lock_guard<std::mutex> lock(ipMasksMutex); ipMasks.erase(uid); } } } catch (const DBError&) { return false; } return true; }
void buildJsonString(const mongo::BSONElement &elem,std::string &con, UUIDEncoding uuid, SupportedTimes tz) { switch (elem.type()) { case NumberDouble: { char dob[32] = {0}; sprintf(dob, "%f", elem.Double()); con.append(dob); } break; case String: { con.append(elem.valuestr(), elem.valuestrsize() - 1); } break; case Object: { buildJsonString(elem.Obj(), con, uuid, tz); } break; case Array: { buildJsonString(elem.Obj(), con, uuid, tz); } break; case BinData: { mongo::BinDataType binType = elem.binDataType(); if (binType == mongo::newUUID || binType == mongo::bdtUUID) { std::string uu = HexUtils::formatUuid(elem, uuid); con.append(uu); break; } con.append("<binary>"); } break; case Undefined: con.append("<undefined>"); break; case jstOID: { std::string idValue = elem.OID().toString(); char buff[256] = {0}; sprintf(buff, "ObjectId(\"%s\")", idValue.c_str()); con.append(buff); } break; case Bool: con.append(elem.Bool() ? "true" : "false"); break; case Date: { long long ms = (long long) elem.Date().millis; boost::posix_time::ptime epoch(boost::gregorian::date(1970,1,1)); boost::posix_time::time_duration diff = boost::posix_time::millisec(ms); boost::posix_time::ptime time = epoch + diff; std::string date = miutil::isotimeString(time,false,tz==LocalTime); con.append(date); break; } case jstNULL: con.append("<null>"); break; case RegEx: { con.append("/" + std::string(elem.regex()) + "/"); for ( const char *f = elem.regexFlags(); *f; ++f ) { switch ( *f ) { case 'g': case 'i': case 'm': con+=*f; default: break; } } } break; case DBRef: break; case Code: con.append(elem._asCode()); break; case Symbol: con.append(elem.valuestr(), elem.valuestrsize() - 1); break; case CodeWScope: { mongo::BSONObj scope = elem.codeWScopeObject(); if (!scope.isEmpty() ) { con.append(elem._asCode()); break; } } break; case NumberInt: { char num[16]={0}; sprintf(num,"%d",elem.Int()); con.append(num); break; } case Timestamp: { Date_t date = elem.timestampTime(); unsigned long long millis = date.millis; if ((long long)millis >= 0 && ((long long)millis/1000) < (std::numeric_limits<time_t>::max)()) { con.append(date.toString()); } break; } case NumberLong: { char num[32]={0}; sprintf(num,"%lld",elem.Long()); con.append(num); break; } default: con.append("<unsupported>"); break; } }
bool isSimpleType(const mongo::BSONElement &elem) { return isSimpleType(elem.type()); }
bool isDocument(const mongo::BSONElement &elem) { return isDocument(elem.type()); }
bool isArray(const mongo::BSONElement &elem) { return isArray(elem.type()); }