summaryrefslogtreecommitdiff
path: root/src/modules/INTRO.md
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/INTRO.md')
-rw-r--r--src/modules/INTRO.md857
1 files changed, 857 insertions, 0 deletions
diff --git a/src/modules/INTRO.md b/src/modules/INTRO.md
new file mode 100644
index 0000000..3ac6a46
--- /dev/null
+++ b/src/modules/INTRO.md
@@ -0,0 +1,857 @@
+Redis Modules: an introduction to the API
+===
+
+The modules documentation is composed of the following files:
+
+* `INTRO.md` (this file). An overview about Redis Modules system and API. It's a good idea to start your reading here.
+* `API.md` is generated from module.c top comments of RedisMoule functions. It is a good reference in order to understand how each function works.
+* `TYPES.md` covers the implementation of native data types into modules.
+* `BLOCK.md` shows how to write blocking commands that will not reply immediately, but will block the client, without blocking the Redis server, and will provide a reply whenever will be possible.
+
+Redis modules make possible to extend Redis functionality using external
+modules, implementing new Redis commands at a speed and with features
+similar to what can be done inside the core itself.
+
+Redis modules are dynamic libraries, that can be loaded into Redis at
+startup or using the `MODULE LOAD` command. Redis exports a C API, in the
+form of a single C header file called `redismodule.h`. Modules are meant
+to be written in C, however it will be possible to use C++ or other languages
+that have C binding functionalities.
+
+Modules are designed in order to be loaded into different versions of Redis,
+so a given module does not need to be designed, or recompiled, in order to
+run with a specific version of Redis. For this reason, the module will
+register to the Redis core using a specific API version. The current API
+version is "1".
+
+This document is about an alpha version of Redis modules. API, functionalities
+and other details may change in the future.
+
+# Loading modules
+
+In order to test the module you are developing, you can load the module
+using the following `redis.conf` configuration directive:
+
+ loadmodule /path/to/mymodule.so
+
+It is also possible to load a module at runtime using the following command:
+
+ MODULE LOAD /path/to/mymodule.so
+
+In order to list all loaded modules, use:
+
+ MODULE LIST
+
+Finally, you can unload (and later reload if you wish) a module using the
+following command:
+
+ MODULE UNLOAD mymodule
+
+Note that `mymodule` above is not the filename without the `.so` suffix, but
+instead, the name the module used to register itself into the Redis core.
+The name can be obtained using `MODULE LIST`. However it is good practice
+that the filename of the dynamic library is the same as the name the module
+uses to register itself into the Redis core.
+
+# The simplest module you can write
+
+In order to show the different parts of a module, here we'll show a very
+simple module that implements a command that outputs a random number.
+
+ #include "redismodule.h"
+ #include <stdlib.h>
+
+ int HelloworldRand_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
+ RedisModule_ReplyWithLongLong(ctx,rand());
+ return REDISMODULE_OK;
+ }
+
+ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
+ if (RedisModule_Init(ctx,"helloworld",1,REDISMODULE_APIVER_1)
+ == REDISMODULE_ERR) return REDISMODULE_ERR;
+
+ if (RedisModule_CreateCommand(ctx,"helloworld.rand",
+ HelloworldRand_RedisCommand) == REDISMODULE_ERR)
+ return REDISMODULE_ERR;
+
+ return REDISMODULE_OK;
+ }
+
+The example module has two functions. One implements a command called
+HELLOWORLD.RAND. This function is specific of that module. However the
+other function called `RedisModule_OnLoad()` must be present in each
+Redis module. It is the entry point for the module to be initialized,
+register its commands, and potentially other private data structures
+it uses.
+
+Note that it is a good idea for modules to call commands with the
+name of the module followed by a dot, and finally the command name,
+like in the case of `HELLOWORLD.RAND`. This way it is less likely to
+have collisions.
+
+Note that if different modules have colliding commands, they'll not be
+able to work in Redis at the same time, since the function
+`RedisModule_CreateCommand` will fail in one of the modules, so the module
+loading will abort returning an error condition.
+
+# Module initialization
+
+The above example shows the usage of the function `RedisModule_Init()`.
+It should be the first function called by the module `OnLoad` function.
+The following is the function prototype:
+
+ int RedisModule_Init(RedisModuleCtx *ctx, const char *modulename,
+ int module_version, int api_version);
+
+The `Init` function announces the Redis core that the module has a given
+name, its version (that is reported by `MODULE LIST`), and that is willing
+to use a specific version of the API.
+
+If the API version is wrong, the name is already taken, or there are other
+similar errors, the function will return `REDISMODULE_ERR`, and the module
+`OnLoad` function should return ASAP with an error.
+
+Before the `Init` function is called, no other API function can be called,
+otherwise the module will segfault and the Redis instance will crash.
+
+The second function called, `RedisModule_CreateCommand`, is used in order
+to register commands into the Redis core. The following is the prototype:
+
+ int RedisModule_CreateCommand(RedisModuleCtx *ctx, const char *cmdname,
+ RedisModuleCmdFunc cmdfunc);
+
+As you can see, most Redis modules API calls all take as first argument
+the `context` of the module, so that they have a reference to the module
+calling it, to the command and client executing a given command, and so forth.
+
+To create a new command, the above function needs the context, the command
+name, and the function pointer of the function implementing the command,
+which must have the following prototype:
+
+
+ int mycommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);
+
+The command function arguments are just the context, that will be passed
+to all the other API calls, the command argument vector, and total number
+of arguments, as passed by the user.
+
+As you can see, the arguments are provided as pointers to a specific data
+type, the `RedisModuleString`. This is an opaque data type you have API
+functions to access and use, direct access to its fields is never needed.
+
+Zooming into the example command implementation, we can find another call:
+
+ int RedisModule_ReplyWithLongLong(RedisModuleCtx *ctx, long long integer);
+
+This function returns an integer to the client that invoked the command,
+exactly like other Redis commands do, like for example `INCR` or `SCARD`.
+
+# Setup and dependencies of a Redis module
+
+Redis modules don't depend on Redis or some other library, nor they
+need to be compiled with a specific `redismodule.h` file. In order
+to create a new module, just copy a recent version of `redismodule.h`
+in your source tree, link all the libraries you want, and create
+a dynamic library having the `RedisModule_OnLoad()` function symbol
+exported.
+
+The module will be able to load into different versions of Redis.
+
+# Passing configuration parameters to Redis modules
+
+When the module is loaded with the `MODULE LOAD` command, or using the
+`loadmodule` directive in the `redis.conf` file, the user is able to pass
+configuration parameters to the module by adding arguments after the module
+file name:
+
+ loadmodule mymodule.so foo bar 1234
+
+In the above example the strings `foo`, `bar` and `123` will be passed
+to the module `OnLoad()` function in the `argv` argument as an array
+of RedisModuleString pointers. The number of arguments passed is into `argc`.
+
+The way you can access those strings will be explained in the rest of this
+document. Normally the module will store the module configuration parameters
+in some `static` global variable that can be accessed module wide, so that
+the configuration can change the behavior of different commands.
+
+# Working with RedisModuleString objects
+
+The command argument vector `argv` passed to module commands, and the
+return value of other module APIs functions, are of type `RedisModuleString`.
+
+Usually you directly pass module strings to other API calls, however sometimes
+you may need to directly access the string object.
+
+There are a few functions in order to work with string objects:
+
+ const char *RedisModule_StringPtrLen(RedisModuleString *string, size_t *len);
+
+The above function accesses a string by returning its pointer and setting its
+length in `len`.
+You should never write to a string object pointer, as you can see from the
+`const` pointer qualifier.
+
+However, if you want, you can create new string objects using the following
+API:
+
+ RedisModuleString *RedisModule_CreateString(RedisModuleCtx *ctx, const char *ptr, size_t len);
+
+The string returned by the above command must be freed using a corresponding
+call to `RedisModule_FreeString()`:
+
+ void RedisModule_FreeString(RedisModuleString *str);
+
+However if you want to avoid having to free strings, the automatic memory
+management, covered later in this document, can be a good alternative, by
+doing it for you.
+
+Note that the strings provided via the argument vector `argv` never need
+to be freed. You only need to free new strings you create, or new strings
+returned by other APIs, where it is specified that the returned string must
+be freed.
+
+## Creating strings from numbers or parsing strings as numbers
+
+Creating a new string from an integer is a very common operation, so there
+is a function to do this:
+
+ RedisModuleString *mystr = RedisModule_CreateStringFromLongLong(ctx,10);
+
+Similarly in order to parse a string as a number:
+
+ long long myval;
+ if (RedisModule_StringToLongLong(ctx,argv[1],&myval) == REDISMODULE_OK) {
+ /* Do something with 'myval' */
+ }
+
+## Accessing Redis keys from modules
+
+Most Redis modules, in order to be useful, have to interact with the Redis
+data space (this is not always true, for example an ID generator may
+never touch Redis keys). Redis modules have two different APIs in order to
+access the Redis data space, one is a low level API that provides very
+fast access and a set of functions to manipulate Redis data structures.
+The other API is more high level, and allows to call Redis commands and
+fetch the result, similarly to how Lua scripts access Redis.
+
+The high level API is also useful in order to access Redis functionalities
+that are not available as APIs.
+
+In general modules developers should prefer the low level API, because commands
+implemented using the low level API run at a speed comparable to the speed
+of native Redis commands. However there are definitely use cases for the
+higher level API. For example often the bottleneck could be processing the
+data and not accessing it.
+
+Also note that sometimes using the low level API is not harder compared to
+the higher level one.
+
+# Calling Redis commands
+
+The high level API to access Redis is the sum of the `RedisModule_Call()`
+function, together with the functions needed in order to access the
+reply object returned by `Call()`.
+
+`RedisModule_Call` uses a special calling convention, with a format specifier
+that is used to specify what kind of objects you are passing as arguments
+to the function.
+
+Redis commands are invoked just using a command name and a list of arguments.
+However when calling commands, the arguments may originate from different
+kind of strings: null-terminated C strings, RedisModuleString objects as
+received from the `argv` parameter in the command implementation, binary
+safe C buffers with a pointer and a length, and so forth.
+
+For example if I want to call `INCRBY` using a first argument (the key)
+a string received in the argument vector `argv`, which is an array
+of RedisModuleString object pointers, and a C string representing the
+number "10" as second argument (the increment), I'll use the following
+function call:
+
+ RedisModuleCallReply *reply;
+ reply = RedisModule_Call(ctx,"INCR","sc",argv[1],"10");
+
+The first argument is the context, and the second is always a null terminated
+C string with the command name. The third argument is the format specifier
+where each character corresponds to the type of the arguments that will follow.
+In the above case `"sc"` means a RedisModuleString object, and a null
+terminated C string. The other arguments are just the two arguments as
+specified. In fact `argv[1]` is a RedisModuleString and `"10"` is a null
+terminated C string.
+
+This is the full list of format specifiers:
+
+* **c** -- Null terminated C string pointer.
+* **b** -- C buffer, two arguments needed: C string pointer and `size_t` length.
+* **s** -- RedisModuleString as received in `argv` or by other Redis module APIs returning a RedisModuleString object.
+* **l** -- Long long integer.
+* **v** -- Array of RedisModuleString objects.
+* **!** -- This modifier just tells the function to replicate the command to slaves and AOF. It is ignored from the point of view of arguments parsing.
+
+The function returns a `RedisModuleCallReply` object on success, on
+error NULL is returned.
+
+NULL is returned when the command name is invalid, the format specifier uses
+characters that are not recognized, or when the command is called with the
+wrong number of arguments. In the above cases the `errno` var is set to `EINVAL`. NULL is also returned when, in an instance with Cluster enabled, the target
+keys are about non local hash slots. In this case `errno` is set to `EPERM`.
+
+## Working with RedisModuleCallReply objects.
+
+`RedisModuleCall` returns reply objects that can be accessed using the
+`RedisModule_CallReply*` family of functions.
+
+In order to obtain the type or reply (corresponding to one of the data types
+supported by the Redis protocol), the function `RedisModule_CallReplyType()`
+is used:
+
+ reply = RedisModule_Call(ctx,"INCR","sc",argv[1],"10");
+ if (RedisModule_CallReplyType(reply) == REDISMODULE_REPLY_INTEGER) {
+ long long myval = RedisModule_CallReplyInteger(reply);
+ /* Do something with myval. */
+ }
+
+Valid reply types are:
+
+* `REDISMODULE_REPLY_STRING` Bulk string or status replies.
+* `REDISMODULE_REPLY_ERROR` Errors.
+* `REDISMODULE_REPLY_INTEGER` Signed 64 bit integers.
+* `REDISMODULE_REPLY_ARRAY` Array of replies.
+* `REDISMODULE_REPLY_NULL` NULL reply.
+
+Strings, errors and arrays have an associated length. For strings and errors
+the length corresponds to the length of the string. For arrays the length
+is the number of elements. To obtain the reply length the following function
+is used:
+
+ size_t reply_len = RedisModule_CallReplyLength(reply);
+
+In order to obtain the value of an integer reply, the following function is used, as already shown in the example above:
+
+ long long reply_integer_val = RedisModule_CallReplyInteger(reply);
+
+Called with a reply object of the wrong type, the above function always
+returns `LLONG_MIN`.
+
+Sub elements of array replies are accessed this way:
+
+ RedisModuleCallReply *subreply;
+ subreply = RedisModule_CallReplyArrayElement(reply,idx);
+
+The above function returns NULL if you try to access out of range elements.
+
+Strings and errors (which are like strings but with a different type) can
+be accessed using in the following way, making sure to never write to
+the resulting pointer (that is returned as as `const` pointer so that
+misusing must be pretty explicit):
+
+ size_t len;
+ char *ptr = RedisModule_CallReplyStringPtr(reply,&len);
+
+If the reply type is not a string or an error, NULL is returned.
+
+RedisCallReply objects are not the same as module string objects
+(RedisModuleString types). However sometimes you may need to pass replies
+of type string or integer, to API functions expecting a module string.
+
+When this is the case, you may want to evaluate if using the low level
+API could be a simpler way to implement your command, or you can use
+the following function in order to create a new string object from a
+call reply of type string, error or integer:
+
+ RedisModuleString *mystr = RedisModule_CreateStringFromCallReply(myreply);
+
+If the reply is not of the right type, NULL is returned.
+The returned string object should be released with `RedisModule_FreeString()`
+as usually, or by enabling automatic memory management (see corresponding
+section).
+
+# Releasing call reply objects
+
+Reply objects must be freed using `RedisModule_FreeCallReply`. For arrays,
+you need to free only the top level reply, not the nested replies.
+Currently the module implementation provides a protection in order to avoid
+crashing if you free a nested reply object for error, however this feature
+is not guaranteed to be here forever, so should not be considered part
+of the API.
+
+If you use automatic memory management (explained later in this document)
+you don't need to free replies (but you still could if you wish to release
+memory ASAP).
+
+## Returning values from Redis commands
+
+Like normal Redis commands, new commands implemented via modules must be
+able to return values to the caller. The API exports a set of functions for
+this goal, in order to return the usual types of the Redis protocol, and
+arrays of such types as elemented. Also errors can be returned with any
+error string and code (the error code is the initial uppercase letters in
+the error message, like the "BUSY" string in the "BUSY the sever is busy" error
+message).
+
+All the functions to send a reply to the client are called
+`RedisModule_ReplyWith<something>`.
+
+To return an error, use:
+
+ RedisModule_ReplyWithError(RedisModuleCtx *ctx, const char *err);
+
+There is a predefined error string for key of wrong type errors:
+
+ REDISMODULE_ERRORMSG_WRONGTYPE
+
+Example usage:
+
+ RedisModule_ReplyWithError(ctx,"ERR invalid arguments");
+
+We already saw how to reply with a long long in the examples above:
+
+ RedisModule_ReplyWithLongLong(ctx,12345);
+
+To reply with a simple string, that can't contain binary values or newlines,
+(so it's suitable to send small words, like "OK") we use:
+
+ RedisModule_ReplyWithSimpleString(ctx,"OK");
+
+It's possible to reply with "bulk strings" that are binary safe, using
+two different functions:
+
+ int RedisModule_ReplyWithStringBuffer(RedisModuleCtx *ctx, const char *buf, size_t len);
+
+ int RedisModule_ReplyWithString(RedisModuleCtx *ctx, RedisModuleString *str);
+
+The first function gets a C pointer and length. The second a RedisMoudleString
+object. Use one or the other depending on the source type you have at hand.
+
+In order to reply with an array, you just need to use a function to emit the
+array length, followed by as many calls to the above functions as the number
+of elements of the array are:
+
+ RedisModule_ReplyWithArray(ctx,2);
+ RedisModule_ReplyWithStringBuffer(ctx,"age",3);
+ RedisModule_ReplyWithLongLong(ctx,22);
+
+To return nested arrays is easy, your nested array element just uses another
+call to `RedisModule_ReplyWithArray()` followed by the calls to emit the
+sub array elements.
+
+## Returning arrays with dynamic length
+
+Sometimes it is not possible to know beforehand the number of items of
+an array. As an example, think of a Redis module implementing a FACTOR
+command that given a number outputs the prime factors. Instead of
+factorializing the number, storing the prime factors into an array, and
+later produce the command reply, a better solution is to start an array
+reply where the length is not known, and set it later. This is accomplished
+with a special argument to `RedisModule_ReplyWithArray()`:
+
+ RedisModule_ReplyWithArray(ctx, REDISMODULE_POSTPONED_ARRAY_LEN);
+
+The above call starts an array reply so we can use other `ReplyWith` calls
+in order to produce the array items. Finally in order to set the length
+se use the following call:
+
+ RedisModule_ReplySetArrayLength(ctx, number_of_items);
+
+In the case of the FACTOR command, this translates to some code similar
+to this:
+
+ RedisModule_ReplyWithArray(ctx, REDISMODULE_POSTPONED_ARRAY_LEN);
+ number_of_factors = 0;
+ while(still_factors) {
+ RedisModule_ReplyWithLongLong(ctx, some_factor);
+ number_of_factors++;
+ }
+ RedisModule_ReplySetArrayLength(ctx, number_of_factors);
+
+Another common use case for this feature is iterating over the arrays of
+some collection and only returning the ones passing some kind of filtering.
+
+It is possible to have multiple nested arrays with postponed reply.
+Each call to `SetArray()` will set the length of the latest corresponding
+call to `ReplyWithArray()`:
+
+ RedisModule_ReplyWithArray(ctx, REDISMODULE_POSTPONED_ARRAY_LEN);
+ ... generate 100 elements ...
+ RedisModule_ReplyWithArray(ctx, REDISMODULE_POSTPONED_ARRAY_LEN);
+ ... generate 10 elements ...
+ RedisModule_ReplySetArrayLength(ctx, 10);
+ RedisModule_ReplySetArrayLength(ctx, 100);
+
+This creates a 100 items array having as last element a 10 items array.
+
+# Arity and type checks
+
+Often commands need to check that the number of arguments and type of the key
+is correct. In order to report a wrong arity, there is a specific function
+called `RedisModule_WrongArity()`. The usage is trivial:
+
+ if (argc != 2) return RedisModule_WrongArity(ctx);
+
+Checking for the wrong type involves opening the key and checking the type:
+
+ 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);
+ }
+
+Note that you often want to proceed with a command both if the key
+is of the expected type, or if it's empty.
+
+## Low level access to keys
+
+Low level access to keys allow to perform operations on value objects associated
+to keys directly, with a speed similar to what Redis uses internally to
+implement the built-in commands.
+
+Once a key is opened, a key pointer is returned that will be used with all the
+other low level API calls in order to perform operations on the key or its
+associated value.
+
+Because the API is meant to be very fast, it cannot do too many run-time
+checks, so the user must be aware of certain rules to follow:
+
+* Opening the same key multiple times where at least one instance is opened for writing, is undefined and may lead to crashes.
+* While a key is open, it should only be accessed via the low level key API. For example opening a key, then calling DEL on the same key using the `RedisModule_Call()` API will result into a crash. However it is safe to open a key, perform some operation with the low level API, closing it, then using other APIs to manage the same key, and later opening it again to do some more work.
+
+In order to open a key the `RedisModule_OpenKey` function is used. It returns
+a key pointer, that we'll use with all the next calls to access and modify
+the value:
+
+ RedisModuleKey *key;
+ key = RedisModule_OpenKey(ctx,argv[1],REDISMODULE_READ);
+
+The second argument is the key name, that must be a `RedisModuleString` object.
+The third argument is the mode: `REDISMODULE_READ` or `REDISMODULE_WRITE`.
+It is possible to use `|` to bitwise OR the two modes to open the key in
+both modes. Currently a key opened for writing can also be accessed for reading
+but this is to be considered an implementation detail. The right mode should
+be used in sane modules.
+
+You can open non exisitng keys for writing, since the keys will be created
+when an attempt to write to the key is performed. However when opening keys
+just for reading, `RedisModule_OpenKey` will return NULL if the key does not
+exist.
+
+Once you are done using a key, you can close it with:
+
+ RedisModule_CloseKey(key);
+
+Note that if automatic memory management is enabled, you are not forced to
+close keys. When the module function returns, Redis will take care to close
+all the keys which are still open.
+
+## Getting the key type
+
+In order to obtain the value of a key, use the `RedisModule_KeyType()` function:
+
+ int keytype = RedisModule_KeyType(key);
+
+It returns one of the following values:
+
+ REDISMODULE_KEYTYPE_EMPTY
+ REDISMODULE_KEYTYPE_STRING
+ REDISMODULE_KEYTYPE_LIST
+ REDISMODULE_KEYTYPE_HASH
+ REDISMODULE_KEYTYPE_SET
+ REDISMODULE_KEYTYPE_ZSET
+
+The above are just the usual Redis key types, with the addition of an empty
+type, that signals the key pointer is associated with an empty key that
+does not yet exists.
+
+## Creating new keys
+
+To create a new key, open it for writing and then write to it using one
+of the key writing functions. Example:
+
+ RedisModuleKey *key;
+ key = RedisModule_OpenKey(ctx,argv[1],REDISMODULE_READ);
+ if (RedisModule_KeyType(key) == REDISMODULE_KEYTYPE_EMPTY) {
+ RedisModule_StringSet(key,argv[2]);
+ }
+
+## Deleting keys
+
+Just use:
+
+ RedisModule_DeleteKey(key);
+
+The function returns `REDISMODULE_ERR` if the key is not open for writing.
+Note that after a key gets deleted, it is setup in order to be targeted
+by new key commands. For example `RedisModule_KeyType()` will return it is
+an empty key, and writing to it will create a new key, possibly of another
+type (depending on the API used).
+
+## Managing key expires (TTLs)
+
+To control key expires two functions are provided, that are able to set,
+modify, get, and unset the time to live associated with a key.
+
+One function is used in order to query the current expire of an open key:
+
+ mstime_t RedisModule_GetExpire(RedisModuleKey *key);
+
+The function returns the time to live of the key in milliseconds, or
+`REDISMODULE_NO_EXPIRE` as a special value to signal the key has no associated
+expire or does not exist at all (you can differentiate the two cases checking
+if the key type is `REDISMODULE_KEYTYPE_EMPTY`).
+
+In order to change the expire of a key the following function is used instead:
+
+ int RedisModule_SetExpire(RedisModuleKey *key, mstime_t expire);
+
+When called on a non existing key, `REDISMODULE_ERR` is returned, because
+the function can only associate expires to existing open keys (non existing
+open keys are only useful in order to create new values with data type
+specific write operations).
+
+Again the `expire` time is specified in milliseconds. If the key has currently
+no expire, a new expire is set. If the key already have an expire, it is
+replaced with the new value.
+
+If the key has an expire, and the special value `REDISMODULE_NO_EXPIRE` is
+used as a new expire, the expire is removed, similarly to the Redis
+`PERSIST` command. In case the key was already persistent, no operation is
+performed.
+
+## Obtaining the length of values
+
+There is a single function in order to retrieve the length of the value
+associated to an open key. The returned length is value-specific, and is
+the string length for strings, and the number of elements for the aggregated
+data types (how many elements there is in a list, set, sorted set, hash).
+
+ size_t len = RedisModule_ValueLength(key);
+
+If the key does not exist, 0 is returned by the function:
+
+## String type API
+
+Setting a new string value, like the Redis `SET` command does, is performed
+using:
+
+ int RedisModule_StringSet(RedisModuleKey *key, RedisModuleString *str);
+
+The function works exactly like the Redis `SET` command itself, that is, if
+there is a prior value (of any type) it will be deleted.
+
+Accessing existing string values is performed using DMA (direct memory
+access) for speed. The API will return a pointer and a length, so that's
+possible to access and, if needed, modify the string directly.
+
+ size_t len, j;
+ char *myptr = RedisModule_StringDMA(key,&len,REDISMODULE_WRITE);
+ for (j = 0; j < len; j++) myptr[j] = 'A';
+
+In the above example we write directly on the string. Note that if you want
+to write, you must be sure to ask for `WRITE` mode.
+
+DMA pointers are only valid if no other operations are performed with the key
+before using the pointer, after the DMA call.
+
+Sometimes when we want to manipulate strings directly, we need to change
+their size as well. For this scope, the `RedisModule_StringTruncate` function
+is used. Example:
+
+ RedisModule_StringTruncate(mykey,1024);
+
+The function truncates, or enlarges the string as needed, padding it with
+zero bytes if the previos length is smaller than the new length we request.
+If the string does not exist since `key` is associated to an open empty key,
+a string value is created and associated to the key.
+
+Note that every time `StringTruncate()` is called, we need to re-obtain
+the DMA pointer again, since the old may be invalid.
+
+## List type API
+
+It's possible to push and pop values from list values:
+
+ int RedisModule_ListPush(RedisModuleKey *key, int where, RedisModuleString *ele);
+ RedisModuleString *RedisModule_ListPop(RedisModuleKey *key, int where);
+
+In both the APIs the `where` argument specifies if to push or pop from tail
+or head, using the following macros:
+
+ REDISMODULE_LIST_HEAD
+ REDISMODULE_LIST_TAIL
+
+Elements returned by `RedisModule_ListPop()` are like strings craeted with
+`RedisModule_CreateString()`, they must be released with
+`RedisModule_FreeString()` or by enabling automatic memory management.
+
+## Set type API
+
+Work in progress.
+
+## Sorted set type API
+
+Documentation missing, please refer to the top comments inside `module.c`
+for the following functions:
+
+* `RedisModule_ZsetAdd`
+* `RedisModule_ZsetIncrby`
+* `RedisModule_ZsetScore`
+* `RedisModule_ZsetRem`
+
+And for the sorted set iterator:
+
+* `RedisModule_ZsetRangeStop`
+* `RedisModule_ZsetFirstInScoreRange`
+* `RedisModule_ZsetLastInScoreRange`
+* `RedisModule_ZsetFirstInLexRange`
+* `RedisModule_ZsetLastInLexRange`
+* `RedisModule_ZsetRangeCurrentElement`
+* `RedisModule_ZsetRangeNext`
+* `RedisModule_ZsetRangePrev`
+* `RedisModule_ZsetRangeEndReached`
+
+## Hash type API
+
+Documentation missing, please refer to the top comments inside `module.c`
+for the following functions:
+
+* `RedisModule_HashSet`
+* `RedisModule_HashGet`
+
+## Iterating aggregated values
+
+Work in progress.
+
+# Replicating commands
+
+If you want to use module commands exactly like normal Redis commands, in the
+context of replicated Redis instances, or using the AOF file for persistence,
+it is important for module commands to handle their replication in a consistent
+way.
+
+When using the higher level APIs to invoke commands, replication happens
+automatically if you use the "!" modifier in the format string of
+`RedisModule_Call()` as in the following example:
+
+ reply = RedisModule_Call(ctx,"INCR","!sc",argv[1],"10");
+
+As you can see the format specifier is `"!sc"`. The bang is not parsed as a
+format specifier, but it internally flags the command as "must replicate".
+
+If you use the above programming style, there are no problems.
+However sometimes things are more complex than that, and you use the low level
+API. In this case, if there are no side effects in the command execution, and
+it consistently always performs the same work, what is possible to do is to
+replicate the command verbatim as the user executed it. To do that, you just
+need to call the following function:
+
+ RedisModule_ReplicateVerbatim(ctx);
+
+When you use the above API, you should not use any other replication function
+since they are not guaranteed to mix well.
+
+However this is not the only option. It's also possible to exactly tell
+Redis what commands to replicate as the effect of the command execution, using
+an API similar to `RedisModule_Call()` but that instead of calling the command
+sends it to the AOF / slaves stream. Example:
+
+ RedisModule_Replicate(ctx,"INCRBY","cl","foo",my_increment);
+
+It's possible to call `RedisModule_Replicate` multiple times, and each
+will emit a command. All the sequence emitted is wrapped between a
+`MULTI/EXEC` transaction, so that the AOF and replication effects are the
+same as executing a single command.
+
+Note that `Call()` replication and `Replicate()` replication have a rule,
+in case you want to mix both forms of replication (not necessarily a good
+idea if there are simpler approaches). Commands replicated with `Call()`
+are always the first emitted in the final `MULTI/EXEC` block, while all
+the commands emitted with `Replicate()` will follow.
+
+# Automatic memory management
+
+Normally when writing programs in the C language, programmers need to manage
+memory manually. This is why the Redis modules API has functions to release
+strings, close open keys, free replies, and so forth.
+
+However given that commands are executed in a contained environment and
+with a set of strict APIs, Redis is able to provide automatic memory management
+to modules, at the cost of some performance (most of the time, a very low
+cost).
+
+When automatic memory management is enabled:
+
+1. You don't need to close open keys.
+2. You don't need to free replies.
+3. You don't need to free RedisModuleString objects.
+
+However you can still do it, if you want. For example, automatic memory
+management may be active, but inside a loop allocating a lot of strings,
+you may still want to free strings no longer used.
+
+In order to enable automatic memory management, just call the following
+function at the start of the command implementation:
+
+ RedisModule_AutoMemory(ctx);
+
+Automatic memory management is usually the way to go, however experienced
+C programmers may not use it in order to gain some speed and memory usage
+benefit.
+
+# Allocating memory into modules
+
+Normal C programs use `malloc()` and `free()` in order to allocate and
+release memory dynamically. While in Redis modules the use of malloc is
+not technically forbidden, it is a lot better to use the Redis Modules
+specific functions, that are exact replacements for `malloc`, `free`,
+`realloc` and `strdup`. These functions are:
+
+ void *RedisModule_Alloc(size_t bytes);
+ void* RedisModule_Realloc(void *ptr, size_t bytes);
+ void RedisModule_Free(void *ptr);
+ void RedisModule_Calloc(size_t nmemb, size_t size);
+ char *RedisModule_Strdup(const char *str);
+
+They work exactly like their `libc` equivalent calls, however they use
+the same allocator Redis uses, and the memory allocated using these
+functions is reported by the `INFO` command in the memory section, is
+accounted when enforcing the `maxmemory` policy, and in general is
+a first citizen of the Redis executable. On the contrar, the method
+allocated inside modules with libc `malloc()` is transparent to Redis.
+
+Another reason to use the modules functions in order to allocate memory
+is that, when creating native data types inside modules, the RDB loading
+functions can return deserialized strings (from the RDB file) directly
+as `RedisModule_Alloc()` allocations, so they can be used directly to
+populate data structures after loading, instead of having to copy them
+to the data structure.
+
+## Pool allocator
+
+Sometimes in commands implementations, it is required to perform many
+small allocations that will be not retained at the end of the command
+execution, but are just functional to execute the command itself.
+
+This work can be more easily accomplished using the Redis pool allocator:
+
+ void *RedisModule_PoolAlloc(RedisModuleCtx *ctx, size_t bytes);
+
+It works similarly to `malloc()`, and returns memory aligned to the
+next power of two of greater or equal to `bytes` (for a maximum alignment
+of 8 bytes). However it allocates memory in blocks, so it the overhead
+of the allocations is small, and more important, the memory allocated
+is automatically released when the command returns.
+
+So in general short living allocations are a good candidates for the pool
+allocator.
+
+# Writing commands compatible with Redis Cluster
+
+Documentation missing, please check the following functions inside `module.c`:
+
+ RedisModule_IsKeysPositionRequest(ctx);
+ RedisModule_KeyAtPos(ctx,pos);