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; }
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; }
int SSDBImpl::_qpop(const Bytes &name, std::string *item, uint64_t front_or_back_seq, char log_type){ Transaction trans(binlogs); int ret; uint64_t seq; ret = qget_uint64(this->ldb, name, front_or_back_seq, &seq); if(ret == -1){ return -1; } if(ret == 0){ return 0; } ret = qget_by_seq(this->ldb, name, seq, item); if(ret == -1){ return -1; } if(ret == 0){ return 0; } // delete item ret = qdel_one(this, name, seq); if(ret == -1){ return -1; } if(front_or_back_seq == QFRONT_SEQ){ binlogs->add_log(log_type, BinlogCommand::QPOP_FRONT, name.String()); }else{ binlogs->add_log(log_type, BinlogCommand::QPOP_BACK, name.String()); } // update size int64_t size = incr_qsize(this, name, -1); if(size == -1){ return -1; } // update front if(size > 0){ seq += (front_or_back_seq == QFRONT_SEQ)? +1 : -1; //log_debug("seq: %" PRIu64 ", ret: %d", seq, ret); ret = qset_one(this, name, front_or_back_seq, Bytes(&seq, sizeof(seq))); if(ret == -1){ return -1; } } leveldb::Status s = binlogs->commit(); if(!s.ok()){ log_error("Write error! %s", s.ToString().c_str()); return -1; } return 1; }
int SSDB::qpush(const Bytes &name, const Bytes &item){ Transaction trans(binlogs); int ret; // generate seq uint64_t seq; ret = qget_uint64(this->db, name, QBACK_SEQ, &seq); if(ret == -1){ return -1; } if(ret == 0){ seq = QITEM_MIN_SEQ; }else{ seq += 1; } // append item ret = qset_one(this, name, seq, item); if(ret == -1){ return -1; } // update size int64_t size = incr_qsize(this, name, +1); if(size == -1){ return -1; } // update back ret = qset_one(this, name, QBACK_SEQ, Bytes(&seq, sizeof(seq))); if(ret == -1){ return -1; } leveldb::Status s = binlogs->commit(); if(!s.ok()){ log_error("Write error!"); return -1; } return 1; }
// @return 0: empty queue, 1: item popped, -1: error int SSDB::qpop(const Bytes &name, std::string *item){ Transaction trans(binlogs); int ret; uint64_t seq; ret = qget_uint64(this->db, name, QFRONT_SEQ, &seq); if(ret == -1){ return -1; } if(ret == 0){ seq = QITEM_MIN_SEQ; } ret = qget(this->db, name, seq, item); if(ret == -1){ return -1; } if(ret == 0){ return 0; } // delete item ret = qdel_one(this, name, seq); if(ret == -1){ return -1; } // update size int64_t size = incr_qsize(this, name, -1); if(size == -1){ return -1; } // update front if(size > 0){ seq += 1; //log_debug("seq: %" PRIu64 ", ret: %d", seq, ret); ret = qset_one(this, name, QFRONT_SEQ, Bytes(&seq, sizeof(seq))); if(ret == -1){ return -1; } } leveldb::Status s = binlogs->commit(); if(!s.ok()){ log_error("Write error!"); return -1; } 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; }