|
| 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