static int64_t incr_qsize(SSDBImpl *ssdb, const Bytes &name, int64_t incr){ int64_t size = ssdb->qsize(name); if(size == -1){ return -1; } size += incr; if(size <= 0){ ssdb->binlogs->Delete(encode_qsize_key(name)); qdel_one(ssdb, name, QFRONT_SEQ); qdel_one(ssdb, name, QBACK_SEQ); }else{ ssdb->binlogs->Put(encode_qsize_key(name), leveldb::Slice((char *)&size, sizeof(size))); } return size; }
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; }
// @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; }