static int qset_one(SSDB *ssdb, const Bytes &name, uint64_t seq, const Bytes &item){ std::string key = encode_qitem_key(name, seq); leveldb::Status s; ssdb->binlogs->Put(key, item.Slice()); return 0; }
static int qdel_one(SSDB *ssdb, const Bytes &name, uint64_t seq){ std::string key = encode_qitem_key(name, seq); leveldb::Status s; ssdb->binlogs->Delete(key); return 0; }
int SSDBImpl::qset_by_seq(const Bytes &name, uint64_t seq, const Bytes &item, char log_type){ Transaction trans(binlogs); uint64_t min_seq, max_seq; int ret; int64_t size = this->qsize(name); if(size == -1){ return -1; } ret = qget_uint64(this->ldb, name, QFRONT_SEQ, &min_seq); if(ret == -1){ return -1; } max_seq = min_seq + size; if(seq < min_seq || seq > max_seq){ return 0; } ret = qset_one(this, name, seq, item); if(ret == -1){ return -1; } std::string buf = encode_qitem_key(name, seq); binlogs->add_log(log_type, BinlogCommand::QSET, buf); leveldb::Status s = binlogs->commit(); if(!s.ok()){ log_error("Write error!"); return -1; } return 1; }
int SSDB::qfix(const Bytes &name){ Transaction trans(binlogs); std::string key_s = encode_qitem_key(name, QITEM_MIN_SEQ - 1); std::string key_e = encode_qitem_key(name, QITEM_MAX_SEQ); bool error = false; uint64_t seq_min = 0; uint64_t seq_max = 0; uint64_t count = 0; Iterator *it = this->iterator(key_s, key_e, QITEM_MAX_SEQ); while(it->next()){ //dump(it->key().data(), it->key().size()); if(seq_min == 0){ if(decode_qitem_key(it->key(), NULL, &seq_min) == -1){ // or just delete it? error = true; break; } } if(decode_qitem_key(it->key(), NULL, &seq_max) == -1){ error = true; break; } count ++; } delete it; if(error){ return -1; } if(count == 0){ this->binlogs->Delete(encode_qsize_key(name)); qdel_one(this, name, QFRONT_SEQ); qdel_one(this, name, QBACK_SEQ); }else{ this->binlogs->Put(encode_qsize_key(name), leveldb::Slice((char *)&count, sizeof(count))); qset_one(this, name, QFRONT_SEQ, Bytes(&seq_min, sizeof(seq_min))); qset_one(this, name, QBACK_SEQ, Bytes(&seq_max, sizeof(seq_max))); } leveldb::Status s = binlogs->commit(); if(!s.ok()){ log_error("Write error!"); return -1; } return 0; }
int64_t SSDBImpl::_qpush(const Bytes &name, const Bytes &item, uint64_t front_or_back_seq, char log_type){ Transaction trans(binlogs); int ret; // generate seq uint64_t seq; ret = qget_uint64(this->ldb, name, front_or_back_seq, &seq); if(ret == -1){ return -1; } // update front and/or back if(ret == 0){ seq = QITEM_SEQ_INIT; ret = qset_one(this, name, QFRONT_SEQ, Bytes(&seq, sizeof(seq))); if(ret == -1){ return -1; } ret = qset_one(this, name, QBACK_SEQ, Bytes(&seq, sizeof(seq))); }else{ seq += (front_or_back_seq == QFRONT_SEQ)? -1 : +1; ret = qset_one(this, name, front_or_back_seq, Bytes(&seq, sizeof(seq))); } if(ret == -1){ return -1; } if(seq <= QITEM_MIN_SEQ || seq >= QITEM_MAX_SEQ){ log_info("queue is full, seq: %" PRIu64 " out of range", seq); return -1; } // prepend/append item ret = qset_one(this, name, seq, item); if(ret == -1){ return -1; } std::string buf = encode_qitem_key(name, seq); if(front_or_back_seq == QFRONT_SEQ){ binlogs->add_log(log_type, BinlogCommand::QPUSH_FRONT, buf); }else{ binlogs->add_log(log_type, BinlogCommand::QPUSH_BACK, buf); } // update size int64_t size = incr_qsize(this, name, +1); if(size == -1){ return -1; } leveldb::Status s = binlogs->commit(); if(!s.ok()){ log_error("Write error! %s", s.ToString().c_str()); return -1; } return size; }
static int qget(leveldb::DB* db, const Bytes &name, uint64_t seq, std::string *val){ std::string key = encode_qitem_key(name, seq); leveldb::Status s; s = db->Get(leveldb::ReadOptions(), key, val); if(s.IsNotFound()){ return 0; }else if(!s.ok()){ log_error("Get() error!"); return -1; }else{ return 1; } }
// return: 0: index out of range, -1: error, 1: ok int SSDBImpl::qset(const Bytes &name, int64_t index, const Bytes &item, char log_type){ Transaction trans(binlogs); int64_t size = this->qsize(name); if(size == -1){ return -1; } if(index >= size || index < -size){ return 0; } int ret; uint64_t seq; if(index >= 0){ ret = qget_uint64(this->ldb, name, QFRONT_SEQ, &seq); seq += index; }else{ ret = qget_uint64(this->ldb, name, QBACK_SEQ, &seq); seq += index + 1; } if(ret == -1){ return -1; } if(ret == 0){ return 0; } ret = qset_one(this, name, seq, item); if(ret == -1){ return -1; } //log_info("qset %s %" PRIu64 "", hexmem(name.data(), name.size()).c_str(), seq); std::string buf = encode_qitem_key(name, seq); binlogs->add_log(log_type, BinlogCommand::QSET, buf); leveldb::Status s = binlogs->commit(); if(!s.ok()){ log_error("Write error!"); return -1; } return 1; }