WS: Better reuse of the cmd struct for WS clients

For WS clients, reuse a persistent cmd struct attached to the
http_client object: take the cmd built from the WS frame, and copy it to
the persistent cmd.
master
Jessie Murray 3 years ago
parent b98116abc8
commit e26d6358e7
No known key found for this signature in database
GPG Key ID: E7E4D57EDDA744C5

@ -35,11 +35,22 @@ cmd_new(struct http_client *client, int count) {
return c; return c;
} }
void
cmd_free_argv(struct cmd *c) {
int i;
fprintf(stderr, "%s: %p\n", __func__, c);
for(i = 0; i < c->count; ++i) {
free((char*)c->argv[i]);
}
free(c->argv);
free(c->argv_len);
}
void void
cmd_free(struct cmd *c) { cmd_free(struct cmd *c) {
int i;
if(!c) return; if(!c) return;
free(c->jsonp); free(c->jsonp);
@ -53,12 +64,7 @@ cmd_free(struct cmd *c) {
pool_free_context(c->ac); pool_free_context(c->ac);
} }
for(i = 0; i < c->count; ++i) { cmd_free_argv(c);
free((char*)c->argv[i]);
}
free(c->argv);
free(c->argv_len);
free(c); free(c);
} }

@ -57,6 +57,9 @@ struct subscription {
struct cmd * struct cmd *
cmd_new(struct http_client *c, int count); cmd_new(struct http_client *c, int count);
void
cmd_free_argv(struct cmd *c);
void void
cmd_free(struct cmd *c); cmd_free(struct cmd *c);

@ -216,16 +216,28 @@ ws_execute(struct http_client *c, const char *frame, size_t frame_len) {
struct cmd *cmd = fun_extract(c, frame, frame_len); struct cmd *cmd = fun_extract(c, frame, frame_len);
if(cmd) { if(cmd) {
/* copy client info into cmd. */
cmd_setup(cmd, c);
cmd->is_websocket = 1; cmd->is_websocket = 1;
if (c->self_cmd != NULL) { if (c->self_cmd != NULL) {
/* This client already has its own connection /* This client already has its own connection
* to Redis from a previous command; use it from * to Redis from a previous command; use it from
* now on. */ * now on. */
cmd->ac = c->self_cmd->ac; /* free args for the previous cmd */
cmd_free_argv(c->self_cmd);
/* copy args from what we just parsed to the persistent command */
c->self_cmd->count = cmd->count;
c->self_cmd->argv = cmd->argv;
c->self_cmd->argv_len = cmd->argv_len;
cmd->argv = NULL;
cmd->argv_len = NULL;
cmd->count = 0;
cmd_free(cmd);
cmd = c->self_cmd; /* replace pointer since we're about to pass it to cmd_send */
} else { } else {
/* copy client info into cmd. */
cmd_setup(cmd, c);
/* First WS command; make new Redis context /* First WS command; make new Redis context
* for this client */ * for this client */
cmd->ac = pool_connect(c->w->pool, cmd->database, 0); cmd->ac = pool_connect(c->w->pool, cmd->database, 0);
@ -390,8 +402,8 @@ ws_frame_and_send_response(struct cmd *cmd, const char *p, size_t sz) {
/* mark as keep alive, otherwise we'll close the connection after the first reply */ /* mark as keep alive, otherwise we'll close the connection after the first reply */
int add_ret = evbuffer_add(cmd->http_client->ws_wbuf, frame, frame_sz); int add_ret = evbuffer_add(cmd->http_client->ws_wbuf, frame, frame_sz);
free(frame); /* no longer needed once added to buffer */
if (add_ret < 0) { if (add_ret < 0) {
free(frame);
slog(cmd->w->s, WEBDIS_ERROR, "Failed response allocation in ws_frame_and_send_response", 0); slog(cmd->w->s, WEBDIS_ERROR, "Failed response allocation in ws_frame_and_send_response", 0);
return -1; return -1;
} }

Loading…
Cancel
Save