void ProducerStateTable::del(string key, string op /*= DEL_COMMAND*/, string prefix) { // Assembly redis command args into a string vector vector<string> args; args.push_back("EVALSHA"); args.push_back(m_shaDel); args.push_back("3"); args.push_back(getChannelName()); args.push_back(getKeySetName()); args.push_back(getKeyName(key)); args.push_back("G"); args.push_back(key); args.push_back("''"); // Transform data structure vector<const char *> args1; transform(args.begin(), args.end(), back_inserter(args1), [](const string &s) { return s.c_str(); } ); // Invoke redis command RedisCommand command; command.formatArgv((int)args1.size(), &args1[0], NULL); m_pipe->push(command, REDIS_REPLY_NIL); if (!m_buffered) { m_pipe->flush(); } }
void ProducerStateTable::set(string key, vector<FieldValueTuple> &values, string op /*= SET_COMMAND*/, string prefix) { // Assembly redis command args into a string vector vector<string> args; args.push_back("EVALSHA"); args.push_back(m_shaSet); args.push_back(to_string(values.size() + 2)); args.push_back(getChannelName()); args.push_back(getKeySetName()); args.insert(args.end(), values.size(), getKeyName(key)); args.push_back("G"); args.push_back(key); for (auto& iv: values) { args.push_back(fvField(iv)); args.push_back(fvValue(iv)); } // Transform data structure vector<const char *> args1; transform(args.begin(), args.end(), back_inserter(args1), [](const string &s) { return s.c_str(); } ); // Invoke redis command RedisCommand command; command.formatArgv((int)args1.size(), &args1[0], NULL); m_pipe->push(command, REDIS_REPLY_NIL); if (!m_buffered) { m_pipe->flush(); } }
ConsumerStateTable::ConsumerStateTable(DBConnector *db, std::string tableName) : RedisTransactioner(db) , TableName_KeySet(tableName) , POP_BATCH_SIZE(128) { for (;;) { RedisReply watch(m_db, "WATCH " + getKeySetName(), REDIS_REPLY_STATUS); watch.checkStatusOK(); multi(); enqueue(std::string("SCARD ") + getKeySetName(), REDIS_REPLY_INTEGER); subscribe(m_db, getChannelName()); bool succ = exec(); if (succ) break; } RedisReply r(dequeueReply()); setQueueLength(r.getReply<long long int>()); }
void ConsumerStateTable::pops(std::deque<KeyOpFieldsValuesTuple> &vkco, std::string /*prefix*/) { static std::string luaScript = "local ret = {}\n" "local keys = redis.call('SPOP', KEYS[1], ARGV[1])\n" "local n = table.getn(keys)\n" "for i = 1, n do\n" "local key = keys[i]\n" "local values = redis.call('HGETALL', KEYS[2] .. key)\n" "table.insert(ret, {key, values})\n" "end\n" "return ret\n"; static std::string sha = loadRedisScript(m_db, luaScript); RedisCommand command; command.format( "EVALSHA %s 2 %s %s: %d ''", sha.c_str(), getKeySetName().c_str(), getTableName().c_str(), POP_BATCH_SIZE); RedisReply r(m_db, command); auto ctx0 = r.getContext(); vkco.clear(); // if the set is empty, return an empty kco object if (ctx0->type == REDIS_REPLY_NIL) { return; } assert(ctx0->type == REDIS_REPLY_ARRAY); size_t n = ctx0->elements; vkco.resize(n); for (size_t ie = 0; ie < n; ie++) { auto& kco = vkco[ie]; auto& values = kfvFieldsValues(kco); assert(values.empty()); auto& ctx = ctx0->element[ie]; assert(ctx->elements == 2); assert(ctx->element[0]->type == REDIS_REPLY_STRING); std::string key = ctx->element[0]->str; kfvKey(kco) = key; assert(ctx->element[1]->type == REDIS_REPLY_ARRAY); auto ctx1 = ctx->element[1]; for (size_t i = 0; i < ctx1->elements / 2; i++) { FieldValueTuple e; fvField(e) = ctx1->element[i * 2]->str; fvValue(e) = ctx1->element[i * 2 + 1]->str; values.push_back(e); } // if there is no field-value pair, the key is already deleted if (values.empty()) { kfvOp(kco) = DEL_COMMAND; } else { kfvOp(kco) = SET_COMMAND; } } }