/* HELLOTYPE.INSERT key value */ int HelloTypeInsert_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { RedisModule_AutoMemory(ctx); /* Use automatic memory management. */ if (argc != 3) return RedisModule_WrongArity(ctx); RedisModuleKey *key = RedisModule_OpenKey(ctx,argv[1], REDISMODULE_READ|REDISMODULE_WRITE); int type = RedisModule_KeyType(key); if (type != REDISMODULE_KEYTYPE_EMPTY && RedisModule_ModuleTypeGetType(key) != HelloType) { return RedisModule_ReplyWithError(ctx,REDISMODULE_ERRORMSG_WRONGTYPE); } long long value; if ((RedisModule_StringToLongLong(argv[2],&value) != REDISMODULE_OK)) { return RedisModule_ReplyWithError(ctx,"ERR invalid value: must be a signed 64 bit integer"); } /* Create an empty value object if the key is currently empty. */ struct HelloTypeObject *hto; if (type == REDISMODULE_KEYTYPE_EMPTY) { hto = createHelloTypeObject(); RedisModule_ModuleTypeSetValue(key,HelloType,hto); } else { hto = RedisModule_ModuleTypeGetValue(key); } /* Insert the new element. */ HelloTypeInsert(hto,value); RedisModule_ReplyWithLongLong(ctx,hto->len); RedisModule_ReplicateVerbatim(ctx); return REDISMODULE_OK; }
/* This is an example of strings DMA access. Given a key containing a string * it toggles the case of each character from lower to upper case or the * other way around. * * No automatic memory management is used in this example (for the sake * of variety). * * HELLO.TOGGLE.CASE key */ int HelloToggleCase_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { if (argc != 2) return RedisModule_WrongArity(ctx); RedisModuleKey *key = RedisModule_OpenKey(ctx,argv[1], REDISMODULE_READ|REDISMODULE_WRITE); int keytype = RedisModule_KeyType(key); if (keytype != REDISMODULE_KEYTYPE_STRING && keytype != REDISMODULE_KEYTYPE_EMPTY) { RedisModule_CloseKey(key); return RedisModule_ReplyWithError(ctx,REDISMODULE_ERRORMSG_WRONGTYPE); } if (keytype == REDISMODULE_KEYTYPE_STRING) { size_t len, j; char *s = RedisModule_StringDMA(key,&len,REDISMODULE_WRITE); for (j = 0; j < len; j++) { if (isupper(s[j])) { s[j] = tolower(s[j]); } else { s[j] = toupper(s[j]); } } } RedisModule_CloseKey(key); RedisModule_ReplyWithSimpleString(ctx,"OK"); RedisModule_ReplicateVerbatim(ctx); return REDISMODULE_OK; }
/* Another command to show replication. In this case, we call * RedisModule_ReplicateVerbatim() to mean we want just the command to be * propagated to slaves / AOF exactly as it was called by the user. * * This command also shows how to work with string objects. * It takes a list, and increments all the elements (that must have * a numerical value) by 1, returning the sum of all the elements * as reply. * * Usage: HELLO.REPL2 <list-key> */ int HelloRepl2_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { if (argc != 2) return RedisModule_WrongArity(ctx); RedisModule_AutoMemory(ctx); /* Use automatic memory management. */ RedisModuleKey *key = RedisModule_OpenKey(ctx,argv[1], REDISMODULE_READ|REDISMODULE_WRITE); if (RedisModule_KeyType(key) != REDISMODULE_KEYTYPE_LIST) return RedisModule_ReplyWithError(ctx,REDISMODULE_ERRORMSG_WRONGTYPE); size_t listlen = RedisModule_ValueLength(key); long long sum = 0; /* Rotate and increment. */ while(listlen--) { RedisModuleString *ele = RedisModule_ListPop(key,REDISMODULE_LIST_TAIL); long long val; if (RedisModule_StringToLongLong(ele,&val) != REDISMODULE_OK) val = 0; val++; sum += val; RedisModuleString *newele = RedisModule_CreateStringFromLongLong(ctx,val); RedisModule_ListPush(key,REDISMODULE_LIST_HEAD,newele); } RedisModule_ReplyWithLongLong(ctx,sum); RedisModule_ReplicateVerbatim(ctx); return REDISMODULE_OK; }
int UniquePushIVCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { if (argc < 4) { return RedisModule_WrongArity(ctx); } RedisModule_AutoMemory(ctx); // open the key and make sure it is indeed a Hash and not empty RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_READ | REDISMODULE_WRITE); int type = RedisModule_KeyType(key); if (type != REDISMODULE_KEYTYPE_EMPTY && RedisModule_ModuleTypeGetType(key) != UniqueType) { return RedisModule_ReplyWithError(ctx,REDISMODULE_ERRORMSG_WRONGTYPE); } unique *unique; if (type == REDISMODULE_KEYTYPE_EMPTY) { unique = uniqueCreate(); RedisModule_ModuleTypeSetValue(key,UniqueType,unique); } else { unique = RedisModule_ModuleTypeGetValue(key); } sds skey, sval; size_t skeylen, svallen; const char *pkey; unsigned int lvec = argc-3; pkey = RedisModule_StringPtrLen(argv[2], &skeylen); svallen = lvec *8; skey = sdsnewlen(pkey, skeylen); sval = sdsnewlen(NULL, svallen); long long *vec = (long long*)sval; int i; for (i=3; i<argc; i++) { if (REDISMODULE_OK != RedisModule_StringToLongLong(argv[i], vec+i-3)) { return RedisModule_WrongArity(ctx); } } int n = uniquePush(unique, skey, sval, merge_int64); if (n == -1) { RedisModule_ReplyWithError(ctx,REDISMODULE_ERRORMSG_WRONGTYPE); } else { RedisModule_ReplyWithLongLong(ctx, n); } RedisModule_ReplicateVerbatim(ctx); return REDISMODULE_OK; }
/* ## FT.SUGGADD key string score [INCR] [PAYLOAD {payload}] Add a suggestion string to an auto-complete suggestion dictionary. This is disconnected from the index definitions, and leaves creating and updating suggestino dictionaries to the user. ### Parameters: - key: the suggestion dictionary key. - string: the suggestion string we index - score: a floating point number of the suggestion string's weight -INCR: if set, we increment the existing entry of the suggestion by the given score, instead of replacing the score. This is useful for updating the dictionary based on user queries in real time - PAYLOAD: Add a payload to the suggestion string that will be used as additional information. ### Returns: Integer reply: the current size of the suggestion dictionary. */ int RSSuggestAddCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { if (argc < 4 || argc > 7) { return RedisModule_WrongArity(ctx); } int incr = 0, rv = AC_OK; RSPayload payload = {0}; ArgsCursor ac = {0}; ArgsCursor_InitRString(&ac, argv + 4, argc - 4); while (!AC_IsAtEnd(&ac)) { const char *s = AC_GetStringNC(&ac, NULL); if (!strcasecmp(s, "INCR")) { incr = 1; } else if (!strcasecmp(s, "PAYLOAD")) { if ((rv = AC_GetString(&ac, (const char **)&payload.data, &payload.len, 0)) != AC_OK) { return RMUtil_ReplyWithErrorFmt(ctx, "Invalid payload: %s", AC_Strerror(rv)); } } else { return RMUtil_ReplyWithErrorFmt(ctx, "Unknown argument `%s`", s); } } RedisModule_AutoMemory(ctx); /* Use automatic memory management. */ RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_READ | REDISMODULE_WRITE); int type = RedisModule_KeyType(key); if (type != REDISMODULE_KEYTYPE_EMPTY && RedisModule_ModuleTypeGetType(key) != TrieType) { return RedisModule_ReplyWithError(ctx, REDISMODULE_ERRORMSG_WRONGTYPE); } RedisModuleString *val = argv[2]; double score; if ((RedisModule_StringToDouble(argv[3], &score) != REDISMODULE_OK)) { return RedisModule_ReplyWithError(ctx, "ERR invalid score"); } /* Create an empty value object if the key is currently empty. */ Trie *tree; if (type == REDISMODULE_KEYTYPE_EMPTY) { tree = NewTrie(); RedisModule_ModuleTypeSetValue(key, TrieType, tree); } else { tree = RedisModule_ModuleTypeGetValue(key); } /* Insert the new element. */ Trie_Insert(tree, val, score, incr, &payload); RedisModule_ReplyWithLongLong(ctx, tree->size); RedisModule_ReplicateVerbatim(ctx); return REDISMODULE_OK; }
static int UniquePushCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc, mergefn fn) { if (argc != 4) { return RedisModule_WrongArity(ctx); } RedisModule_AutoMemory(ctx); // open the key and make sure it is indeed a Hash and not empty RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_READ | REDISMODULE_WRITE); int type = RedisModule_KeyType(key); if (type != REDISMODULE_KEYTYPE_EMPTY && RedisModule_ModuleTypeGetType(key) != UniqueType) { return RedisModule_ReplyWithError(ctx,REDISMODULE_ERRORMSG_WRONGTYPE); } unique *unique; if (type == REDISMODULE_KEYTYPE_EMPTY) { unique = uniqueCreate(); RedisModule_ModuleTypeSetValue(key,UniqueType,unique); } else { unique = RedisModule_ModuleTypeGetValue(key); } sds skey, sval; size_t skeylen, svallen; const char *pkey, *pval; pkey = RedisModule_StringPtrLen(argv[2], &skeylen); pval = RedisModule_StringPtrLen(argv[3], &svallen); skey = sdsnewlen(pkey, skeylen); sval = sdsnewlen(pval, svallen); int n = uniquePush(unique, skey, sval, fn); if (n == -1) { RedisModule_ReplyWithError(ctx,REDISMODULE_ERRORMSG_WRONGTYPE); } else { RedisModule_ReplyWithLongLong(ctx, n); } RedisModule_ReplicateVerbatim(ctx); return REDISMODULE_OK; }
/* ## FT.SUGDEL key str Delete a string from a suggestion index. ### Parameters: - key: the suggestion dictionary key. - str: the string to delete ### Returns: Integer reply: 1 if the string was found and deleted, 0 otherwise. */ int RSSuggestDelCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { RedisModule_AutoMemory(ctx); /* Use automatic memory management. */ if (argc != 3) return RedisModule_WrongArity(ctx); RedisModule_ReplicateVerbatim(ctx); RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_READ); int type = RedisModule_KeyType(key); if (type != REDISMODULE_KEYTYPE_EMPTY && RedisModule_ModuleTypeGetType(key) != TrieType) { return RedisModule_ReplyWithError(ctx, REDISMODULE_ERRORMSG_WRONGTYPE); } Trie *tree = RedisModule_ModuleTypeGetValue(key); if (!tree) { return RedisModule_ReplyWithLongLong(ctx, 0); } size_t len; const char *str = RedisModule_StringPtrLen(argv[2], &len); return RedisModule_ReplyWithLongLong(ctx, Trie_Delete(tree, str, len)); }