resource_quota_server.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. /*
  2. *
  3. * Copyright 2016 gRPC authors.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include <grpc/byte_buffer.h>
  21. #include <grpc/support/alloc.h>
  22. #include <grpc/support/log.h>
  23. #include <grpc/support/time.h>
  24. #include "test/core/end2end/cq_verifier.h"
  25. #include "test/core/end2end/end2end_tests.h"
  26. static void* tag(intptr_t t) { return reinterpret_cast<void*>(t); }
  27. static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
  28. const char* test_name,
  29. grpc_channel_args* client_args,
  30. grpc_channel_args* server_args) {
  31. grpc_end2end_test_fixture f;
  32. gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
  33. f = config.create_fixture(client_args, server_args);
  34. config.init_server(&f, server_args);
  35. config.init_client(&f, client_args);
  36. return f;
  37. }
  38. static gpr_timespec n_seconds_from_now(int n) {
  39. return grpc_timeout_seconds_to_deadline(n);
  40. }
  41. static gpr_timespec five_seconds_from_now(void) {
  42. return n_seconds_from_now(5);
  43. }
  44. static void drain_cq(grpc_completion_queue* cq) {
  45. grpc_event ev;
  46. do {
  47. ev = grpc_completion_queue_next(cq, five_seconds_from_now(), nullptr);
  48. } while (ev.type != GRPC_QUEUE_SHUTDOWN);
  49. }
  50. static void shutdown_server(grpc_end2end_test_fixture* f) {
  51. if (!f->server) return;
  52. grpc_server_shutdown_and_notify(f->server, f->shutdown_cq, tag(1000));
  53. GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_cq, tag(1000),
  54. grpc_timeout_seconds_to_deadline(5),
  55. nullptr)
  56. .type == GRPC_OP_COMPLETE);
  57. grpc_server_destroy(f->server);
  58. f->server = nullptr;
  59. }
  60. static void shutdown_client(grpc_end2end_test_fixture* f) {
  61. if (!f->client) return;
  62. grpc_channel_destroy(f->client);
  63. f->client = nullptr;
  64. }
  65. static void end_test(grpc_end2end_test_fixture* f) {
  66. shutdown_server(f);
  67. shutdown_client(f);
  68. grpc_completion_queue_shutdown(f->cq);
  69. drain_cq(f->cq);
  70. grpc_completion_queue_destroy(f->cq);
  71. grpc_completion_queue_destroy(f->shutdown_cq);
  72. }
  73. /* Creates and returns a grpc_slice containing random alphanumeric characters.
  74. */
  75. static grpc_slice generate_random_slice() {
  76. size_t i;
  77. static const char chars[] = "abcdefghijklmnopqrstuvwxyz1234567890";
  78. char* output;
  79. const size_t output_size = 1024 * 1024;
  80. output = static_cast<char*>(gpr_malloc(output_size));
  81. for (i = 0; i < output_size - 1; ++i) {
  82. output[i] = chars[rand() % static_cast<int>(sizeof(chars) - 1)];
  83. }
  84. output[output_size - 1] = '\0';
  85. grpc_slice out = grpc_slice_from_copied_string(output);
  86. gpr_free(output);
  87. return out;
  88. }
  89. void resource_quota_server(grpc_end2end_test_config config) {
  90. if (config.feature_mask &
  91. FEATURE_MASK_DOES_NOT_SUPPORT_RESOURCE_QUOTA_SERVER) {
  92. return;
  93. }
  94. grpc_resource_quota* resource_quota =
  95. grpc_resource_quota_create("test_server");
  96. grpc_resource_quota_resize(resource_quota, 5 * 1024 * 1024);
  97. #define NUM_CALLS 100
  98. #define CLIENT_BASE_TAG 0x1000
  99. #define SERVER_START_BASE_TAG 0x2000
  100. #define SERVER_RECV_BASE_TAG 0x3000
  101. #define SERVER_END_BASE_TAG 0x4000
  102. grpc_arg arg;
  103. arg.key = const_cast<char*>(GRPC_ARG_RESOURCE_QUOTA);
  104. arg.type = GRPC_ARG_POINTER;
  105. arg.value.pointer.p = resource_quota;
  106. arg.value.pointer.vtable = grpc_resource_quota_arg_vtable();
  107. grpc_channel_args args = {1, &arg};
  108. grpc_end2end_test_fixture f =
  109. begin_test(config, "resource_quota_server", nullptr, &args);
  110. /* Create large request and response bodies. These are big enough to require
  111. * multiple round trips to deliver to the peer, and their exact contents of
  112. * will be verified on completion. */
  113. grpc_slice request_payload_slice = generate_random_slice();
  114. grpc_call** client_calls =
  115. static_cast<grpc_call**>(malloc(sizeof(grpc_call*) * NUM_CALLS));
  116. grpc_call** server_calls =
  117. static_cast<grpc_call**>(malloc(sizeof(grpc_call*) * NUM_CALLS));
  118. grpc_metadata_array* initial_metadata_recv =
  119. static_cast<grpc_metadata_array*>(
  120. malloc(sizeof(grpc_metadata_array) * NUM_CALLS));
  121. grpc_metadata_array* trailing_metadata_recv =
  122. static_cast<grpc_metadata_array*>(
  123. malloc(sizeof(grpc_metadata_array) * NUM_CALLS));
  124. grpc_metadata_array* request_metadata_recv =
  125. static_cast<grpc_metadata_array*>(
  126. malloc(sizeof(grpc_metadata_array) * NUM_CALLS));
  127. grpc_call_details* call_details = static_cast<grpc_call_details*>(
  128. malloc(sizeof(grpc_call_details) * NUM_CALLS));
  129. grpc_status_code* status = static_cast<grpc_status_code*>(
  130. malloc(sizeof(grpc_status_code) * NUM_CALLS));
  131. grpc_slice* details =
  132. static_cast<grpc_slice*>(malloc(sizeof(grpc_slice) * NUM_CALLS));
  133. grpc_byte_buffer** request_payload = static_cast<grpc_byte_buffer**>(
  134. malloc(sizeof(grpc_byte_buffer*) * NUM_CALLS));
  135. grpc_byte_buffer** request_payload_recv = static_cast<grpc_byte_buffer**>(
  136. malloc(sizeof(grpc_byte_buffer*) * NUM_CALLS));
  137. int* was_cancelled = static_cast<int*>(malloc(sizeof(int) * NUM_CALLS));
  138. grpc_call_error error;
  139. int pending_client_calls = 0;
  140. int pending_server_start_calls = 0;
  141. int pending_server_recv_calls = 0;
  142. int pending_server_end_calls = 0;
  143. int cancelled_calls_on_client = 0;
  144. int cancelled_calls_on_server = 0;
  145. int deadline_exceeded = 0;
  146. int unavailable = 0;
  147. grpc_op ops[6];
  148. grpc_op* op;
  149. for (int i = 0; i < NUM_CALLS; i++) {
  150. grpc_metadata_array_init(&initial_metadata_recv[i]);
  151. grpc_metadata_array_init(&trailing_metadata_recv[i]);
  152. grpc_metadata_array_init(&request_metadata_recv[i]);
  153. grpc_call_details_init(&call_details[i]);
  154. request_payload[i] = grpc_raw_byte_buffer_create(&request_payload_slice, 1);
  155. request_payload_recv[i] = nullptr;
  156. was_cancelled[i] = 0;
  157. }
  158. for (int i = 0; i < NUM_CALLS; i++) {
  159. error = grpc_server_request_call(
  160. f.server, &server_calls[i], &call_details[i], &request_metadata_recv[i],
  161. f.cq, f.cq, tag(SERVER_START_BASE_TAG + i));
  162. GPR_ASSERT(GRPC_CALL_OK == error);
  163. pending_server_start_calls++;
  164. }
  165. for (int i = 0; i < NUM_CALLS; i++) {
  166. client_calls[i] =
  167. grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS,
  168. f.cq, grpc_slice_from_static_string("/foo"),
  169. nullptr, n_seconds_from_now(60), nullptr);
  170. memset(ops, 0, sizeof(ops));
  171. op = ops;
  172. op->op = GRPC_OP_SEND_INITIAL_METADATA;
  173. op->data.send_initial_metadata.count = 0;
  174. op->flags = GRPC_INITIAL_METADATA_WAIT_FOR_READY;
  175. op->reserved = nullptr;
  176. op++;
  177. op->op = GRPC_OP_SEND_MESSAGE;
  178. op->data.send_message.send_message = request_payload[i];
  179. op->flags = 0;
  180. op->reserved = nullptr;
  181. op++;
  182. op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
  183. op->flags = 0;
  184. op->reserved = nullptr;
  185. op++;
  186. op->op = GRPC_OP_RECV_INITIAL_METADATA;
  187. op->data.recv_initial_metadata.recv_initial_metadata =
  188. &initial_metadata_recv[i];
  189. op->flags = 0;
  190. op->reserved = nullptr;
  191. op++;
  192. op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
  193. op->data.recv_status_on_client.trailing_metadata =
  194. &trailing_metadata_recv[i];
  195. op->data.recv_status_on_client.status = &status[i];
  196. op->data.recv_status_on_client.status_details = &details[i];
  197. op->flags = 0;
  198. op->reserved = nullptr;
  199. op++;
  200. error = grpc_call_start_batch(client_calls[i], ops,
  201. static_cast<size_t>(op - ops),
  202. tag(CLIENT_BASE_TAG + i), nullptr);
  203. GPR_ASSERT(GRPC_CALL_OK == error);
  204. pending_client_calls++;
  205. }
  206. while (pending_client_calls + pending_server_recv_calls +
  207. pending_server_end_calls >
  208. 0) {
  209. grpc_event ev =
  210. grpc_completion_queue_next(f.cq, n_seconds_from_now(60), nullptr);
  211. GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
  212. int ev_tag = static_cast<int>(reinterpret_cast<intptr_t>(ev.tag));
  213. if (ev_tag < CLIENT_BASE_TAG) {
  214. abort(); /* illegal tag */
  215. } else if (ev_tag < SERVER_START_BASE_TAG) {
  216. /* client call finished */
  217. int call_id = ev_tag - CLIENT_BASE_TAG;
  218. GPR_ASSERT(call_id >= 0);
  219. GPR_ASSERT(call_id < NUM_CALLS);
  220. switch (status[call_id]) {
  221. case GRPC_STATUS_RESOURCE_EXHAUSTED:
  222. cancelled_calls_on_client++;
  223. break;
  224. case GRPC_STATUS_DEADLINE_EXCEEDED:
  225. deadline_exceeded++;
  226. break;
  227. case GRPC_STATUS_UNAVAILABLE:
  228. unavailable++;
  229. break;
  230. case GRPC_STATUS_OK:
  231. break;
  232. default:
  233. gpr_log(GPR_ERROR, "Unexpected status code: %d", status[call_id]);
  234. abort();
  235. }
  236. GPR_ASSERT(pending_client_calls > 0);
  237. grpc_metadata_array_destroy(&initial_metadata_recv[call_id]);
  238. grpc_metadata_array_destroy(&trailing_metadata_recv[call_id]);
  239. grpc_call_unref(client_calls[call_id]);
  240. grpc_slice_unref(details[call_id]);
  241. grpc_byte_buffer_destroy(request_payload[call_id]);
  242. pending_client_calls--;
  243. } else if (ev_tag < SERVER_RECV_BASE_TAG) {
  244. /* new incoming call to the server */
  245. int call_id = ev_tag - SERVER_START_BASE_TAG;
  246. GPR_ASSERT(call_id >= 0);
  247. GPR_ASSERT(call_id < NUM_CALLS);
  248. memset(ops, 0, sizeof(ops));
  249. op = ops;
  250. op->op = GRPC_OP_SEND_INITIAL_METADATA;
  251. op->data.send_initial_metadata.count = 0;
  252. op->flags = 0;
  253. op->reserved = nullptr;
  254. op++;
  255. op->op = GRPC_OP_RECV_MESSAGE;
  256. op->data.recv_message.recv_message = &request_payload_recv[call_id];
  257. op->flags = 0;
  258. op->reserved = nullptr;
  259. op++;
  260. error = grpc_call_start_batch(
  261. server_calls[call_id], ops, static_cast<size_t>(op - ops),
  262. tag(SERVER_RECV_BASE_TAG + call_id), nullptr);
  263. GPR_ASSERT(GRPC_CALL_OK == error);
  264. GPR_ASSERT(pending_server_start_calls > 0);
  265. pending_server_start_calls--;
  266. pending_server_recv_calls++;
  267. grpc_call_details_destroy(&call_details[call_id]);
  268. grpc_metadata_array_destroy(&request_metadata_recv[call_id]);
  269. } else if (ev_tag < SERVER_END_BASE_TAG) {
  270. /* finished read on the server */
  271. int call_id = ev_tag - SERVER_RECV_BASE_TAG;
  272. GPR_ASSERT(call_id >= 0);
  273. GPR_ASSERT(call_id < NUM_CALLS);
  274. if (ev.success) {
  275. if (request_payload_recv[call_id] != nullptr) {
  276. grpc_byte_buffer_destroy(request_payload_recv[call_id]);
  277. request_payload_recv[call_id] = nullptr;
  278. }
  279. } else {
  280. GPR_ASSERT(request_payload_recv[call_id] == nullptr);
  281. }
  282. memset(ops, 0, sizeof(ops));
  283. op = ops;
  284. op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
  285. op->data.recv_close_on_server.cancelled = &was_cancelled[call_id];
  286. op->flags = 0;
  287. op->reserved = nullptr;
  288. op++;
  289. op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
  290. op->data.send_status_from_server.trailing_metadata_count = 0;
  291. op->data.send_status_from_server.status = GRPC_STATUS_OK;
  292. grpc_slice status_details = grpc_slice_from_static_string("xyz");
  293. op->data.send_status_from_server.status_details = &status_details;
  294. op->flags = 0;
  295. op->reserved = nullptr;
  296. op++;
  297. error = grpc_call_start_batch(
  298. server_calls[call_id], ops, static_cast<size_t>(op - ops),
  299. tag(SERVER_END_BASE_TAG + call_id), nullptr);
  300. GPR_ASSERT(GRPC_CALL_OK == error);
  301. GPR_ASSERT(pending_server_recv_calls > 0);
  302. pending_server_recv_calls--;
  303. pending_server_end_calls++;
  304. } else {
  305. int call_id = ev_tag - SERVER_END_BASE_TAG;
  306. GPR_ASSERT(call_id >= 0);
  307. GPR_ASSERT(call_id < NUM_CALLS);
  308. if (was_cancelled[call_id]) {
  309. cancelled_calls_on_server++;
  310. }
  311. GPR_ASSERT(pending_server_end_calls > 0);
  312. pending_server_end_calls--;
  313. grpc_call_unref(server_calls[call_id]);
  314. }
  315. }
  316. gpr_log(GPR_INFO,
  317. "Done. %d total calls: %d cancelled at server, %d cancelled at "
  318. "client, %d timed out, %d unavailable.",
  319. NUM_CALLS, cancelled_calls_on_server, cancelled_calls_on_client,
  320. deadline_exceeded, unavailable);
  321. grpc_slice_unref(request_payload_slice);
  322. grpc_resource_quota_unref(resource_quota);
  323. end_test(&f);
  324. config.tear_down_data(&f);
  325. free(client_calls);
  326. free(server_calls);
  327. free(initial_metadata_recv);
  328. free(trailing_metadata_recv);
  329. free(request_metadata_recv);
  330. free(call_details);
  331. free(status);
  332. free(details);
  333. free(request_payload);
  334. free(request_payload_recv);
  335. free(was_cancelled);
  336. }
  337. void resource_quota_server_pre_init(void) {}