]> git.proxmox.com Git - ceph.git/blob - ceph/src/dmclock/sim/src/config.cc
import 15.2.0 Octopus source
[ceph.git] / ceph / src / dmclock / sim / src / config.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 /*
5 * Copyright (C) 2016 Red Hat Inc.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License version
9 * 2.1, as published by the Free Software Foundation. See file
10 * COPYING.
11 */
12
13
14 #include <unistd.h>
15 #include <string.h>
16 #include <stdarg.h>
17
18 #include <iostream>
19 #include <vector>
20 #include <list>
21
22 #include "config.h"
23 #include "str_list.h"
24
25
26 static void dashes_to_underscores(const char *input, char *output) {
27 char c = 0;
28 char *o = output;
29 const char *i = input;
30 // first two characters are copied as-is
31 *o = *i++;
32 if (*o++ == '\0')
33 return;
34 *o = *i++;
35 if (*o++ == '\0')
36 return;
37 for (; ((c = *i)); ++i) {
38 if (c == '=') {
39 strcpy(o, i);
40 return;
41 }
42 if (c == '-')
43 *o++ = '_';
44 else
45 *o++ = c;
46 }
47 *o++ = '\0';
48 }
49
50 static int va_ceph_argparse_witharg(std::vector<const char*> &args,
51 std::vector<const char*>::iterator &i, std::string *ret,
52 std::ostream &oss, va_list ap) {
53 const char *first = *i;
54 char tmp[strlen(first)+1];
55 dashes_to_underscores(first, tmp);
56 first = tmp;
57
58 // does this argument match any of the possibilities?
59 while (1) {
60 const char *a = va_arg(ap, char*);
61 if (a == NULL)
62 return 0;
63 int strlen_a = strlen(a);
64 char a2[strlen_a+1];
65 dashes_to_underscores(a, a2);
66 if (strncmp(a2, first, strlen(a2)) == 0) {
67 if (first[strlen_a] == '=') {
68 *ret = first + strlen_a + 1;
69 i = args.erase(i);
70 return 1;
71 }
72 else if (first[strlen_a] == '\0') {
73 // find second part (or not)
74 if (i+1 == args.end()) {
75 oss << "Option " << *i << " requires an argument." << std::endl;
76 i = args.erase(i);
77 return -EINVAL;
78 }
79 i = args.erase(i);
80 *ret = *i;
81 i = args.erase(i);
82 return 1;
83 }
84 }
85 }
86 }
87
88 bool crimson::qos_simulation::ceph_argparse_witharg(std::vector<const char*> &args,
89 std::vector<const char*>::iterator &i, std::string *ret, ...) {
90 int r;
91 va_list ap;
92 va_start(ap, ret);
93 r = va_ceph_argparse_witharg(args, i, ret, std::cerr, ap);
94 va_end(ap);
95 if (r < 0)
96 _exit(1);
97 return r != 0;
98 }
99
100 void crimson::qos_simulation::ceph_argparse_early_args(std::vector<const char*>& args, std::string *conf_file_list) {
101 std::string val;
102
103 std::vector<const char *> orig_args = args;
104
105 for (std::vector<const char*>::iterator i = args.begin(); i != args.end(); ) {
106 if (ceph_argparse_witharg(args, i, &val, "--conf", "-c", (char*)NULL)) {
107 *conf_file_list = val;
108 }
109 else {
110 // ignore
111 ++i;
112 }
113 }
114 return;
115 }
116
117 static bool stobool(const std::string & v) {
118 return !v.empty () &&
119 (strcasecmp (v.c_str (), "true") == 0 ||
120 atoi (v.c_str ()) != 0);
121 }
122
123 int crimson::qos_simulation::parse_config_file(const std::string &fname, sim_config_t &g_conf) {
124 ConfFile cf;
125 std::deque<std::string> err;
126 std::ostringstream warn;
127 int ret = cf.parse_file(fname.c_str(), &err, &warn);
128 if (ret) {
129 // error
130 return ret;
131 }
132
133 std::string val;
134 if (!cf.read("global", "server_groups", val))
135 g_conf.server_groups = std::stoul(val);
136 if (!cf.read("global", "client_groups", val))
137 g_conf.client_groups = std::stoul(val);
138 if (!cf.read("global", "server_random_selection", val))
139 g_conf.server_random_selection = stobool(val);
140 if (!cf.read("global", "server_soft_limit", val))
141 g_conf.server_soft_limit = stobool(val);
142 if (!cf.read("global", "anticipation_timeout", val))
143 g_conf.anticipation_timeout = stod(val);
144
145 for (unsigned i = 0; i < g_conf.server_groups; i++) {
146 srv_group_t st;
147 std::string section = "server." + std::to_string(i);
148 if (!cf.read(section, "server_count", val))
149 st.server_count = std::stoul(val);
150 if (!cf.read(section, "server_iops", val))
151 st.server_iops = std::stoul(val);
152 if (!cf.read(section, "server_threads", val))
153 st.server_threads = std::stoul(val);
154 g_conf.srv_group.push_back(st);
155 }
156
157 for (unsigned i = 0; i < g_conf.client_groups; i++) {
158 cli_group_t ct;
159 std::string section = "client." + std::to_string(i);
160 if (!cf.read(section, "client_count", val))
161 ct.client_count = std::stoul(val);
162 if (!cf.read(section, "client_wait", val))
163 ct.client_wait = std::chrono::seconds(std::stoul(val));
164 if (!cf.read(section, "client_total_ops", val))
165 ct.client_total_ops = std::stoul(val);
166 if (!cf.read(section, "client_server_select_range", val))
167 ct.client_server_select_range = std::stoul(val);
168 if (!cf.read(section, "client_iops_goal", val))
169 ct.client_iops_goal = std::stoul(val);
170 if (!cf.read(section, "client_outstanding_ops", val))
171 ct.client_outstanding_ops = std::stoul(val);
172 if (!cf.read(section, "client_reservation", val))
173 ct.client_reservation = std::stod(val);
174 if (!cf.read(section, "client_limit", val))
175 ct.client_limit = std::stod(val);
176 if (!cf.read(section, "client_weight", val))
177 ct.client_weight = std::stod(val);
178 if (!cf.read(section, "client_req_cost", val))
179 ct.client_req_cost = std::stoul(val);
180 g_conf.cli_group.push_back(ct);
181 }
182
183 return 0;
184 }