8000 Allow mixing multi and pipeline modes · jrtkcoder/phpredis@aa95fcb · GitHub
[go: up one dir, main page]

Skip to content

Commit aa95fcb

Browse files
committed
Allow mixing multi and pipeline modes
1 parent d6756ca commit aa95fcb

File tree

2 files changed

+81
-47
lines changed

2 files changed

+81
-47
lines changed

common.h

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -467,12 +467,17 @@ typedef enum _PUBSUB_TYPE {
467467
#define REDIS_ERR_SYNC_MSG "MASTERDOWN Link with MASTER is down and slave-serve-stale-data is set to 'no'"
468468
#define REDIS_ERR_SYNC_KW "MASTERDOWN"
469469

470+
/* Transaction modes */
471+
#define ATOMIC 0
472+
#define MULTI 1
473+
#define PIPELINE 2
474+
470475
#define IF_ATOMIC() if (redis_sock->mode == ATOMIC)
471476
#define IF_NOT_ATOMIC() if (redis_sock->mode != ATOMIC)
472-
#define IF_MULTI() if (redis_sock->mode == MULTI)
473-
#define IF_NOT_MULTI() if (redis_sock->mode != MULTI)
474-
#define IF_PIPELINE() if (redis_sock->mode == PIPELINE)
475-
#define IF_NOT_PIPELINE() if (redis_sock->mode != PIPELINE)
477+
#define IF_MULTI() if (redis_sock->mode & MULTI)
478+
#define IF_NOT_MULTI() if (!(redis_sock->mode & MULTI))
479+
#define IF_PIPELINE() if (redis_sock->mode & PIPELINE)
480+
#define IF_NOT_PIPELINE() if (!(redis_sock->mode & PIPELINE))
476481

477482
#define PIPELINE_ENQUEUE_COMMAND(cmd, cmd_len) do { \
478483
request_item *tmp = malloc(sizeof(request_item)); \
@@ -518,7 +523,7 @@ typedef enum _PUBSUB_TYPE {
518523
efree(cmd);
519524

520525
#define REDIS_PROCESS_RESPONSE_CLOSURE(function, closure_context) \
521-
IF_MULTI() { \
526+
IF_NOT_PIPELINE() { \
522527
if (redis_response_enqueued(redis_sock TSRMLS_CC) != SUCCESS) { \
523528
RETURN_FALSE; \
524529
} \
@@ -594,7 +599,8 @@ typedef enum _PUBSUB_TYPE {
594599
#define IS_LEX_ARG(s,l) \
595600
(l>0 && (*s=='(' || *s=='[' || (l==1 && (*s=='+' || *s=='-'))))
596601

597-
typedef enum {ATOMIC, MULTI, PIPELINE} redis_mode;
602+
#define REDIS_ENABLE_MODE(redis_sock, m) (redis_sock->mode |= m)
603+
#define REDIS_DISABLE_MODE(redis_sock, m) (redis_sock->mode &= ~m)
598604

599605
typedef struct fold_item {
600606
zval * (*fun)(INTERNAL_FUNCTION_PARAMETERS, void *, ...);
@@ -629,7 +635,7 @@ typedef struct {
629635
char *prefix;
630636
int prefix_len;
631637

632-
redis_mode mode;
638+
short mode;
633639
fold_item *head;
634640
fold_item *current;
635641

redis.c

Lines changed: 68 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -771,9 +771,11 @@ PHP_METHOD(Redis,__destruct) {
771771

772772
// If we think we're in MULTI mode, send a discard
773773
IF_MULTI() {
774-
// Discard any multi commands, and free any callbacks that have been
775-
// queued
776-
send_discard_static(redis_sock TSRMLS_CC);
774+
IF_NOT_PIPELINE() {
775+
// Discard any multi commands, and free any callbacks that have been
776+
// queued
777+
send_discard_static(redis_sock TSRMLS_CC);
778+
}
777779
free_reply_callbacks(redis_sock);
778780
}
779781
}
@@ -2243,9 +2245,8 @@ PHP_METHOD(Redis, multi)
22432245
{
22442246

22452247
RedisSock *redis_sock;
2246-
char *cmd;
2247-
int response_len, cmd_len;
2248-
char * response;
2248+
char *cmd, *resp;
2249+
int cmd_len, resp_len;
22492250
zval *object;
22502251
zend_long multi_value = MULTI;
22512252

@@ -2262,37 +2263,45 @@ PHP_METHOD(Redis, multi)
22622263
RETURN_FALSE;
22632264
}
22642265

2265-
if(multi_value == MULTI || multi_value == PIPELINE) {
2266-
redis_sock->mode = multi_value;
2267-
} else {
2268-
RETURN_FALSE;
2269-
}
2270-
2271-
redis_sock->current = NULL;
2272-
2273-
IF_MULTI() {
2274-
cmd_len = redis_cmd_format_static(&cmd, "MULTI", "");
2275-
2276-
SOCKET_WRITE_COMMAND(redis_sock, cmd, cmd_len)
2277-
efree(cmd);
2278-
2279-
if ((response = redis_sock_read(redis_sock, &response_len TSRMLS_CC))
2280-
== NULL)
2281-
{
2282-
RETURN_FALSE;
2266+
if (multi_value == PIPELINE) {
2267+
IF_PIPELINE() {
2268+
php_error_docref(NULL TSRMLS_CC, E_WARNING,
2269+
"Already in pipeline mode");
2270+
} else {
2271+
IF_MULTI() {
2272+
php_error_docref(NULL TSRMLS_CC, E_ERROR,
2273+
"Can't activate pipeline in multi mode!");
2274+
RETURN_FALSE;
2275+
}
2276+
free_reply_callbacks(redis_sock);
2277+
REDIS_ENABLE_MODE(redis_ 9E81 sock, PIPELINE);
22832278
}
2284-
2285-
if(strncmp(response, "+OK", 3) == 0) {
2286-
efree(response);
2287-
RETURN_ZVAL(getThis(), 1, 0);
2279+
} else if (multi_value == MULTI) {
2280+
IF_MULTI() {
2281+
php_error_docref(NULL TSRMLS_CC, E_WARNING,
2282+
"Already in multi mode");
2283+
} else {
2284+
cmd_len = redis_cmd_format_static(&cmd, "MULTI", "");
2285+
IF_PIPELINE() {
2286+
PIPELINE_ENQUEUE_COMMAND(cmd, cmd_len);
2287+
efree(cmd);
2288+
} else {
2289+
SOCKET_WRITE_COMMAND(redis_sock, cmd, cmd_len)
2290+
efree(cmd);
2291+
if ((resp = redis_sock_read(redis_sock, &resp_len TSRMLS_CC)) == NULL) {
2292+
RETURN_FALSE;
2293+
} else if (strncmp(resp, "+OK", 3) != 0) {
2294+
efree(resp);
2295+
RETURN_FALSE;
2296+
}
2297+
efree(resp);
2298+
}
2299+
REDIS_ENABLE_MODE(redis_sock, MULTI);
22882300
}
2289-
efree(response);
2301+
} else {
22902302
RETURN_FALSE;
22912303
}
2292-
IF_PIPELINE() {
2293-
free_reply_callbacks(redis_sock);
2294-
RETURN_ZVAL(getThis(), 1, 0);
2295-
}
2304+
RETURN_ZVAL(getThis(), 1, 0);
22962305
}
22972306

22982307
/* discard */
@@ -2362,6 +2371,12 @@ PHP_METHOD(Redis, exec)
23622371

23632372
IF_MULTI() {
23642373
cmd_len = redis_cmd_format_static(&cmd, "EXEC", "");
2374+
IF_PIPELINE() {
2375+
PIPELINE_ENQUEUE_COMMAND(cmd, cmd_len);
2376+
efree(cmd);
2377+
REDIS_DISABLE_MODE(redis_sock, MULTI);
2378+
RETURN_ZVAL(getThis(), 1, 0);
2379+
}
23652380
SOCKET_WRITE_COMMAND(redis_sock, cmd, cmd_len)
23662381
efree(cmd);
23672382

@@ -2371,12 +2386,12 @@ PHP_METHOD(Redis, exec)
23712386
{
23722387
zval_dtor(return_value);
23732388
free_reply_callbacks(redis_sock);
2374-
redis_sock->mode = ATOMIC;
2389+
REDIS_DISABLE_MODE(redis_sock, MULTI);
23752390
redis_sock->watching = 0;
23762391
RETURN_FALSE;
23772392
}
23782393
free_reply_callbacks(redis_sock);
2379-
redis_sock->mode = ATOMIC;
2394+
REDIS_DISABLE_MODE(redis_sock, MULTI);
23802395
redis_sock->watching = 0;
23812396
}
23822397

@@ -2409,8 +2424,8 @@ PHP_METHOD(Redis, exec)
24092424
/* Empty array when no command was run. */
24102425
array_init(return_value);
24112426
}
2412-
redis_sock->mode = ATOMIC;
24132427
free_reply_callbacks(redis_sock);
2428+
REDIS_DISABLE_MODE(redis_sock, PIPELINE);
24142429
}
24152430
}
24162431

@@ -2456,13 +2471,20 @@ PHP_METHOD(Redis, pipeline)
24562471
RETURN_FALSE;
24572472
}
24582473

2459-
IF_NOT_PIPELINE() {
2460-
redis_sock->mode = PIPELINE;
2461-
2474+
IF_PIPELINE() {
2475+
php_error_docref(NULL TSRMLS_CC, E_WARNING,
2476+
"Already in pipeline mode");
2477+
} else {
2478+
IF_MULTI() {
2479+
php_error_docref(NULL TSRMLS_CC, E_ERROR,
2480+
"Can't activate pipeline in multi mode!");
2481+
RETURN_FALSE;
2482+
}
24622483
/* NB : we keep the function fold, to detect the last function.
24632484
* We need the response format of the n - 1 command. So, we can delete
24642485
* when n > 2, the { 1 .. n - 2} commands */
24652486
free_reply_callbacks(redis_sock);
2487+
REDIS_ENABLE_MODE(redis_sock, PIPELINE);
24662488
}
24672489
RETURN_ZVAL(getThis(), 1, 0);
24682490
}
@@ -3411,7 +3433,13 @@ PHP_METHOD(Redis, getMode) {
34113433
RETURN_FALSE;
34123434
}
34133435

3414-
RETVAL_LONG(redis_sock->mode);
3436+
IF_PIPELINE() {
3437+
RETVAL_LONG(PIPELINE);
3438+
} else IF_MULTI() {
3439+
RETVAL_LONG(MULTI);
3440+
} else {
3441+
RETVAL_LONG(ATOMIC);
3442+
}
34153443
}
34163444

34173445
/* {{{ proto Redis::time() */

0 commit comments

Comments
 (0)
0