-
Notifications
You must be signed in to change notification settings - Fork 238
Expand file tree
/
Copy pathconfig_types.h
More file actions
240 lines (195 loc) · 6.76 KB
/
config_types.h
File metadata and controls
240 lines (195 loc) · 6.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
/*
* Copyright (C) 2011-2026 Redis Labs Ltd.
*
* This file is part of memtier_benchmark.
*
* memtier_benchmark is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 2.
*
* memtier_benchmark is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with memtier_benchmark. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _CONFIG_TYPES_H
#define _CONFIG_TYPES_H
#ifdef HAVE_PTHREAD_H
#include <pthread.h>
#endif
#include <netinet/in.h>
#include <vector>
#include <string>
#include <atomic>
#include <map>
struct config_range
{
int min;
int max;
config_range() : min(0), max(0) {}
config_range(const char *range_str);
bool is_defined(void) { return max > 0; }
};
struct config_ratio
{
unsigned int a;
unsigned int b;
config_ratio() : a(0), b(0) {}
config_ratio(const char *ratio_str);
bool is_defined(void) { return (a > 0 || b > 0); }
};
struct config_quantiles
{
std::vector<float> quantile_list;
config_quantiles();
config_quantiles(const char *ratio_str);
bool is_defined(void);
inline std::vector<float>::iterator begin() { return quantile_list.begin(); }
inline std::vector<float>::iterator end() { return quantile_list.end(); }
};
struct config_weight_list
{
struct weight_item
{
unsigned int size;
unsigned int weight;
};
std::vector<weight_item> item_list;
std::vector<weight_item>::iterator next_size_iter;
unsigned int next_size_weight;
config_weight_list();
config_weight_list(const char *str);
config_weight_list(const config_weight_list ©);
config_weight_list &operator=(const config_weight_list &rhs);
bool is_defined(void);
unsigned int largest(void);
const char *print(char *buf, int buf_len);
unsigned int get_next_size(void);
};
struct connect_info
{
int ci_family;
int ci_socktype;
int ci_protocol;
socklen_t ci_addrlen;
struct sockaddr *ci_addr;
char addr_buf[sizeof(struct sockaddr_storage)];
};
struct server_addr
{
server_addr(const char *hostname, int port, int resolution);
virtual ~server_addr();
int get_connect_info(struct connect_info *ci);
const char *get_last_error(void) const;
protected:
int resolve(void);
pthread_mutex_t m_mutex;
std::string m_hostname;
int m_port;
struct addrinfo *m_server_addr;
struct addrinfo *m_used_addr;
int m_resolution;
std::atomic<int> m_last_error; // Atomic to prevent data race between resolve() and get_connect_info()
};
// Forward declaration for object_generator
class object_generator;
#define KEY_PLACEHOLDER "__key__"
#define DATA_PLACEHOLDER "__data__"
#define MONITOR_PLACEHOLDER_PREFIX "__monitor_line"
#define MONITOR_RANDOM_PLACEHOLDER "__monitor_line@__"
#define SCAN_CURSOR_PLACEHOLDER "__scan_cursor__"
enum command_arg_type
{
const_type = 0,
key_type = 1,
data_type = 2,
monitor_type = 3,
monitor_random_type = 4,
undefined_type = 5,
scan_cursor_type = 6
};
struct command_arg
{
command_arg(const char *arg, unsigned int arg_len) :
type(undefined_type), data(arg, arg_len), monitor_index(0), has_key_affixes(false)
{
;
}
command_arg_type type;
std::string data;
// For monitor_type, stores the index (1-based)
size_t monitor_index;
// the prefix and suffix strings are used for mixed key placeholder storing of substrings
std::string data_prefix;
std::string data_suffix;
// optimization flag to avoid runtime checks
bool has_key_affixes;
};
struct arbitrary_command
{
arbitrary_command(const char *cmd);
bool set_key_pattern(const char *pattern_str);
bool set_ratio(const char *pattern_str);
bool split_command_to_args();
std::vector<command_arg> command_args;
std::string command;
std::string command_name; // Display name (e.g., "SET (Line 1)" or "SET")
std::string command_type; // Base command type for aggregation (e.g., "SET")
char key_pattern;
unsigned int keys_count;
unsigned int ratio;
bool stats_only; // If true, this is a stats-only slot (not executed, just for stats tracking)
};
struct arbitrary_command_list
{
private:
std::vector<arbitrary_command> commands_list;
public:
arbitrary_command_list() { ; }
arbitrary_command &at(size_t idx) { return commands_list.at(idx); }
const arbitrary_command &at(std::size_t idx) const { return commands_list.at(idx); }
// array subscript operator
arbitrary_command &operator[](std::size_t idx) { return commands_list[idx]; }
const arbitrary_command &operator[](std::size_t idx) const { return commands_list[idx]; }
void add_command(const arbitrary_command &command) { commands_list.push_back(command); }
arbitrary_command &get_last_command() { return commands_list.back(); }
size_t size() const { return commands_list.size(); }
bool is_defined() const { return !commands_list.empty(); }
unsigned int get_max_command_name_length() const
{
unsigned int max_length = 0;
for (size_t i = 0; i < size(); i++) {
if (commands_list[i].command_name.length() > max_length) {
max_length = commands_list[i].command_name.length();
}
}
return max_length;
}
};
struct monitor_command_list
{
private:
std::vector<std::string> commands;
std::vector<std::string> command_types; // Command type for each command (e.g., "SET", "GET")
std::map<std::string, size_t> type_to_stats_index; // Maps command type to stats slot index
std::atomic<size_t> next_index;
public:
monitor_command_list() : next_index(0) { ; }
bool load_from_file(const char *filename);
const std::string &get_command(size_t index) const;
const std::string &get_random_command(object_generator *obj_gen, size_t *out_index) const;
const std::string &get_next_sequential_command(size_t *out_index);
size_t size() const { return commands.size(); }
// Get unique command types found in the file (for stats allocation)
std::vector<std::string> get_unique_command_types() const;
// Set up stats index mapping - called after allocating stats slots
void setup_stats_indices(size_t base_index);
// Get the stats index for a command at the given file index
size_t get_stats_index(size_t cmd_index) const;
// Get the command type for a command at the given file index
const std::string &get_command_type(size_t cmd_index) const;
};
#endif /* _CONFIG_TYPES_H */