mxArray *GetTick(mxArray *inst, mxArray *start, mxArray *end) { mxArray *result; const char *field_names[] = {"tradingday", "time", "instrument", "o", "h", "l", "c", "v", "i", "a1", "b1", "av1", "bv1"}; string instrument = mxArrayToString(inst); int st = mxGetScalar(start); int et = mxGetScalar(end); auto_ptr<DBClientCursor> cursor; BSONObjBuilder b; BSONObjBuilder timePeriod; b.append("InstrumentID", instrument); timePeriod.appendDate("$gte",( (st - 719529) * 24LL)* 60LL * 60LL * 1000LL); timePeriod.appendDate("$lte", ( (et - 719529 + 1) * 24LL) * 60LL * 60LL * 1000LL); b.append("UpdateTime", timePeriod.obj()); BSONObj qry = b.obj(); cursor = mCon->query(string("MarketData.") + collection, qry); int size = cursor->itcount(); // mexPrintf("数据长度%d, collection为%s\n", size, collection.c_str()); mwSize dims[2] = {1, size}; result = mxCreateStructArray(2, dims, sizeof(field_names)/sizeof(*field_names), field_names); cursor = mCon->query(string("MarketData.") + collection, qry); BSONObj p; int i = size - 1; while(cursor->more()) { p = cursor->next(); tm buf; //trun into peking time; Date_t pkTime = Date_t(p["UpdateTime"].Date().millis + 8 * 3600000LL); double time = pkTime.millis%1000 / 100 / 100000.0; pkTime.toTm(&buf); int day = (buf.tm_year + 1900) * 10000 + (buf.tm_mon + 1) * 100 + buf.tm_mday; time = time + buf.tm_hour + buf.tm_min / 100.0 + buf.tm_sec / 10000.0; mxSetField(result, i, "tradingday", mxCreateDoubleScalar(day)); mxSetField(result, i, "time", mxCreateDoubleScalar(time)); mxSetField(result, i, "instrument", mxCreateString(instrument.c_str())); mxSetField(result, i, "o", mxCreateDoubleScalar( p["OpenPrice"].Double() )); mxSetField(result, i, "h", mxCreateDoubleScalar(p["HighestPrice"].Double())); mxSetField(result, i, "l", mxCreateDoubleScalar(p["LowestPrice"].Double())); mxSetField(result, i, "c", mxCreateDoubleScalar(p["LastPrice"].Double())); mxSetField(result, i, "v", mxCreateDoubleScalar(p["Volume"].Int())); mxSetField(result, i, "i", mxCreateDoubleScalar(p["OpenInterest"].Double())); mxSetField(result, i, "a1", mxCreateDoubleScalar(p["AskPrice1"].Double())); mxSetField(result, i, "b1", mxCreateDoubleScalar(p["BidPrice1"].Double())); mxSetField(result, i, "av1", mxCreateDoubleScalar(p["AskVolume1"].Int())); mxSetField(result, i, "bv1", mxCreateDoubleScalar(p["BidVolume1"].Int())); --i; if(i < -1) { mexWarnMsgTxt("GetTick程序越界!"); break; } } return result; }
Status CatalogManagerCommon::_log(OperationContext* txn, const StringData& logCollName, const std::string& what, const std::string& operationNS, const BSONObj& detail) { Date_t now = grid.shardRegistry()->getExecutor()->now(); const std::string hostName = grid.shardRegistry()->getNetwork()->getHostName(); const string changeId = str::stream() << hostName << "-" << now.toString() << "-" << OID::gen(); ChangeLogType changeLog; changeLog.setChangeId(changeId); changeLog.setServer(hostName); changeLog.setClientAddr(txn->getClient()->clientAddress(true)); changeLog.setTime(now); changeLog.setNS(operationNS); changeLog.setWhat(what); changeLog.setDetails(detail); BSONObj changeLogBSON = changeLog.toBSON(); log() << "about to log metadata event into " << logCollName << ": " << changeLogBSON; const NamespaceString nss("config", logCollName); Status result = insertConfigDocument(txn, nss.ns(), changeLogBSON); if (!result.isOK()) { warning() << "Error encountered while logging config change with ID [" << changeId << "] into collection " << logCollName << ": " << result; } return result; }
std::string dateToCtimeString(Date_t date) { time_t t = date.toTimeT(); char buf[64]; #if defined(_WIN32) ctime_s(buf, sizeof(buf), &t); #else ctime_r(&t, buf); #endif char* milliSecStr = buf + 19; snprintf(milliSecStr, 5, ".%03d", static_cast<int32_t>(date.asInt64() % 1000)); return buf; }
Status CatalogManagerReplicaSet::logChange(OperationContext* txn, const string& clientAddress, const string& what, const string& ns, const BSONObj& detail) { if (_changeLogCollectionCreated.load() == 0) { BSONObj createCmd = BSON("create" << ChangeLogType::ConfigNS << "capped" << true << "size" << kChangeLogCollectionSize); auto result = grid.shardRegistry()->runCommandOnConfigWithNotMasterRetries("config", createCmd); if (!result.isOK()) { LOG(1) << "couldn't create changelog collection: " << causedBy(result.getStatus()); return result.getStatus(); } Status commandStatus = Command::getStatusFromCommandResult(result.getValue()); if (commandStatus.isOK() || commandStatus == ErrorCodes::NamespaceExists) { _changeLogCollectionCreated.store(1); } else { LOG(1) << "couldn't create changelog collection: " << causedBy(commandStatus); return commandStatus; } } Date_t now = grid.shardRegistry()->getExecutor()->now(); const std::string hostName = grid.shardRegistry()->getNetwork()->getHostName(); const string changeId = str::stream() << hostName << "-" << now.toString() << "-" << OID::gen(); ChangeLogType changeLog; changeLog.setChangeId(changeId); changeLog.setServer(hostName); changeLog.setClientAddr(clientAddress); changeLog.setTime(now); changeLog.setNS(ns); changeLog.setWhat(what); changeLog.setDetails(detail); BSONObj changeLogBSON = changeLog.toBSON(); log() << "about to log metadata event: " << changeLogBSON; Status result = insert(txn, ChangeLogType::ConfigNS, changeLogBSON, NULL); if (!result.isOK()) { warning() << "Error encountered while logging config change with ID " << changeId << ": " << result; } return result; }
void NetworkInterfaceMock::setNow(Date_t newNow) { boost::lock_guard<boost::mutex> lk(_mutex); invariant(newNow.asInt64() > _now.asInt64()); _now = newNow; _executor->signalWorkForTest(); _timeElapsed.notify_all(); }
void UserCacheInvalidator::run() { Client::initThread("UserCacheInvalidator"); lastInvalidationTime = Date_t::now(); while (true) { stdx::unique_lock<stdx::mutex> lock(invalidationIntervalMutex); Date_t sleepUntil = lastInvalidationTime + Seconds(userCacheInvalidationIntervalSecs.load()); Date_t now = Date_t::now(); while (now < sleepUntil) { MONGO_IDLE_THREAD_BLOCK; invalidationIntervalChangedCondition.wait_until(lock, sleepUntil.toSystemTimePoint()); sleepUntil = lastInvalidationTime + Seconds(userCacheInvalidationIntervalSecs.load()); now = Date_t::now(); } lastInvalidationTime = now; lock.unlock(); if (globalInShutdownDeprecated()) { break; } auto opCtx = cc().makeOperationContext(); StatusWith<OID> currentGeneration = getCurrentCacheGeneration(opCtx.get()); if (!currentGeneration.isOK()) { if (currentGeneration.getStatus().code() == ErrorCodes::CommandNotFound) { warning() << "_getUserCacheGeneration command not found on config server(s), " "this most likely means you are running an outdated version of mongod " "on the config servers"; } else { warning() << "An error occurred while fetching current user cache generation " "to check if user cache needs invalidation: " << currentGeneration.getStatus(); } // When in doubt, invalidate the cache _authzManager->invalidateUserCache(); continue; } if (currentGeneration.getValue() != _previousCacheGeneration) { log() << "User cache generation changed from " << _previousCacheGeneration << " to " << currentGeneration.getValue() << "; invalidating user cache"; _authzManager->invalidateUserCache(); _previousCacheGeneration = currentGeneration.getValue(); } } }
StatusWith<executor::TaskExecutor::CallbackHandle> TaskExecutorMock::scheduleWorkAt( Date_t when, const CallbackFn& work) { if (shouldFailScheduleWorkAtRequest()) { return Status(ErrorCodes::OperationFailed, str::stream() << "failed to schedule work at " << when.toString()); } return getExecutor()->scheduleWorkAt(when, work); }
static inline std::string _dateToISOString(Date_t date, bool local) { const int bufSize = 32; char buf[bufSize]; struct tm t; time_t_to_Struct(date.toTimeT(), &t, local); int pos = strftime(buf, bufSize, MONGO_ISO_DATE_FMT_NO_TZ, &t); fassert(16981, 0 < pos); char* cur = buf + pos; int bufRemaining = bufSize - pos; pos = snprintf(cur, bufRemaining, ".%03d", static_cast<int32_t>(date.asInt64() % 1000)); fassert(16982, bufRemaining > pos && pos > 0); cur += pos; bufRemaining -= pos; if (local) { fassert(16983, bufRemaining >= 6); #ifdef _WIN32 // NOTE(schwerin): The value stored by _get_timezone is the value one adds to local time // to get UTC. This is opposite of the ISO-8601 meaning of the timezone offset. // NOTE(schwerin): Microsoft's timezone code always assumes US rules for daylight // savings time. We can do no better without completely reimplementing localtime_s and // related time library functions. long msTimeZone; _get_timezone(&msTimeZone); if (t.tm_isdst) msTimeZone -= 3600; const bool tzIsWestOfUTC = msTimeZone > 0; const long tzOffsetSeconds = msTimeZone* (tzIsWestOfUTC ? 1 : -1); const long tzOffsetHoursPart = tzOffsetSeconds / 3600; const long tzOffsetMinutesPart = (tzOffsetSeconds / 60) % 60; snprintf(cur, 6, "%c%02ld%02ld", tzIsWestOfUTC ? '-' : '+', tzOffsetHoursPart, tzOffsetMinutesPart); #else strftime(cur, bufRemaining, "%z", &t); #endif } else { fassert(16984, bufRemaining >= 2); *cur = 'Z'; ++cur; *cur = '\0'; } return buf; }
bool TicketHolder::waitForTicketUntil(OperationContext* opCtx, Date_t until) { stdx::unique_lock<stdx::mutex> lk(_mutex); if (opCtx) { return opCtx->waitForConditionOrInterruptUntil( _newTicket, lk, until, [this] { return _tryAcquire(); }); } else { return _newTicket.wait_until( lk, until.toSystemTimePoint(), [this] { return _tryAcquire(); }); } }
Date_t roundTime(Date_t now, Milliseconds period) { // Note: auto type deduction is explicitly avoided here to ensure rigid type correctness long long clock_duration = now.toMillisSinceEpoch(); long long now_next_period = clock_duration + period.count(); long long excess_time(now_next_period % period.count()); long long next_time = now_next_period - excess_time; return Date_t::fromMillisSinceEpoch(next_time); }
void ShardingTestFixture::expectConfigCollectionInsert(const HostAndPort& configHost, StringData collName, Date_t timestamp, const std::string& what, const std::string& ns, const BSONObj& detail) { onCommand([&](const RemoteCommandRequest& request) { ASSERT_EQUALS(configHost, request.target); ASSERT_EQUALS("config", request.dbname); BatchedInsertRequest actualBatchedInsert; std::string errmsg; ASSERT_TRUE(actualBatchedInsert.parseBSON(request.dbname, request.cmdObj, &errmsg)); ASSERT_EQ("config", actualBatchedInsert.getNS().db()); ASSERT_EQ(collName, actualBatchedInsert.getNS().coll()); auto inserts = actualBatchedInsert.getDocuments(); ASSERT_EQUALS(1U, inserts.size()); const ChangeLogType& actualChangeLog = assertGet(ChangeLogType::fromBSON(inserts.front())); ASSERT_EQUALS(operationContext()->getClient()->clientAddress(true), actualChangeLog.getClientAddr()); ASSERT_EQUALS(detail, actualChangeLog.getDetails()); ASSERT_EQUALS(ns, actualChangeLog.getNS()); ASSERT_EQUALS(network()->getHostName(), actualChangeLog.getServer()); ASSERT_EQUALS(timestamp, actualChangeLog.getTime()); ASSERT_EQUALS(what, actualChangeLog.getWhat()); // Handle changeId specially because there's no way to know what OID was generated std::string changeId = actualChangeLog.getChangeId(); size_t firstDash = changeId.find("-"); size_t lastDash = changeId.rfind("-"); const std::string serverPiece = changeId.substr(0, firstDash); const std::string timePiece = changeId.substr(firstDash + 1, lastDash - firstDash - 1); const std::string oidPiece = changeId.substr(lastDash + 1); ASSERT_EQUALS(grid.getNetwork()->getHostName(), serverPiece); ASSERT_EQUALS(timestamp.toString(), timePiece); OID generatedOID; // Just make sure this doesn't throws and assume the OID is valid generatedOID.init(oidPiece); BatchedCommandResponse response; response.setOk(true); return response.toBSON(); }); }
Status NetworkInterfaceASIO::setAlarm(Date_t when, const stdx::function<void()>& action) { if (inShutdown()) { return {ErrorCodes::ShutdownInProgress, "NetworkInterfaceASIO shutdown in progress"}; } // "alarm" must stay alive until it expires, hence the shared_ptr. auto alarm = std::make_shared<asio::system_timer>(_io_service, when.toSystemTimePoint()); alarm->async_wait([alarm, this, action](std::error_code ec) { if (!ec) { return action(); } else if (ec != asio::error::operation_aborted) { // When the network interface is shut down, it will cancel all pending // alarms, raising an "operation_aborted" error here, which we ignore. warning() << "setAlarm() received an error: " << ec.message(); } }); return Status::OK(); };
// Theory of operation for waitForConditionOrInterruptNoAssertUntil and markKilled: // // An operation indicates to potential killers that it is waiting on a condition variable by setting // _waitMutex and _waitCV, while holding the lock on its parent Client. It then unlocks its Client, // unblocking any killers, which are required to have locked the Client before calling markKilled. // // When _waitMutex and _waitCV are set, killers must lock _waitMutex before setting the _killCode, // and must signal _waitCV before releasing _waitMutex. Unfortunately, they must lock _waitMutex // without holding a lock on Client to avoid a deadlock with callers of // waitForConditionOrInterruptNoAssertUntil(). So, in the event that _waitMutex is set, the killer // increments _numKillers, drops the Client lock, acquires _waitMutex and then re-acquires the // Client lock. We know that the Client, its OperationContext and _waitMutex will remain valid // during this period because the caller of waitForConditionOrInterruptNoAssertUntil will not return // while _numKillers > 0 and will not return until it has itself reacquired _waitMutex. Instead, // that caller will keep waiting on _waitCV until _numKillers drops to 0. // // In essence, when _waitMutex is set, _killCode is guarded by _waitMutex and _waitCV, but when // _waitMutex is not set, it is guarded by the Client spinlock. Changing _waitMutex is itself // guarded by the Client spinlock and _numKillers. // // When _numKillers does drop to 0, the waiter will null out _waitMutex and _waitCV. // // This implementation adds a minimum of two spinlock acquire-release pairs to every condition // variable wait. StatusWith<stdx::cv_status> OperationContext::waitForConditionOrInterruptNoAssertUntil( stdx::condition_variable& cv, stdx::unique_lock<stdx::mutex>& m, Date_t deadline) noexcept { invariant(getClient()); { stdx::lock_guard<Client> clientLock(*getClient()); invariant(!_waitMutex); invariant(!_waitCV); invariant(0 == _numKillers); // This interrupt check must be done while holding the client lock, so as not to race with a // concurrent caller of markKilled. auto status = checkForInterruptNoAssert(); if (!status.isOK()) { return status; } _waitMutex = m.mutex(); _waitCV = &cv; } if (hasDeadline()) { deadline = std::min(deadline, getDeadline()); } const auto waitStatus = [&] { if (Date_t::max() == deadline) { cv.wait(m); return stdx::cv_status::no_timeout; } const auto clockSource = getServiceContext()->getPreciseClockSource(); if (clockSource->tracksSystemClock()) { return cv.wait_until(m, deadline.toSystemTimePoint()); } // The following cases only occur during testing, when the precise clock source is // virtualized and does not track the system clock. return cvWaitUntilWithClockSource(clockSource, cv, m, deadline); }(); // Continue waiting on cv until no other thread is attempting to kill this one. cv.wait(m, [this] { stdx::lock_guard<Client> clientLock(*getClient()); if (0 == _numKillers) { _waitMutex = nullptr; _waitCV = nullptr; return true; } return false; }); auto status = checkForInterruptNoAssert(); if (!status.isOK()) { return status; } if (hasDeadline() && waitStatus == stdx::cv_status::timeout && deadline == getDeadline()) { // It's possible that the system clock used in stdx::condition_variable::wait_until // is slightly ahead of the FastClock used in checkForInterrupt. In this case, // we treat the operation as though it has exceeded its time limit, just as if the // FastClock and system clock had agreed. markKilled(ErrorCodes::ExceededTimeLimit); return Status(ErrorCodes::ExceededTimeLimit, "operation exceeded time limit"); } return waitStatus; }
/* ** Build Json string that represent this element. */ void MongoElement::buildJsonString(Concatenator &con) { switch (_bsonElement.type()) { /** double precision floating point value */ case NumberDouble: con.append(QString::number(_bsonElement.Double())); break; /** character string, stored in utf8 */ case String: { /* ** If you'll write: ** ** int valsize = element.valuesize(); ** int strsize = element.valuestrsize(); ** int bytescount = qstrlen(element.valuestr()); ** ** You'll get: ** ** bytescount + 1 == strsize ** strsize + 4 == valsize ** ** So: ** bytescount + 5 == valsize ** */ QString res = QString::fromUtf8(_bsonElement.valuestr(), _bsonElement.valuestrsize() - 1); con.append(res); } break; /** an embedded object */ case Object: { MongoDocumentPtr doc = asDocument(); doc->buildJsonString(con); } break; /** an embedded array */ case Array: { MongoDocumentPtr doc = asDocument(); doc->buildJsonString(con); } break; /** binary data */ case BinData: { mongo::BinDataType binType = _bsonElement.binDataType(); if (binType == mongo::newUUID || binType == mongo::bdtUUID) { std::string uuid = HexUtils::formatUuid(_bsonElement, AppRegistry::instance().settingsManager()->uuidEncoding()); con.append(QString::fromStdString(uuid)); break; } con.append("<binary>"); } break; /** Undefined type */ case Undefined: con.append("<undefined>"); break; /** ObjectId */ case jstOID: { QString idValue = QString::fromStdString(_bsonElement.OID().toString()); QString objectId = QString("ObjectId(\"%1\")").arg(idValue); con.append(objectId); } break; /** boolean type */ case Bool: con.append(_bsonElement.Bool() ? "true" : "false"); break; /** date type */ case Date: { long long ms = (long long) _bsonElement.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::stringstream strm; //boost::date_time::time_facet *timeFacet = new boost::date_time::time_facet("%a, %d %b %Y %H:%M:%S.%f GMT"); // "%Y---%m-%d %H:%M:%S" boost::posix_time::time_facet *facet = new boost::posix_time::time_facet("%Y-%m-%d %H:%M:%S"); strm.imbue(std::locale(strm.getloc(), facet)); strm << time; con.append(QString::fromStdString(strm.str())); break; /* // this code is left untill the upper one will stabilize unsigned long long millis = _bsonElement.Date().millis; if ((long long)millis >= 0 && ((long long)millis/1000) < (std::numeric_limits<time_t>::max)()) { con.append(QString::fromStdString(_bsonElement.Date().toString())); } break; */ } /** null type */ case jstNULL: con.append(QString("<null>")); break; /** regular expression, a pattern with options */ case RegEx: { con.append("/" + QString::fromUtf8(_bsonElement.regex()) + "/"); for ( const char *f = _bsonElement.regexFlags(); *f; ++f ) { switch ( *f ) { case 'g': case 'i': case 'm': con.append(QString(*f)); default: break; } } } break; /** deprecated / will be redesigned */ case DBRef: break; /** deprecated / use CodeWScope */ case Code: con.append(QString::fromUtf8(_bsonElement._asCode().data())); break; /** a programming language (e.g., Python) symbol */ case Symbol: con.append(QString::fromUtf8(_bsonElement.valuestr(), _bsonElement.valuestrsize() - 1)); break; /** javascript code that can execute on the database server, with SavedContext */ case CodeWScope: { mongo::BSONObj scope = _bsonElement.codeWScopeObject(); if (!scope.isEmpty() ) { con.append(QString::fromUtf8(_bsonElement._asCode().data())); break; } } break; /** 32 bit signed integer */ case NumberInt: con.append(QString::number(_bsonElement.Int())); break; /** Updated to a Date with value next OpTime on insert */ case Timestamp: { Date_t date = _bsonElement.timestampTime(); unsigned long long millis = date.millis; if ((long long)millis >= 0 && ((long long)millis/1000) < (std::numeric_limits<time_t>::max)()) { con.append(QString::fromStdString(date.toString())); } break; } /** 64 bit integer */ case NumberLong: con.append(QString::number(_bsonElement.Long())); break; default: con.append("<unsupported>"); break; } }
void ReplSetImpl::veto(const string& host, const Date_t until) { lock lk(this); _veto[host] = until.toTimeT(); }
/* ** Build Json string that represent this element. */ void MongoElement::buildJsonString(std::string &con) { switch (_bsonElement.type()) { /** double precision floating point value */ case NumberDouble: con.append(QtUtils::toStdString<std::string>(QString::number(_bsonElement.Double(),'g',14))); break; /** character string, stored in utf8 */ case String: { /* ** If you'll write: ** ** int valsize = element.valuesize(); ** int strsize = element.valuestrsize(); ** int bytescount = qstrlen(element.valuestr()); ** ** You'll get: ** ** bytescount + 1 == strsize ** strsize + 4 == valsize ** ** So: ** bytescount + 5 == valsize ** */ con.append(_bsonElement.valuestr(), _bsonElement.valuestrsize() - 1); } break; /** an embedded object */ case Object: { MongoDocumentPtr doc = asDocument(); doc->buildJsonString(con); } break; /** an embedded array */ case Array: { MongoDocumentPtr doc = asDocument(); doc->buildJsonString(con); } break; /** binary data */ case BinData: { mongo::BinDataType binType = _bsonElement.binDataType(); if (binType == mongo::newUUID || binType == mongo::bdtUUID) { std::string uuid = HexUtils::formatUuid(_bsonElement, AppRegistry::instance().settingsManager()->uuidEncoding()); con.append(uuid); break; } con.append("<binary>"); } break; /** Undefined type */ case Undefined: con.append("<undefined>"); break; /** ObjectId */ case jstOID: { std::string idValue = _bsonElement.OID().toString(); char buff[256]={0}; sprintf(buff,"ObjectId(\"%s\")",idValue.c_str()); con.append(buff); } break; /** boolean type */ case Bool: con.append(_bsonElement.Bool() ? "true" : "false"); break; /** date type */ case Date: { long long ms = (long long) _bsonElement.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,AppRegistry::instance().settingsManager()->timeZone()==LocalTime); con.append(date); break; } /** null type */ case jstNULL: con.append("<null>"); break; /** regular expression, a pattern with options */ case RegEx: { con.append("/" + std::string(_bsonElement.regex()) + "/"); for ( const char *f = _bsonElement.regexFlags(); *f; ++f ) { switch ( *f ) { case 'g': case 'i': case 'm': con+=*f; default: break; } } } break; /** deprecated / will be redesigned */ case DBRef: break; /** deprecated / use CodeWScope */ case Code: con.append(_bsonElement._asCode()); break; /** a programming language (e.g., Python) symbol */ case Symbol: con.append(_bsonElement.valuestr(), _bsonElement.valuestrsize() - 1); break; /** javascript code that can execute on the database server, with SavedContext */ case CodeWScope: { mongo::BSONObj scope = _bsonElement.codeWScopeObject(); if (!scope.isEmpty() ) { con.append(_bsonElement._asCode()); break; } } break; /** 32 bit signed integer */ case NumberInt: { char num[16]={0}; sprintf(num,"%d",_bsonElement.Int()); con.append(num); break; } /** Updated to a Date with value next OpTime on insert */ case Timestamp: { Date_t date = _bsonElement.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; } /** 64 bit integer */ case NumberLong: { char num[32]={0}; sprintf(num,"%lld",_bsonElement.Long()); con.append(num); break; } default: con.append("<unsupported>"); break; } }
void BSONElement::jsonStringStream(JsonStringFormat format, bool includeFieldNames, int pretty, std::stringstream& s) const { if (includeFieldNames) s << '"' << escape(fieldName()) << "\" : "; switch (type()) { case mongo::String: case Symbol: s << '"' << escape(string(valuestr(), valuestrsize() - 1)) << '"'; break; case NumberLong: if (format == TenGen) { s << "NumberLong(" << _numberLong() << ")"; } else { s << "{ \"$numberLong\" : \"" << _numberLong() << "\" }"; } break; case NumberInt: if (format == TenGen) { s << "NumberInt(" << _numberInt() << ")"; break; } case NumberDouble: if (number() >= -std::numeric_limits<double>::max() && number() <= std::numeric_limits<double>::max()) { auto origPrecision = s.precision(); auto guard = MakeGuard([&s, origPrecision]() { s.precision(origPrecision); }); s.precision(16); s << number(); } // This is not valid JSON, but according to RFC-4627, "Numeric values that cannot be // represented as sequences of digits (such as Infinity and NaN) are not permitted." so // we are accepting the fact that if we have such values we cannot output valid JSON. else if (std::isnan(number())) { s << "NaN"; } else if (std::isinf(number())) { s << (number() > 0 ? "Infinity" : "-Infinity"); } else { StringBuilder ss; ss << "Number " << number() << " cannot be represented in JSON"; string message = ss.str(); massert(10311, message.c_str(), false); } break; case NumberDecimal: if (format == TenGen) s << "NumberDecimal(\""; else s << "{ \"$numberDecimal\" : \""; // Recognize again that this is not valid JSON according to RFC-4627. // Also, treat -NaN and +NaN as the same thing for MongoDB. if (numberDecimal().isNaN()) { s << "NaN"; } else if (numberDecimal().isInfinite()) { s << (numberDecimal().isNegative() ? "-Infinity" : "Infinity"); } else { s << numberDecimal().toString(); } if (format == TenGen) s << "\")"; else s << "\" }"; break; case mongo::Bool: s << (boolean() ? "true" : "false"); break; case jstNULL: s << "null"; break; case Undefined: if (format == Strict) { s << "{ \"$undefined\" : true }"; } else { s << "undefined"; } break; case Object: embeddedObject().jsonStringStream(format, pretty, false, s); break; case mongo::Array: { if (embeddedObject().isEmpty()) { s << "[]"; break; } s << "[ "; BSONObjIterator i(embeddedObject()); BSONElement e = i.next(); if (!e.eoo()) { int count = 0; while (1) { if (pretty) { s << '\n'; for (int x = 0; x < pretty; x++) s << " "; } if (strtol(e.fieldName(), 0, 10) > count) { s << "undefined"; } else { e.jsonStringStream(format, false, pretty ? pretty + 1 : 0, s); e = i.next(); } count++; if (e.eoo()) break; s << ", "; } } s << " ]"; break; } case DBRef: { if (format == TenGen) s << "Dbref( "; else s << "{ \"$ref\" : "; s << '"' << valuestr() << "\", "; if (format != TenGen) s << "\"$id\" : "; s << '"' << mongo::OID::from(valuestr() + valuestrsize()) << "\" "; if (format == TenGen) s << ')'; else s << '}'; break; } case jstOID: if (format == TenGen) { s << "ObjectId( "; } else { s << "{ \"$oid\" : "; } s << '"' << __oid() << '"'; if (format == TenGen) { s << " )"; } else { s << " }"; } break; case BinData: { ConstDataCursor reader(value()); const int len = reader.readAndAdvance<LittleEndian<int>>(); BinDataType type = static_cast<BinDataType>(reader.readAndAdvance<uint8_t>()); s << "{ \"$binary\" : \""; base64::encode(s, reader.view(), len); auto origFill = s.fill(); auto origFmtF = s.flags(); auto origWidth = s.width(); auto guard = MakeGuard([&s, origFill, origFmtF, origWidth] { s.fill(origFill); s.setf(origFmtF); s.width(origWidth); }); s.setf(std::ios_base::hex, std::ios_base::basefield); s << "\", \"$type\" : \""; s.width(2); s.fill('0'); s << type; s << "\" }"; break; } case mongo::Date: if (format == Strict) { Date_t d = date(); s << "{ \"$date\" : "; // The two cases in which we cannot convert Date_t::millis to an ISO Date string are // when the date is too large to format (SERVER-13760), and when the date is before // the epoch (SERVER-11273). Since Date_t internally stores millis as an unsigned // long long, despite the fact that it is logically signed (SERVER-8573), this check // handles both the case where Date_t::millis is too large, and the case where // Date_t::millis is negative (before the epoch). if (d.isFormattable()) { s << "\"" << dateToISOStringLocal(date()) << "\""; } else { s << "{ \"$numberLong\" : \"" << d.toMillisSinceEpoch() << "\" }"; } s << " }"; } else { s << "Date( "; if (pretty) { Date_t d = date(); // The two cases in which we cannot convert Date_t::millis to an ISO Date string // are when the date is too large to format (SERVER-13760), and when the date is // before the epoch (SERVER-11273). Since Date_t internally stores millis as an // unsigned long long, despite the fact that it is logically signed // (SERVER-8573), this check handles both the case where Date_t::millis is too // large, and the case where Date_t::millis is negative (before the epoch). if (d.isFormattable()) { s << "\"" << dateToISOStringLocal(date()) << "\""; } else { // FIXME: This is not parseable by the shell, since it may not fit in a // float s << d.toMillisSinceEpoch(); } } else { s << date().asInt64(); } s << " )"; } break; case RegEx: if (format == Strict) { s << "{ \"$regex\" : \"" << escape(regex()); s << "\", \"$options\" : \"" << regexFlags() << "\" }"; } else { s << "/" << escape(regex(), true) << "/"; // FIXME Worry about alpha order? for (const char* f = regexFlags(); *f; ++f) { switch (*f) { case 'g': case 'i': case 'm': s << *f; default: break; } } } break; case CodeWScope: { BSONObj scope = codeWScopeObject(); if (!scope.isEmpty()) { s << "{ \"$code\" : \"" << escape(_asCode()) << "\" , " << "\"$scope\" : " << scope.jsonString() << " }"; break; } } case Code: s << "\"" << escape(_asCode()) << "\""; break; case bsonTimestamp: if (format == TenGen) { s << "Timestamp( " << durationCount<Seconds>(timestampTime().toDurationSinceEpoch()) << ", " << timestampInc() << " )"; } else { s << "{ \"$timestamp\" : { \"t\" : " << durationCount<Seconds>(timestampTime().toDurationSinceEpoch()) << ", \"i\" : " << timestampInc() << " } }"; } break; case MinKey: s << "{ \"$minKey\" : 1 }"; break; case MaxKey: s << "{ \"$maxKey\" : 1 }"; break; default: StringBuilder ss; ss << "Cannot create a properly formatted JSON string with " << "element: " << toString() << " of type: " << type(); string message = ss.str(); massert(10312, message.c_str(), false); } }
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; } }