passing object info information with redis module (#138)

* adding object broadcast channel; published on each object table add

* publishing data size to the bcast channel

* bug fix: objectkey

* update object tests to test for data size: C + py

* remove debug

* clang format

* Minor changes.

* Fix error.

* merging with Robert's comments

* clang format for the object table test upgrade
This commit is contained in:
Alexey Tumanov
2016-12-19 21:07:25 -08:00
committed by Robert Nishihara
parent 269f37e26f
commit cb3e6cde9e
7 changed files with 221 additions and 45 deletions
+46 -3
View File
@@ -25,6 +25,7 @@
#define OBJECT_LOCATION_PREFIX "OL:"
#define OBJECT_NOTIFICATION_PREFIX "ON:"
#define TASK_PREFIX "TT:"
#define OBJECT_BCAST "BCAST"
#define OBJECT_CHANNEL_PREFIX "OC:"
@@ -228,11 +229,26 @@ int ObjectTableLookup_RedisCommand(RedisModuleCtx *ctx,
bool PublishObjectNotification(RedisModuleCtx *ctx,
RedisModuleString *client_id,
RedisModuleString *object_id,
RedisModuleString *data_size,
RedisModuleKey *key) {
/* Create a string formatted as "<object id> MANAGERS <manager id1>
* <manager id2> ..." */
RedisModuleString *manager_list =
RedisModule_CreateStringFromString(ctx, object_id);
long long data_size_value;
if (RedisModule_StringToLongLong(data_size, &data_size_value) !=
REDISMODULE_OK) {
return RedisModule_ReplyWithError(ctx, "data_size must be integer");
}
/* Add a space to the payload for human readability. */
RedisModule_StringAppendBuffer(ctx, manager_list, " ", strlen(" "));
/* Append binary data size for this object. */
RedisModule_StringAppendBuffer(ctx, manager_list,
(const char *) &data_size_value,
sizeof(data_size_value));
RedisModule_StringAppendBuffer(ctx, manager_list, " MANAGERS",
strlen(" MANAGERS"));
@@ -328,6 +344,16 @@ int ObjectTableAdd_RedisCommand(RedisModuleCtx *ctx,
/* Sets are not implemented yet, so we use ZSETs instead. */
RedisModule_ZsetAdd(table_key, 0.0, manager, NULL);
RedisModuleString *bcast_client_str =
RedisModule_CreateString(ctx, OBJECT_BCAST, strlen(OBJECT_BCAST));
bool success = PublishObjectNotification(ctx, bcast_client_str, object_id,
data_size, table_key);
if (!success) {
/* The publish failed somehow. */
return RedisModule_ReplyWithError(ctx, "PUBLISH BCAST unsuccessful");
}
RedisModule_FreeString(ctx, bcast_client_str);
/* Get the zset of clients that requested a notification about the
* availability of this object. */
RedisModuleKey *object_notification_key =
@@ -344,14 +370,15 @@ int ObjectTableAdd_RedisCommand(RedisModuleCtx *ctx,
/* Iterate over the list of clients that requested notifiations about the
* availability of this object, and publish notifications to their object
* notification channels. */
do {
RedisModuleString *client_id =
RedisModule_ZsetRangeCurrentElement(object_notification_key, NULL);
/* TODO(rkn): Some computation could be saved by batching the string
* constructions in the multiple calls to PublishObjectNotification
* together. */
bool success =
PublishObjectNotification(ctx, client_id, object_id, table_key);
bool success = PublishObjectNotification(ctx, client_id, object_id,
data_size, table_key);
if (!success) {
/* The publish failed somehow. */
RedisModule_CloseKey(object_notification_key);
@@ -420,7 +447,23 @@ int ObjectTableRequestNotifications_RedisCommand(RedisModuleCtx *ctx,
RedisModule_CloseKey(object_notification_key);
} else {
/* Publish a notification to the client's object notification channel. */
bool success = PublishObjectNotification(ctx, client_id, object_id, key);
/* Extract the data_size first. */
RedisModuleKey *object_info_key;
object_info_key =
OpenPrefixedKey(ctx, OBJECT_INFO_PREFIX, object_id, REDISMODULE_READ);
int keytype = RedisModule_KeyType(key);
if (keytype == REDISMODULE_KEYTYPE_EMPTY) {
RedisModule_CloseKey(object_info_key);
RedisModule_CloseKey(key);
return RedisModule_ReplyWithError(ctx, "requested object not found");
}
RedisModuleString *existing_data_size;
RedisModule_HashGet(object_info_key, REDISMODULE_HASH_CFIELDS,
"data_size", &existing_data_size, NULL);
RedisModule_CloseKey(object_info_key); /* No longer needed. */
bool success = PublishObjectNotification(ctx, client_id, object_id,
existing_data_size, key);
if (!success) {
/* The publish failed somehow. */
RedisModule_CloseKey(key);