int Ardb::BlockForKeys(Context& ctx, const StringArray& keys, const AnyArray& vals, KeyType ktype, uint32 mstimeout) { if (ctx.keyslocked) { FATAL_LOG("Can not modify block dataset when key locked."); } if (mstimeout > 0) { ctx.GetBPop().timeout = (uint64) mstimeout * 1000 + get_current_epoch_micros(); } ctx.GetBPop().block_keytype = ktype; ctx.client->client->BlockRead(); LockGuard<SpinMutexLock> guard(m_block_keys_lock); for (size_t i = 0; i < keys.size(); i++) { KeyPrefix prefix; prefix.ns = ctx.ns; prefix.key.SetString(keys[i], false); if(vals.size() != keys.size()) { ctx.GetBPop().keys.insert(BlockingState::BlockKeyTable::value_type(prefix, NULL)); }else { ctx.GetBPop().keys.insert(BlockingState::BlockKeyTable::value_type(prefix, vals[i])); } m_blocked_ctxs[prefix].insert(&ctx); } return 0; }
int Ardb::UnblockKeys(Context& ctx, bool sync, RedisReply* reply) { if (ctx.keyslocked) { FATAL_LOG("Can not modify block dataset when key locked."); } if (!sync) { ctx.client->client->GetService().AsyncIO(ctx.client->client->GetID(), AsyncUnblockKeysCallback, new ContexWithReply(&ctx, reply)); return 0; } if (NULL != reply) { Channel* ch = ctx.client->client; ch->Write(*reply); } LockGuard<SpinMutexLock> guard(m_block_keys_lock, true); if (ctx.bpop != NULL && !m_blocked_ctxs.empty()) { BlockingState::BlockKeyTable::iterator it = ctx.GetBPop().keys.begin(); while (it != ctx.GetBPop().keys.end()) { const KeyPrefix& prefix = it->first; BlockedContextTable::iterator blocked_found = m_blocked_ctxs.find(prefix); if (blocked_found != m_blocked_ctxs.end()) { ContextSet& blocked_set = blocked_found->second; blocked_set.erase(&ctx); if (blocked_set.empty()) { m_blocked_ctxs.erase(blocked_found); } } it++; } ctx.ClearBPop(); } ctx.client->client->UnblockRead(); return 0; }