Skip to content

Commit 11239a4

Browse files
Implement substr command (#212)
The PR implements the SUBSTR command, although it's deprecated it's still available. The SUBSTR command is a clone of the GETRANGE command, tests have been duplicated and adapted as needed.
1 parent 00b8b28 commit 11239a4

File tree

2 files changed

+402
-0
lines changed

2 files changed

+402
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/**
2+
* Copyright (C) 2018-2022 Daniele Salvatore Albano
3+
* All rights reserved.
4+
*
5+
* This software may be modified and distributed under the terms
6+
* of the BSD license. See the LICENSE file for details.
7+
**/
8+
9+
#include <stdint.h>
10+
#include <stdbool.h>
11+
#include <stddef.h>
12+
#include <string.h>
13+
#include <strings.h>
14+
#include <arpa/inet.h>
15+
#include <assert.h>
16+
17+
#include "misc.h"
18+
#include "exttypes.h"
19+
#include "log/log.h"
20+
#include "clock.h"
21+
#include "spinlock.h"
22+
#include "data_structures/small_circular_queue/small_circular_queue.h"
23+
#include "data_structures/double_linked_list/double_linked_list.h"
24+
#include "data_structures/queue_mpmc/queue_mpmc.h"
25+
#include "slab_allocator.h"
26+
#include "data_structures/hashtable/mcmp/hashtable.h"
27+
#include "data_structures/hashtable/mcmp/hashtable_op_get.h"
28+
#include "data_structures/hashtable/spsc/hashtable_spsc.h"
29+
#include "protocol/redis/protocol_redis.h"
30+
#include "protocol/redis/protocol_redis_reader.h"
31+
#include "protocol/redis/protocol_redis_writer.h"
32+
#include "module/module.h"
33+
#include "network/io/network_io_common.h"
34+
#include "config.h"
35+
#include "fiber.h"
36+
#include "network/channel/network_channel.h"
37+
#include "storage/io/storage_io_common.h"
38+
#include "storage/channel/storage_channel.h"
39+
#include "storage/db/storage_db.h"
40+
#include "module/redis/module_redis.h"
41+
#include "module/redis/module_redis_connection.h"
42+
#include "module/redis/module_redis_command.h"
43+
#include "network/network.h"
44+
#include "worker/worker_stats.h"
45+
#include "worker/worker_context.h"
46+
47+
#define TAG "module_redis_command_substr"
48+
49+
MODULE_REDIS_COMMAND_FUNCPTR_COMMAND_END(substr) {
50+
bool return_res = false;
51+
storage_db_entry_index_t *entry_index = NULL;
52+
module_redis_command_substr_context_t *context = connection_context->command.context;
53+
54+
entry_index = storage_db_get_entry_index_for_read(
55+
connection_context->db,
56+
context->key.value.key,
57+
context->key.value.length);
58+
59+
if (unlikely(!entry_index)) {
60+
return_res = module_redis_connection_send_string_null(connection_context);
61+
goto end;
62+
}
63+
64+
off_t range_start = context->start.value;
65+
off_t range_end = context->end.value;
66+
67+
if (range_start < 0) {
68+
range_start += (off_t)entry_index->value->size;
69+
}
70+
71+
if (range_end < 0) {
72+
range_end += (off_t)entry_index->value->size;
73+
}
74+
75+
if (unlikely(range_end < range_start)) {
76+
return_res = module_redis_connection_send_string(connection_context, "", 0);
77+
goto end;
78+
}
79+
80+
off_t range_length = range_end - range_start + 1;
81+
82+
if (unlikely(range_start > entry_index->value->size || range_length <= 0)) {
83+
return_res = module_redis_connection_send_string(connection_context, "", 0);
84+
goto end;
85+
}
86+
87+
if (unlikely(range_start + range_length > entry_index->value->size)) {
88+
range_length = (off_t)entry_index->value->size - range_start;
89+
}
90+
91+
return_res = module_redis_command_stream_entry_range(
92+
connection_context->network_channel,
93+
connection_context->db,
94+
entry_index,
95+
range_start,
96+
range_length);
97+
98+
end:
99+
100+
if (likely(entry_index)) {
101+
storage_db_entry_index_status_decrease_readers_counter(entry_index, NULL);
102+
entry_index = NULL;
103+
}
104+
105+
return return_res;
106+
}

0 commit comments

Comments
 (0)