redict/tests/modules/test_lazyfree.c
Drew DeVault cdd60793d5 tests/modules: fix remaining redis => redict cases
Non-API impacting renames.

Signed-off-by: Drew DeVault <sir@cmpwn.com>
2024-03-25 12:45:47 +01:00

203 lines
6.4 KiB
C

// SPDX-FileCopyrightText: 2024 Redict Contributors
// SPDX-FileCopyrightText: 2024 Salvatore Sanfilippo <antirez at gmail dot com>
//
// SPDX-License-Identifier: BSD-3-Clause
// SPDX-License-Identifier: LGPL-3.0-only
/* This module emulates a linked list for lazyfree testing of modules, which
is a simplified version of 'hellotype.c'
*/
#include "redictmodule.h"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <stdint.h>
static RedictModuleType *LazyFreeLinkType;
struct LazyFreeLinkNode {
int64_t value;
struct LazyFreeLinkNode *next;
};
struct LazyFreeLinkObject {
struct LazyFreeLinkNode *head;
size_t len; /* Number of elements added. */
};
struct LazyFreeLinkObject *createLazyFreeLinkObject(void) {
struct LazyFreeLinkObject *o;
o = RedictModule_Alloc(sizeof(*o));
o->head = NULL;
o->len = 0;
return o;
}
void LazyFreeLinkInsert(struct LazyFreeLinkObject *o, int64_t ele) {
struct LazyFreeLinkNode *next = o->head, *newnode, *prev = NULL;
while(next && next->value < ele) {
prev = next;
next = next->next;
}
newnode = RedictModule_Alloc(sizeof(*newnode));
newnode->value = ele;
newnode->next = next;
if (prev) {
prev->next = newnode;
} else {
o->head = newnode;
}
o->len++;
}
void LazyFreeLinkReleaseObject(struct LazyFreeLinkObject *o) {
struct LazyFreeLinkNode *cur, *next;
cur = o->head;
while(cur) {
next = cur->next;
RedictModule_Free(cur);
cur = next;
}
RedictModule_Free(o);
}
/* LAZYFREELINK.INSERT key value */
int LazyFreeLinkInsert_RedictCommand(RedictModuleCtx *ctx, RedictModuleString **argv, int argc) {
RedictModule_AutoMemory(ctx); /* Use automatic memory management. */
if (argc != 3) return RedictModule_WrongArity(ctx);
RedictModuleKey *key = RedictModule_OpenKey(ctx,argv[1],
REDICTMODULE_READ|REDICTMODULE_WRITE);
int type = RedictModule_KeyType(key);
if (type != REDICTMODULE_KEYTYPE_EMPTY &&
RedictModule_ModuleTypeGetType(key) != LazyFreeLinkType)
{
return RedictModule_ReplyWithError(ctx,REDICTMODULE_ERRORMSG_WRONGTYPE);
}
long long value;
if ((RedictModule_StringToLongLong(argv[2],&value) != REDICTMODULE_OK)) {
return RedictModule_ReplyWithError(ctx,"ERR invalid value: must be a signed 64 bit integer");
}
struct LazyFreeLinkObject *hto;
if (type == REDICTMODULE_KEYTYPE_EMPTY) {
hto = createLazyFreeLinkObject();
RedictModule_ModuleTypeSetValue(key,LazyFreeLinkType,hto);
} else {
hto = RedictModule_ModuleTypeGetValue(key);
}
LazyFreeLinkInsert(hto,value);
RedictModule_SignalKeyAsReady(ctx,argv[1]);
RedictModule_ReplyWithLongLong(ctx,hto->len);
RedictModule_ReplicateVerbatim(ctx);
return REDICTMODULE_OK;
}
/* LAZYFREELINK.LEN key */
int LazyFreeLinkLen_RedictCommand(RedictModuleCtx *ctx, RedictModuleString **argv, int argc) {
RedictModule_AutoMemory(ctx); /* Use automatic memory management. */
if (argc != 2) return RedictModule_WrongArity(ctx);
RedictModuleKey *key = RedictModule_OpenKey(ctx,argv[1],
REDICTMODULE_READ);
int type = RedictModule_KeyType(key);
if (type != REDICTMODULE_KEYTYPE_EMPTY &&
RedictModule_ModuleTypeGetType(key) != LazyFreeLinkType)
{
return RedictModule_ReplyWithError(ctx,REDICTMODULE_ERRORMSG_WRONGTYPE);
}
struct LazyFreeLinkObject *hto = RedictModule_ModuleTypeGetValue(key);
RedictModule_ReplyWithLongLong(ctx,hto ? hto->len : 0);
return REDICTMODULE_OK;
}
void *LazyFreeLinkRdbLoad(RedictModuleIO *rdb, int encver) {
if (encver != 0) {
return NULL;
}
uint64_t elements = RedictModule_LoadUnsigned(rdb);
struct LazyFreeLinkObject *hto = createLazyFreeLinkObject();
while(elements--) {
int64_t ele = RedictModule_LoadSigned(rdb);
LazyFreeLinkInsert(hto,ele);
}
return hto;
}
void LazyFreeLinkRdbSave(RedictModuleIO *rdb, void *value) {
struct LazyFreeLinkObject *hto = value;
struct LazyFreeLinkNode *node = hto->head;
RedictModule_SaveUnsigned(rdb,hto->len);
while(node) {
RedictModule_SaveSigned(rdb,node->value);
node = node->next;
}
}
void LazyFreeLinkAofRewrite(RedictModuleIO *aof, RedictModuleString *key, void *value) {
struct LazyFreeLinkObject *hto = value;
struct LazyFreeLinkNode *node = hto->head;
while(node) {
RedictModule_EmitAOF(aof,"LAZYFREELINK.INSERT","sl",key,node->value);
node = node->next;
}
}
void LazyFreeLinkFree(void *value) {
LazyFreeLinkReleaseObject(value);
}
size_t LazyFreeLinkFreeEffort(RedictModuleString *key, const void *value) {
REDICTMODULE_NOT_USED(key);
const struct LazyFreeLinkObject *hto = value;
return hto->len;
}
void LazyFreeLinkUnlink(RedictModuleString *key, const void *value) {
REDICTMODULE_NOT_USED(key);
REDICTMODULE_NOT_USED(value);
/* Here you can know which key and value is about to be freed. */
}
int RedictModule_OnLoad(RedictModuleCtx *ctx, RedictModuleString **argv, int argc) {
REDICTMODULE_NOT_USED(argv);
REDICTMODULE_NOT_USED(argc);
if (RedictModule_Init(ctx,"lazyfreetest",1,REDICTMODULE_APIVER_1)
== REDICTMODULE_ERR) return REDICTMODULE_ERR;
/* We only allow our module to be loaded when the Redict core version is greater than the version of my module */
if (RedictModule_GetTypeMethodVersion() < REDICTMODULE_TYPE_METHOD_VERSION) {
return REDICTMODULE_ERR;
}
RedictModuleTypeMethods tm = {
.version = REDICTMODULE_TYPE_METHOD_VERSION,
.rdb_load = LazyFreeLinkRdbLoad,
.rdb_save = LazyFreeLinkRdbSave,
.aof_rewrite = LazyFreeLinkAofRewrite,
.free = LazyFreeLinkFree,
.free_effort = LazyFreeLinkFreeEffort,
.unlink = LazyFreeLinkUnlink,
};
LazyFreeLinkType = RedictModule_CreateDataType(ctx,"test_lazy",0,&tm);
if (LazyFreeLinkType == NULL) return REDICTMODULE_ERR;
if (RedictModule_CreateCommand(ctx,"lazyfreelink.insert",
LazyFreeLinkInsert_RedictCommand,"write deny-oom",1,1,1) == REDICTMODULE_ERR)
return REDICTMODULE_ERR;
if (RedictModule_CreateCommand(ctx,"lazyfreelink.len",
LazyFreeLinkLen_RedictCommand,"readonly",1,1,1) == REDICTMODULE_ERR)
return REDICTMODULE_ERR;
return REDICTMODULE_OK;
}