TEST_F(LeaseClerkTest, exist) { ++g_client_id; int32_t remove_threshold = 0xffff; LeaseClerkPtr clerk = new LeaseClerk(remove_threshold); uint32_t lease_id = clerk->add(g_client_id); ++g_lease_id; EXPECT_EQ(g_lease_id, lease_id); LeaseEntryPtr entry = clerk->find(g_client_id); EXPECT_NE(0, entry); EXPECT_EQ(g_client_id, entry->client()); EXPECT_EQ(LEASE_TYPE_WRITE, entry->type()); EXPECT_EQ(LEASE_STATUS_RUNNING, entry->status()); EXPECT_EQ(true, entry->is_valid_lease()); EXPECT_EQ(true, clerk->has_valid_lease(g_client_id)); EXPECT_EQ(true, clerk->exist(g_client_id)); clerk->obsolete(g_client_id); EXPECT_EQ(false, clerk->has_valid_lease(g_client_id)); EXPECT_EQ(true, clerk->exist(g_client_id)); EXPECT_EQ(true, clerk->remove(g_client_id)); EXPECT_EQ(false, clerk->has_valid_lease(g_client_id)); EXPECT_EQ(false, clerk->exist(g_client_id)); clerk = 0; }
bool LeaseClerk::has_valid_lease(int64_t id) { RWLock::Lock lock(mutex_, READ_LOCKER); LeaseEntryPtr lease = find(id); if (lease == 0) { //TBSYS_LOG(WARN, "lease not found by id: %"PRI64_PREFIX"d", id); return false; } return lease->is_valid_lease(); }
bool LeaseClerk::change(int64_t id, LeaseStatus status) { RWLock::Lock r_lock(mutex_, READ_LOCKER); LeaseEntryPtr lease = find(id); if (lease == 0) { TBSYS_LOG(ERROR, "lease not found by block id: %u", id); return false; } tbutil::Monitor<tbutil::Mutex>::Lock lock(*lease); lease->change(status); lease->notifyAll(); GFactory::get_timer()->cancel(lease); return true; }
TEST_F(LeaseClerkTest, clear) { int32_t remove_threshold = 0x2; LeaseClerkPtr clerk = new LeaseClerk(remove_threshold); const int MAX_COUNT = 5; for (int i = 0; i < MAX_COUNT; ++i) { ++g_client_id; ++g_lease_id; uint32_t lease_id = clerk->add(g_client_id); EXPECT_EQ(g_lease_id, lease_id); LeaseEntryPtr entry = clerk->find(g_client_id); EXPECT_EQ(g_client_id, entry->client()); } sleep((LeaseEntry::LEASE_EXPIRE_TIME_MS/1000) + 1); clerk->clear(false); clerk = 0; }
bool LeaseClerk::commit(int64_t id, uint32_t lease_id, LeaseStatus status) { LeaseEntryPtr lease = 0; { RWLock::Lock r_lock(mutex_, READ_LOCKER); lease = find(id); if (lease == 0) { TBSYS_LOG(WARN, "lease not found by id: %"PRI64_PREFIX"d", id); return false; } } TBSYS_LOG(DEBUG,"commit : %"PRI64_PREFIX"d, status: %d", id, status); Monitor<Mutex>::Lock lock(*lease); if (lease->id() != lease_id) { lease->notifyAll(); TBSYS_LOG(ERROR, "id: %"PRI64_PREFIX"d lease id not match %u:%u", id, lease->id(), lease_id); return false; } if (!lease->is_valid_lease()) { TBSYS_LOG(WARN, "id: %"PRI64_PREFIX"d has lease, but it: %u was invalid", id, lease_id); lease->change(LEASE_STATUS_EXPIRED); lease->notifyAll(); return false; } lease->change(status); lease->notifyAll(); TBSYS_LOG(DEBUG, "cancel ---------%"PRI64_PREFIX"d", lease->id()); GFactory::get_timer()->cancel(lease); return true; }
TEST_F(LeaseClerkTest, add) { ++g_client_id; int32_t remove_threshold = 0xffff; LeaseClerkPtr clerk = new LeaseClerk(remove_threshold); uint32_t lease_id = clerk->add(g_client_id); EXPECT_EQ(g_lease_id, lease_id); LeaseEntryPtr entry = clerk->find(g_client_id); EXPECT_NE(0, entry); EXPECT_EQ(g_client_id, entry->client()); EXPECT_EQ(LEASE_TYPE_WRITE, entry->type()); EXPECT_EQ(LEASE_STATUS_RUNNING, entry->status()); EXPECT_EQ(true, entry->is_valid_lease()); NsRuntimeGlobalInformation& ngi = GFactory::get_runtime_info(); ngi.destroy_flag_ = NS_DESTROY_FLAGS_YES; EXPECT_EQ(0U, clerk->add(0xff)); ngi.destroy_flag_ = NS_DESTROY_FLAGS_NO; //no wait entry->change(LEASE_STATUS_FINISH); EXPECT_EQ(false, entry->is_valid_lease()); lease_id = clerk->add(g_client_id); ++g_lease_id; EXPECT_EQ(g_lease_id, lease_id); EXPECT_EQ(true, entry->is_valid_lease()); //wait for expire lease_id = clerk->add(g_client_id); ++g_lease_id; EXPECT_EQ(g_lease_id, lease_id); EXPECT_EQ(true, entry->is_valid_lease()); //wait for expired sleep((LeaseEntry::LEASE_EXPIRE_TIME_MS/1000) + 1); clerk = 0; }
uint32_t LeaseClerk::add(int64_t id) { TBSYS_LOG(DEBUG, "client: %"PRI64_PREFIX"d register lease", id); NsRuntimeGlobalInformation& ngi = GFactory::get_runtime_info(); if (ngi.destroy_flag_ == NS_DESTROY_FLAGS_YES) { TBSYS_LOG(WARN, "%s", "add lease fail because nameserver destroyed"); return INVALID_LEASE_ID; } mutex_.rdlock(); uint32_t lease_id = INVALID_LEASE_ID; LeaseEntryPtr lease = 0; LEASE_MAP_ITER iter = leases_.find(id); if ((iter == leases_.end()) || ( iter != leases_.end() && iter->second == 0)) { mutex_.unlock(); goto Next; } lease = iter->second; mutex_.unlock(); if (!lease->is_valid_lease()) { goto Renew; } if (LeaseFactory::gwait_count_ > SYSPARAM_NAMESERVER.max_wait_write_lease_) { TBSYS_LOG(WARN, "lease: %u, current wait thread: %d beyond max_wait: %d", lease->id(), LeaseFactory::gwait_count_, SYSPARAM_NAMESERVER.max_wait_write_lease_); return INVALID_LEASE_ID; } atomic_inc(&LeaseFactory::gwait_count_); //lease was found by id, we must be wait lease->wait_for_expire(); atomic_dec(&LeaseFactory::gwait_count_); if (!lease->is_valid_lease()) { goto Renew; } return INVALID_LEASE_ID; Next: { if (ngi.destroy_flag_ == NS_DESTROY_FLAGS_YES) { TBSYS_LOG(WARN, "%s", "add lease fail because nameserver destroyed"); return INVALID_LEASE_ID; } RWLock::Lock lock(mutex_, WRITE_LOCKER); lease_id = LeaseFactory::new_lease_id(); lease = new LeaseEntry(tbutil::Handle<LeaseClerk>::dynamicCast(this), lease_id, id); std::pair<LEASE_MAP_ITER, bool> res = leases_.insert(LEASE_MAP_ITER::value_type(id, lease)); if (!res.second) { lease = 0; TBSYS_LOG(WARN, "id: %"PRI64_PREFIX"d has been lease" , id); return INVALID_LEASE_ID; } GFactory::get_timer()->schedule(lease, tbutil::Time::milliSeconds(LeaseEntry::LEASE_EXPIRE_TIME_MS)); return lease_id; } Renew: { if (ngi.destroy_flag_ == NS_DESTROY_FLAGS_YES) { TBSYS_LOG(WARN, "%s", "add lease fail because nameserver destroyed"); return INVALID_LEASE_ID; } tbutil::Monitor<tbutil::Mutex>::Lock lock(*lease); if (lease->is_valid_lease()) { TBSYS_LOG(WARN, "id: %"PRI64_PREFIX"d has been lease" , id); return INVALID_LEASE_ID; } lease_id = LeaseFactory::new_lease_id(); lease->reset(lease_id); lease->notifyAll(); GFactory::get_timer()->cancel(lease); GFactory::get_timer()->schedule(lease, tbutil::Time::milliSeconds(LeaseEntry::LEASE_EXPIRE_TIME_MS)); return lease_id; } return INVALID_LEASE_ID; }
TEST_F(LeaseEntryTest, lease_entry) { uint32_t lease_id = 0xff; int64_t client_id = 0xffff; int32_t remove_threshold = 0xffff; LeaseClerkPtr clerk = new LeaseClerk(remove_threshold); LeaseEntryPtr entry = new LeaseEntry(clerk, lease_id, client_id); EXPECT_EQ(lease_id, entry->id()); EXPECT_EQ(client_id, entry->client()); EXPECT_EQ(LEASE_TYPE_WRITE, entry->type()); EXPECT_EQ(LEASE_STATUS_RUNNING, entry->status()); EXPECT_EQ(true, entry->is_valid_lease()); entry->change(LEASE_STATUS_FINISH); EXPECT_EQ(false, entry->is_valid_lease()); entry->change(LEASE_STATUS_FAILED); EXPECT_EQ(false, entry->is_valid_lease()); entry->change(LEASE_STATUS_EXPIRED); EXPECT_EQ(false, entry->is_valid_lease()); entry->change(LEASE_STATUS_CANCELED); EXPECT_EQ(false, entry->is_valid_lease()); entry->change(LEASE_STATUS_OBSOLETE); EXPECT_EQ(false, entry->is_valid_lease()); bool check_time = false; tbutil::Time now = tbutil::Time::now(); EXPECT_EQ(true, entry->is_remove(now, check_time)); check_time = true; EXPECT_EQ(false, entry->is_remove(now, check_time)); now += tbutil::Time::milliSeconds(LeaseEntry::LEASE_EXPIRE_REMOVE_TIME_MS + 3000); EXPECT_EQ(true, entry->is_remove(now, check_time)); lease_id = 0xff + 0xff; entry->reset(lease_id); EXPECT_EQ(lease_id, entry->id()); EXPECT_EQ(client_id, entry->client()); EXPECT_EQ(LEASE_TYPE_WRITE, entry->type()); EXPECT_EQ(LEASE_STATUS_RUNNING, entry->status()); EXPECT_EQ(true, entry->is_valid_lease()); entry->change(LEASE_STATUS_OBSOLETE); EXPECT_EQ(false, entry->is_valid_lease()); EXPECT_EQ(true, entry->wait_for_expire()); entry->change(LEASE_STATUS_RUNNING); EXPECT_EQ(true, entry->is_valid_lease()); EXPECT_EQ(true, entry->wait_for_expire()); }