Exemple #1
0
/* This is a simple command to test replication. Because of the "!" modified
 * in the RedisModule_Call() call, the two INCRs get replicated.
 * Also note how the ECHO is replicated in an unexpected position (check
 * comments the function implementation). */
int HelloRepl1_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
{
    RedisModuleCallReply *reply;
    RedisModule_AutoMemory(ctx);

    /* This will be replicated *after* the two INCR statements, since
     * the Call() replication has precedence, so the actual replication
     * stream will be:
     *
     * MULTI
     * INCR foo
     * INCR bar
     * ECHO c foo
     * EXEC
     */
    RedisModule_Replicate(ctx,"ECHO","c","foo");

    /* Using the "!" modifier we replicate the command if it
     * modified the dataset in some way. */
    reply = RedisModule_Call(ctx,"INCR","c!","foo");
    reply = RedisModule_Call(ctx,"INCR","c!","bar");

    RedisModule_ReplyWithLongLong(ctx,0);

    return REDISMODULE_OK;
}
Exemple #2
0
void RMUtil_SCAN(RedisModuleCtx *ctx, const char *pattern, RedisModuleString **keys, size_t *key_count) {
    int scan_idx = 0;               /* SCAN cursor. */
    size_t total_keys = 0;          /* Number of keys retrieved. */
    RedisModuleCallReply *reply;

    /* Consume SCAN */
    do {
        reply = RedisModule_Call(ctx, "SCAN", "lcc", scan_idx, "MATCH", pattern);

        /* First element is the scan cursor, 0 indicates end of SCAN. */
        RedisModuleCallReply *element = RedisModule_CallReplyArrayElement(reply, 0);
        scan_idx = RedisModule_CallReplyInteger(element);

        /* Process SCAN results. */
        RedisModuleCallReply *scan_results = RedisModule_CallReplyArrayElement(reply, 1);
        /* Number of elements in replay. */
        size_t keys_count = RedisModule_CallReplyLength(scan_results);

        /* Extract SCAN result elements. */
        for(int idx = 0; idx < keys_count && *key_count > total_keys; idx++) {
            element = RedisModule_CallReplyArrayElement(scan_results, idx);
            RedisModuleString *key = RedisModule_CreateStringFromCallReply(element);
            keys[total_keys] = key;
            total_keys++;
        }
        RedisModule_FreeCallReply(reply);
    } while(scan_idx != 0);

    /* Update number of stores fetched. */
    *key_count = total_keys;
}
Exemple #3
0
RMUtilInfo *RMUtil_HGetAll(RedisModuleCtx *ctx, RedisModuleString *id) {
    RedisModuleCallReply *reply = RedisModule_Call(ctx, "HGETALL", "s", id);
    if(RedisModule_CallReplyType(reply) != REDISMODULE_REPLY_ARRAY) {
        printf("ERROE expecting an array \n");
        return NULL;
    }
    
    size_t reply_len = RedisModule_CallReplyLength(reply);
    RMUtilInfo *hgetall = malloc(sizeof(RMUtilInfo));
    hgetall->numEntries = reply_len/2;
    hgetall->entries = malloc(sizeof(RMUtilInfoEntry) * hgetall->numEntries);
    
    // Consume HGETALL
    for(int idx = 0; idx < reply_len; idx+=2) {
        RedisModuleCallReply *subreply;
        subreply = RedisModule_CallReplyArrayElement(reply, idx);

        size_t len;
        char *key = strdup(RedisModule_CallReplyStringPtr(subreply, &len));
        key[len] = 0;
        hgetall->entries[idx/2].key = key;
        
        subreply = RedisModule_CallReplyArrayElement(reply, idx+1);
        char *val = strdup(RedisModule_CallReplyStringPtr(subreply, &len));
        val[len] = 0;
        hgetall->entries[idx/2].val = val;
    }

    RedisModule_FreeCallReply(reply);
    return hgetall;
}
Exemple #4
0
/* HELLO.PUSH.CALL2
 * This is exaxctly as HELLO.PUSH.CALL, but shows how we can reply to the
 * client using directly a reply object that Call() returned. */
int HelloPushCall2_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
{
    if (argc != 3) return RedisModule_WrongArity(ctx);

    RedisModuleCallReply *reply;

    reply = RedisModule_Call(ctx,"RPUSH","ss",argv[1],argv[2]);
    RedisModule_ReplyWithCallReply(ctx,reply);
    RedisModule_FreeCallReply(reply);
    return REDISMODULE_OK;
}
Exemple #5
0
static int cmd_password_hcheck(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
    RedisModuleCallReply *reply;

    if (argc != 4) {
        RedisModule_WrongArity(ctx);
        return REDISMODULE_OK;
    }

    reply = RedisModule_Call(ctx, "HGET", "ss", argv[1], argv[2]);
    validate(ctx, reply, argv[3]);
    return REDISMODULE_OK;
}
Exemple #6
0
int TestModule(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
  RedisModule_AutoMemory(ctx);

  /* TODO: calling flushall but checking only for db 0. */
  RedisModuleCallReply *r = RedisModule_Call(ctx, "DBSIZE", "");
  if (RedisModule_CallReplyInteger(r) != 0) {
    RedisModule_ReplyWithError(ctx,
                               "ERR test must be run on an empty instance");
    return REDISMODULE_ERR;
  }

  RMUtil_Test(testMSIsMember);

  RedisModule_ReplyWithSimpleString(ctx, "PASS");
  return REDISMODULE_OK;
}
static int router_simple_command(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
    RedisModule_AutoMemory(ctx);

    if (argc < 2) {
        RedisModule_WrongArity(ctx);
        return REDISMODULE_OK;
    }

    RedisModuleCallReply *reply;
    size_t len;
    const char *realCmd = RedisModule_StringPtrLen(argv[1], &len);

    if (argc == 2) {
        reply = RedisModule_Call(ctx, realCmd, "");
    } else {
        char *fmt = (char *) malloc(argc-1);
        memset(fmt, 's', argc-2);
        fmt[argc-2] = '\0';

        ffi_cif cif;
        ffi_type **ffi_argv = (ffi_type **)malloc(sizeof(ffi_type *) * (argc + 1));
        void *result;
        int i;
        for (i = 0; i < argc+1; i++) {
            ffi_argv[i] = &ffi_type_pointer;
        }
        void **values = (void **) malloc(sizeof(void *) * (argc + 1));
        values[0] = &ctx;
        values[1] = &realCmd;
        values[2] = &fmt;
        for (i = 3; i < argc + 1; i++) {
            values[i] = &argv[i-1];
        }

        if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, (argc + 1), &ffi_type_pointer, ffi_argv) == FFI_OK) {
            ffi_call(&cif, FFI_FN(RedisModule_Call), &result, values);
        }
        reply = (RedisModuleCallReply *) result;
    }
    if (reply == NULL) {
        const char *err = "command error";
        RedisModule_ReplyWithError(ctx, err);
    } else {
        RedisModule_ReplyWithCallReply(ctx, reply);
    }
    return REDISMODULE_OK;
}
Exemple #8
0
int testMSIsMember(RedisModuleCtx *ctx) {
  RedisModuleCallReply *r;

  r = RedisModule_Call(ctx, "msismember", "ccc", "s1", "s2", "ele");
  RMUtil_Assert(RedisModule_CallReplyInteger(r) == 0);
  r = RedisModule_Call(ctx, "SADD", "ccc", "s1", "ele", "foo");
  r = RedisModule_Call(ctx, "msismember", "ccc", "s1", "s2", "ele");
  RMUtil_Assert(RedisModule_CallReplyInteger(r) == 1);
  r = RedisModule_Call(ctx, "SADD", "cc", "s2", "bar");
  r = RedisModule_Call(ctx, "msismember", "ccc", "s1", "s2", "ele");
  RMUtil_Assert(RedisModule_CallReplyInteger(r) == 1);
  r = RedisModule_Call(ctx, "SADD", "cc", "s2", "ele");
  r = RedisModule_Call(ctx, "msismember", "ccc", "s1", "s2", "ele");
  RMUtil_Assert(RedisModule_CallReplyInteger(r) == 2);

  r = RedisModule_Call(ctx, "FLUSHALL", "");

  return 0;
}
Exemple #9
0
/* HELLO.LIST.SUM.LEN returns the total length of all the items inside
 * a Redis list, by using the high level Call() API.
 * This command is an example of the array reply access. */
int HelloListSumLen_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
{
    if (argc != 2) return RedisModule_WrongArity(ctx);

    RedisModuleCallReply *reply;

    reply = RedisModule_Call(ctx,"LRANGE","sll",argv[1],(long long)0,(long long)-1);
    size_t strlen = 0;
    size_t items = RedisModule_CallReplyLength(reply);
    size_t j;
    for (j = 0; j < items; j++) {
        RedisModuleCallReply *ele = RedisModule_CallReplyArrayElement(reply,j);
        strlen += RedisModule_CallReplyLength(ele);
    }
    RedisModule_FreeCallReply(reply);
    RedisModule_ReplyWithLongLong(ctx,strlen);
    return REDISMODULE_OK;
}
Exemple #10
0
/*
* MSISMEMBER key1 [key2 ...] member
* Checks for membership in multiple sets.
* Reply: Integer, the count of sets to which the member belongs.
*/
int MSIsMemberCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
  if (argc < 3) {
    if (RedisModule_IsKeysPositionRequest(ctx))
      /* TODO: handle this once the getkey-api allows signalling errors */
      return REDISMODULE_OK;
    else
      return RedisModule_WrongArity(ctx);
  }

  if (RedisModule_IsKeysPositionRequest(ctx)) {
    size_t i;
    for (i = 1; i < argc - 1; i++) RedisModule_KeyAtPos(ctx, i);
    return REDISMODULE_OK;
  }

  RedisModule_AutoMemory(ctx);

  int iele = argc - 1;
  size_t count = 0;
  int i;
  for (i = 1; i < iele; i++) {
    RedisModuleKey *key =
        RedisModule_OpenKey(ctx, argv[i], REDISMODULE_READ | REDISMODULE_WRITE);

    if (RedisModule_KeyType(key) == REDISMODULE_KEYTYPE_EMPTY) continue;

    if (RedisModule_KeyType(key) != REDISMODULE_KEYTYPE_SET) {
      RedisModule_ReplyWithError(ctx, REDISMODULE_ERRORMSG_WRONGTYPE);
      return REDISMODULE_ERR;
    }

    RedisModuleCallReply *rep =
        RedisModule_Call(ctx, "SISMEMBER", "ss", argv[i], argv[iele]);
    RMUTIL_ASSERT_NOERROR(rep)

    count += RedisModule_CallReplyInteger(rep);
  }

  RedisModule_ReplyWithLongLong(ctx, count);
  return REDISMODULE_OK;
}
Exemple #11
0
static int cmd_password_hset(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
    RedisModuleCallReply *reply;
    size_t len;
    char crypt_buf[64];
    char *hash;

    if (argc != 4) {
        RedisModule_WrongArity(ctx);
        return REDISMODULE_OK;
    }

    hash = do_crypt(RedisModule_StringPtrLen(argv[3], &len), crypt_buf, sizeof(crypt_buf));
    if (!hash) {
        RedisModule_ReplyWithError(ctx, "ERR hash error");
        return REDISMODULE_ERR;
    }
    reply = RedisModule_Call(ctx, "HSET", "ssc!", argv[1], argv[2], hash);
    RedisModule_ReplyWithCallReply(ctx, reply);

    return REDISMODULE_OK;
}
Exemple #12
0
RMUtilInfo *RMUtil_GetRedisInfo(RedisModuleCtx *ctx) {
    
    RedisModuleCallReply *r = RedisModule_Call(ctx, "INFO", "c", "all");
    if (r == NULL || RedisModule_CallReplyType(r) == REDISMODULE_REPLY_ERROR) {
        return NULL;
    }
    
    
    int cap = 100; // rough estimate of info lines
    RMUtilInfo *info = malloc(sizeof(RMUtilInfo));
    info->entries = calloc(cap, sizeof(RMUtilInfoEntry));
    
    
    int i = 0;
    char *text = (char *)RedisModule_StringPtrLen(RedisModule_CreateStringFromCallReply(r), NULL);
    char *line = text;
    while (line) {
        char *line = strsep(&text, "\r\n");
        if (line == NULL)  break;
        
        if (!(*line >= 'a' && *line <= 'z')) { //skip non entry lines 
            continue;
        }
        
        char *key = strsep(&line, ":");
        info->entries[i].key = key;
        info->entries[i].val = line;
        printf("Got info '%s' = '%s'\n", key, line);
        i++;
        if (i >= cap) {
            cap *=2;
            info->entries = realloc(info->entries, cap*sizeof(RMUtilInfoEntry));
        }
    } 
    info->numEntries = i;
    
    return info;
    
}