int BackendSync::Client::sync(BinlogQueue *logs) { Binlog log; while(1) { int ret = 0; uint64_t expect_seq = this->last_seq + 1; if(this->status == Client::COPY && this->last_seq == 0) { ret = logs->find_last(&log); } else { ret = logs->find_next(expect_seq, &log); } if(ret == 0) { return 0; } if(this->status == Client::COPY && log.key() > this->last_key) { log_debug("fd: %d, last_key: '%s', drop: %s", link->fd(), hexmem(this->last_key.data(), this->last_key.size()).c_str(), log.dumps().c_str()); this->last_seq = log.seq(); // WARN: When there are writes behind last_key, we MUST create // a new iterator, because iterator will not know this key. // Because iterator ONLY iterates throught keys written before // iterator is created. if(this->iter) { delete this->iter; this->iter = NULL; } continue; } if(this->last_seq != 0 && log.seq() != expect_seq) { log_warn("%s:%d fd: %d, OUT_OF_SYNC! log.seq: %" PRIu64 ", expect_seq: %" PRIu64 "", link->remote_ip, link->remote_port, link->fd(), log.seq(), expect_seq ); this->status = Client::OUT_OF_SYNC; return 1; } // update last_seq this->last_seq = log.seq(); char type = log.type(); if(type == BinlogType::MIRROR && this->is_mirror) { if(this->last_seq - this->last_noop_seq >= 1000) { this->noop(); return 1; } else { continue; } } break; } int ret = 0; std::string val; switch(log.cmd()) { case BinlogCommand::KSET: case BinlogCommand::HSET: case BinlogCommand::ZSET: case BinlogCommand::QSET: case BinlogCommand::QPUSH_BACK: case BinlogCommand::QPUSH_FRONT: ret = backend->ssdb->raw_get(log.key(), &val); if(ret == -1) { log_error("fd: %d, raw_get error!", link->fd()); } else if(ret == 0) { //log_debug("%s", hexmem(log.key().data(), log.key().size()).c_str()); log_trace("fd: %d, skip not found: %s", link->fd(), log.dumps().c_str()); } else { log_trace("fd: %d, %s", link->fd(), log.dumps().c_str()); link->send(log.repr(), val); } break; case BinlogCommand::KDEL: case BinlogCommand::HDEL: case BinlogCommand::ZDEL: case BinlogCommand::QPOP_BACK: case BinlogCommand::QPOP_FRONT: log_trace("fd: %d, %s", link->fd(), log.dumps().c_str()); link->send(log.repr()); break; } return 1; }
int BackendSync::Client::sync(BinlogQueue *logs){ Binlog log; while(1){ int ret = 0; uint64_t expect_seq = this->last_seq + 1; if(this->status == Client::COPY && this->last_seq == 0){ ret = logs->find_last(&log); }else{ ret = logs->find_next(expect_seq, &log); } if(ret == 0){ return 0; } // writes that are out of copied range will be discarded. if(this->status == Client::COPY && log.key() > this->last_key){ log_trace("fd: %d, last_key: '%s', drop: %s", link->fd(), hexmem(this->last_key.data(), this->last_key.size()).c_str(), log.dumps().c_str()); this->last_seq = log.seq(); //if(this->iter){ // delete this->iter; // this->iter = NULL; //} continue; } if(this->last_seq != 0 && log.seq() != expect_seq){ log_warn("fd: %d, OUT_OF_SYNC! log.seq: %" PRIu64", expect_seq: %" PRIu64"", link->fd(), log.seq(), expect_seq ); this->status = Client::OUT_OF_SYNC; return 1; } // update last_seq this->last_seq = log.seq(); char type = log.type(); if(type == BinlogType::MIRROR && this->is_mirror){ if(this->last_seq - this->last_noop_seq >= 1000){ this->noop(); return 1; }else{ continue; } } break; } int ret = 0; std::string val; switch(log.cmd()){ case BinlogCommand::KSET: case BinlogCommand::HSET: case BinlogCommand::ZSET: ret = backend->ssdb->raw_get(log.key(), &val); if(ret == -1){ log_error("fd: %d, raw_get error!", link->fd()); }else if(ret == 0){ //log_debug("%s", hexmem(log.key().data(), log.key().size()).c_str()); log_trace("fd: %d, skip not found: %s", link->fd(), log.dumps().c_str()); }else{ log_trace("fd: %d, %s", link->fd(), log.dumps().c_str()); link->send(log.repr(), val); } break; case BinlogCommand::KDEL: case BinlogCommand::HDEL: case BinlogCommand::ZDEL: log_trace("fd: %d, %s", link->fd(), log.dumps().c_str()); link->send(log.repr()); break; } return 1; }