bool CvMongoMat::upload(const cv::Mat &image) { if (conn_ == NULL) return false; mongo::BSONObj old_obj = BSON(key_ << BSON("$exists" << true)); mongo::BSONObjBuilder builder; if (image.empty()) { builder.appendBinData(key_, 0, mongo::BinDataGeneral, NULL); } else { std::vector<int> params(2); params[0] = CV_IMWRITE_JPEG_QUALITY; params[1] = 95; std::vector<uchar> buf; cv::imencode(".jpg", image, buf, params); builder.appendBinData(key_, buf.size(), mongo::BinDataGeneral, &buf[0]); } timestamp_ = get_timestamp_(); builder.append("timestamp", timestamp_); conn_->update(collection_, old_obj, builder.obj()); return true; }
// move sorted runs to ready_ collection int Sequencer::make_checkpoint_(aku_Timestamp new_checkpoint) { int flag = sequence_number_.fetch_add(1) + 1; if (flag % 2 != 0) { auto old_top = get_timestamp_(checkpoint_); checkpoint_ = new_checkpoint; vector<PSortedRun> new_runs; for (auto& sorted_run: runs_) { auto it = lower_bound(sorted_run->begin(), sorted_run->end(), TimeSeriesValue(old_top, AKU_LIMITS_MAX_ID, 0u, 0u)); // Check that compression threshold is reached if (it == sorted_run->begin()) { // all timestamps are newer than old_top, do nothing new_runs.push_back(move(sorted_run)); continue; } else if (it == sorted_run->end()) { // all timestamps are older than old_top, move them ready_.push_back(move(sorted_run)); } else { // it is in between of the sorted run - split PSortedRun run(new SortedRun()); copy(sorted_run->begin(), it, back_inserter(*run)); // copy old ready_.push_back(move(run)); run.reset(new SortedRun()); copy(it, sorted_run->end(), back_inserter(*run)); // copy new new_runs.push_back(move(run)); } } Lock guard(runs_resize_lock_); space_estimate_ = 0u; for (auto& sorted_run: new_runs) { space_estimate_ += sorted_run->size() * SPACE_PER_ELEMENT; } swap(runs_, new_runs); size_t ready_size = 0u; for (auto& sorted_run: ready_) { ready_size += sorted_run->size(); } if (ready_size < c_threshold_) { // If ready doesn't contains enough data compression wouldn't be efficient, // we need to wait for more data to come flag = sequence_number_.fetch_add(1) + 1; // We should make sorted runs in ready_ array searchable again for (auto& sorted_run: ready_) { runs_.push_back(sorted_run); } ready_.clear(); } } return flag; }
CvMongoMat::CvMongoMat(mongo::DBClientConnection &conn, const std::string &collection, const std::string &key) : conn_(&conn), collection_(collection), key_(key), timestamp_(0) { if (conn_ == NULL) return; // cleanup target key mongo::BSONObj remove_query = BSON(key_ << BSON("$exists" << "true")); conn_->remove(collection_, remove_query); // insert dummy key-value mongo::BSONObjBuilder builder; builder.appendBinData(key_, 0, mongo::BinDataGeneral, NULL); builder.append("timestamp", get_timestamp_()); conn_->insert(collection_, builder.obj()); }
Sequencer::Sequencer(PageHeader const* page, const aku_FineTuneParams &config) : window_size_(config.window_size) , page_(page) , top_timestamp_() , checkpoint_(0u) , sequence_number_ {0} , run_locks_(RUN_LOCK_FLAGS_SIZE) , c_threshold_(config.compression_threshold) { key_.reset(new SortedRun()); key_->push_back(TimeSeriesValue()); if (page) { auto cnt = page->get_entries_count(); if (cnt != 0) { auto ts = page->read_timestamp_at(cnt - 1); checkpoint_ = get_checkpoint_(ts); top_timestamp_ = get_timestamp_(ts); } } }