Пример #1
0
 void Ardb::ClearBlockKeys(Context& ctx)
 {
     if (NULL != ctx.block)
     {
         if (ctx.block->blocking_timer_task_id != -1)
         {
             ctx.client->GetService().GetTimer().Cancel(ctx.block->blocking_timer_task_id);
         }
         WatchKeySet::iterator it = ctx.GetBlockContext().keys.begin();
         while (it != ctx.GetBlockContext().keys.end())
         {
             WriteLockGuard<SpinRWLock> guard(m_block_ctx_lock);
             BlockContextTable::iterator fit = m_block_context_table.find(*it);
             if (fit != m_block_context_table.end())
             {
                 fit->second.erase(std::remove(fit->second.begin(), fit->second.end(), &ctx), fit->second.end());
                 if (fit->second.empty())
                 {
                     m_block_context_table.erase(fit);
                 }
             }
         }
         ctx.ClearBlockContext();
     }
 }
Пример #2
0
 void Ardb::AddBlockKey(Context& ctx, const std::string& key)
 {
     DBItemKey kk(ctx.currentDB, key);
     ctx.GetBlockContext().keys.insert(kk);
     WriteLockGuard<SpinRWLock> guard(m_block_ctx_lock);
     m_block_context_table[kk].push_back(&ctx);
 }
Пример #3
0
 int Comms::BRPopLPush(Context& ctx, RedisCommandFrame& cmd)
 {
     uint32 timeout;
     if (!string_touint32(cmd.GetArguments()[cmd.GetArguments().size() - 1], timeout))
     {
         fill_error_reply(ctx.reply, "timeout is not an integer or out of range");
         return 0;
     }
     RPopLPush(ctx, cmd);
     if (ctx.reply.type == REDIS_REPLY_NIL)
     {
         //block;
         AddBlockKey(ctx, cmd.GetArguments()[0]);
         ctx.GetBlockContext().lpop = false;
         ctx.GetBlockContext().push_key = cmd.GetArguments()[1];
         if (NULL != ctx.client)
         {
             ctx.client->DetachFD();
             if (timeout > 0)
             {
                 ctx.block->blocking_timer_task_id = ctx.client->GetService().GetTimer().ScheduleHeapTask(
                         new BlockListTimeout(&ctx), timeout, -1, SECONDS);
             }
         }
         ctx.reply.type = 0;
     }
     return 0;
 }
Пример #4
0
 void Comms::AddBlockKey(Context& ctx, const std::string& keystr)
 {
     WatchKey key(ctx.currentDB, keystr);
     WriteLockGuard<SpinRWLock> guard(m_block_ctx_lock);
     ctx.GetBlockContext().keys.insert(key);
     m_block_context_table[key].insert(&ctx);
 }
Пример #5
0
 void Comms::WakeBlockedList(Context& ctx, const std::string& key)
 {
     std::string v;
     int err =
             ctx.GetBlockContext().lpop ?
                     m_kv_store->LPop(ctx.currentDB, key, v) : m_kv_store->RPop(ctx.currentDB, key, v);
     if (0 == err && !v.empty())
     {
         if (ctx.GetBlockContext().push_key.empty())
         {
             RedisReply& r1 = ctx.reply.AddMember();
             RedisReply& r2 = ctx.reply.AddMember();
             fill_str_reply(r1, key);
             fill_str_reply(r2, v);
             if (!ctx.flags.no_wal)
             {
                 RedisCommandFrame list_pop(ctx.GetBlockContext().lpop ? "lpop" : "rpop");
                 list_pop.AddArg(key);
                 m_repl.WriteWAL(ctx.currentDB, list_pop);
             }
         }
         else
         {
             err = m_kv_store->RPush(ctx.currentDB, ctx.GetBlockContext().push_key, v);
             if (err < 0)
             {
                 ctx.GetBlockContext().lpop ?
                         m_kv_store->LPush(ctx.currentDB, key, v) : m_kv_store->RPush(ctx.currentDB, key, v);
                 FillErrorReply(ctx, err);
             }
             else
             {
                 fill_str_reply(ctx.reply, v);
                 if (!ctx.flags.no_wal)
                 {
                     RedisCommandFrame rpoplpush("rpoplpush");
                     rpoplpush.AddArg(key);
                     m_repl.WriteWAL(ctx.currentDB, rpoplpush);
                 }
             }
         }
         ctx.client->Write(ctx.reply);
         ctx.client->AttachFD();
         ClearBlockKeys(ctx);
     }
 }
Пример #6
0
    int Comms::BLPop(Context& ctx, RedisCommandFrame& cmd)
    {
        uint32 timeout;
        if (!string_touint32(cmd.GetArguments()[cmd.GetArguments().size() - 1], timeout))
        {
            fill_error_reply(ctx.reply, "timeout is not an integer or out of range");
            return 0;
        }
        bool lpop = cmd.GetType() == REDIS_CMD_BLPOP;
        for (uint32 i = 0; i < cmd.GetArguments().size() - 1; i++)
        {
            std::string v;
            int err =
                    lpop ? m_kv_store->LPop(ctx.currentDB, cmd.GetArguments()[i], v) : m_kv_store->RPop(ctx.currentDB,
                                   cmd.GetArguments()[i], v);
            if (0 == err && !v.empty())
            {
                RedisReply& r1 = ctx.reply.AddMember();
                RedisReply& r2 = ctx.reply.AddMember();
                fill_str_reply(r1, cmd.GetArguments()[i]);
                fill_str_reply(r2, v);

                FireKeyChangedEvent(ctx, ctx.currentDB, cmd.GetArguments()[i]);
                RedisCommandFrame list_pop(lpop ? "lpop" : "rpop");
                list_pop.AddArg(cmd.GetArguments()[i]);
                RewriteClientCommand(ctx, list_pop);
                return 0;
            }
            if (err != 0 && err != mmkv::ERR_ENTRY_NOT_EXIST && err != mmkv::ERR_DB_NOT_EXIST)
            {
                FillErrorReply(ctx, err);
                return 0;
            }
        }
        if (NULL != ctx.client)
        {
            ctx.client->DetachFD();
            ctx.GetBlockContext().lpop = cmd.GetType() == REDIS_CMD_BLPOP;
            if (timeout > 0)
            {
                ctx.block->blocking_timer_task_id = ctx.client->GetService().GetTimer().ScheduleHeapTask(
                        new BlockListTimeout(&ctx), timeout, -1, SECONDS);
            }
        }
        for (uint32 i = 0; i < cmd.GetArguments().size() - 1; i++)
        {
            AddBlockKey(ctx, cmd.GetArguments()[i]);
        }
        return 0;
    }