GitHub Sale: sign up for any paid plan this week and pay nothing until January 1, 2009!  [ hide ]

public
Description: Beanstalkd is a fast, distributed, in-memory workqueue service. Its interface is generic, but was designed for use in reducing the latency of page views in high-volume web applications by running most time-consuming tasks asynchronously.
Homepage: http://xph.us/software/beanstalkd/
Clone URL: git://github.com/kr/beanstalkd.git
Click here to lend your support to: beanstalkd and make a donation at www.pledgie.com !
Implement tubes.
kr (author)
Wed Feb 20 15:08:02 -0800 2008
commit  c1b09c4fd41f4496fc147bd273d0b823b400f35b
tree    477a3cd539a7d01603ace54ae1b8d107b0af4ef6
parent  35594240aec055321e97065f778be5ec6196cbfa
0
...
42
43
44
 
45
46
47
 
 
 
 
 
 
 
 
 
 
 
 
48
49
 
50
51
52
...
54
55
56
 
 
 
 
 
 
 
 
 
57
58
59
...
149
150
151
152
 
153
154
155
...
209
210
211
212
 
213
214
215
 
216
217
218
...
226
227
228
 
 
229
230
...
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
 
62
63
64
65
...
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
...
171
172
173
 
174
175
176
177
...
231
232
233
 
234
235
236
 
237
238
239
240
...
248
249
250
251
252
253
254
0
@@ -42,11 +42,24 @@ static void
0
 conn_free(conn c)
0
 {
0
     c->fd = 0;
0
+ TUBE_ASSIGN(c->use, NULL);
0
     conn_insert(&pool, c);
0
 }
0
 
0
+static void
0
+inc(ms a, tube t, size_t i)
0
+{
0
+ tube_iref(t);
0
+}
0
+
0
+static void
0
+dec(ms a, tube t, size_t i)
0
+{
0
+ tube_dref(t);
0
+}
0
+
0
 conn
0
-make_conn(int fd, char start_state)
0
+make_conn(int fd, char start_state, tube use, tube watch)
0
 {
0
     job j;
0
     conn c;
0
@@ -54,6 +67,15 @@ make_conn(int fd, char start_state)
0
     c = conn_alloc();
0
     if (!c) return twarn("OOM"), NULL;
0
 
0
+ ms_init(&c->watch, (ms_event_fn) inc, (ms_event_fn) dec);
0
+ if (!ms_append(&c->watch, watch)) {
0
+ conn_free(c);
0
+ return twarn("OOM"), NULL;
0
+ }
0
+
0
+ c->use = NULL; /* initialize */
0
+ TUBE_ASSIGN(c->use, use);
0
+
0
     c->fd = fd;
0
     c->state = start_state;
0
     c->type = 0;
0
@@ -149,7 +171,7 @@ conn_update_evq(conn c, const int events)
0
     return conn_set_evq(c, events, c->evq.ev_callback);
0
 }
0
 
0
-int
0
+static int
0
 conn_list_any_p(conn head)
0
 {
0
     return head->next != head || head->prev != head;
0
@@ -209,10 +231,10 @@ conn_close(conn c)
0
 
0
     close(c->fd);
0
 
0
- free(c->in_job);
0
+ job_free(c->in_job);
0
 
0
     /* was this a peek or stats command? */
0
- if (!has_reserved_this_job(c, c->out_job)) free(c->out_job);
0
+ if (!has_reserved_this_job(c, c->out_job)) job_free(c->out_job);
0
 
0
     c->in_job = c->out_job = NULL;
0
 
0
@@ -226,5 +248,7 @@ conn_close(conn c)
0
     conn_remove(c);
0
     if (has_reserved_job(c)) enqueue_reserved_jobs(c);
0
 
0
+ ms_clear(&c->watch);
0
+
0
     conn_free(c);
0
 }
0
...
20
21
22
 
23
 
24
25
26
...
44
45
46
 
 
 
47
48
49
...
74
75
76
 
 
77
78
79
 
80
81
82
83
84
85
86
87
88
89
...
20
21
22
23
24
25
26
27
28
...
46
47
48
49
50
51
52
53
54
...
79
80
81
82
83
84
85
 
86
87
88
89
90
91
92
 
93
94
95
0
@@ -20,7 +20,9 @@
0
 #define conn_h
0
 
0
 #include "event.h"
0
+#include "ms.h"
0
 #include "job.h"
0
+#include "tube.h"
0
 
0
 #define STATE_WANTCOMMAND 0
0
 #define STATE_WANTDATA 1
0
@@ -44,6 +46,9 @@
0
 #define OP_STATS 8
0
 #define OP_JOBSTATS 9
0
 #define OP_PEEK 10
0
+#define OP_USE 11
0
+#define OP_WATCH 12
0
+#define OP_IGNORE 13
0
 
0
 /* CONN_TYPE_* are bit masks */
0
 #define CONN_TYPE_PRODUCER 1
0
@@ -74,16 +79,17 @@ struct conn {
0
     job out_job;
0
     int out_job_sent;
0
     struct job reserved_jobs; /* doubly-linked list header */
0
+ tube use;
0
+ struct ms watch;
0
 };
0
 
0
-conn make_conn(int fd, char start_state);
0
+conn make_conn(int fd, char start_state, tube use, tube watch);
0
 
0
 int conn_set_evq(conn c, const int events, evh handler);
0
 int conn_update_evq(conn c, const int flags);
0
 
0
 void conn_close(conn c);
0
 
0
-int conn_list_any_p(conn head);
0
 conn conn_remove(conn c);
0
 void conn_insert(conn head, conn c);
0
 
...
10
11
12
 
 
 
 
 
 
13
14
15
...
106
107
108
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
110
111
 
 
112
113
114
...
116
117
118
119
 
 
120
121
122
...
150
151
152
 
 
 
 
 
 
 
 
 
 
 
 
 
153
154
155
...
239
240
241
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
242
243
244
...
315
316
317
 
 
318
319
320
...
366
367
368
 
 
369
370
371
...
10
11
12
13
14
15
16
17
18
19
20
21
...
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
 
 
130
131
132
133
134
...
136
137
138
 
139
140
141
142
143
...
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
...
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
...
379
380
381
382
383
384
385
386
...
432
433
434
435
436
437
438
439
0
@@ -10,6 +10,12 @@ were received and sends responses in the same order. All integers in the
0
 protocol are formatted in decimal and (unless otherwise indicated)
0
 nonnegative.
0
 
0
+Names, in this protocol, are ASCII strings. They may contain letters (A-Z and
0
+a-z), numerals (0-9), hyphen ("-"), plus ("+"), slash ("/"), semicolon (";"),
0
+dot ("."), dollar-sign ("$"), and parentheses ("(" and ")"), but they may not
0
+begin with a hyphen. They are terminated by white space (either a space char or
0
+end of line). Each name must be at least one character long.
0
+
0
 The protocol contains two kinds of data: text lines and unstructured chunks of
0
 data. Text lines are used for client commands and server responses. Chunks are
0
 used to transfer job bodies and stats information. Each job body is an opaque
0
@@ -106,9 +112,23 @@ Here is a picture with more possibilities:
0
                         `--------> *poof*
0
 
0
 
0
+The system has one or more tubes. Each tube consists of a ready queue and a
0
+delay queue. Each job spends its entire life in one tube. Consumers can show
0
+interest in tubes by sending the "watch" command; they can show disinterest by
0
+sending the "ignore" command. This set of interesting tubes is said to be a
0
+consumer's "watch list". When a client reserves a job, it may come from any of
0
+the tubes in its watch list.
0
+
0
+When a client connects, its watch list is initially just the tube named
0
+"default". If it submits jobs without having sent a "use" command, they will
0
+live in the tube named "default".
0
+
0
+Tubes are created on demand whenever they are referenced. If a tube is empty
0
+(that is, it contains no ready, delayed, or buried jobs) and no client refers
0
+to it, it will be deleted.
0
 
0
-Producer Command
0
-----------------
0
+Producer Commands
0
+-----------------
0
 
0
 The "put" command is for any process that wants to insert a job into the queue.
0
 It comprises a command line followed by the job body:
0
@@ -116,7 +136,8 @@ It comprises a command line followed by the job body:
0
 put <pri> <delay> <ttr> <bytes>\r\n
0
 <data>\r\n
0
 
0
-It inserts a job into the queue.
0
+It inserts a job into the client's currently used tube (see the "use" command
0
+below).
0
 
0
  - <pri> is an integer < 2**32. Jobs with smaller priority values will be
0
    scheduled before jobs with larger priorities. The most urgent priority is 0;
0
@@ -150,6 +171,19 @@ may be:
0
 
0
    - <id> is the integer id of the new job
0
 
0
+The "use" command is for producers. Subsequent put commands will put jobs into
0
+the tube specified by this command. If no use command has been issued, jobs
0
+will be put into the tube named "default".
0
+
0
+use <tube>\r\n
0
+
0
+ - <tube> is a name at most 200 bytes. It specifies the tube to use. If the
0
+ tube does not exist, it will be created.
0
+
0
+The only reply is:
0
+
0
+USING\r\n
0
+
0
 Worker Commands
0
 ---------------
0
 
0
@@ -239,6 +273,36 @@ There are two possible responses:
0
 
0
  - "NOT_FOUND\r\n" if the job does not exist or is not reserved by the client.
0
 
0
+The "watch" command adds the named tube to the watch list for the current
0
+connection. A reserve command will take a job from any of the tubes in the
0
+watch list. For each new connection, the watch list initially consists of one
0
+tube, named "default".
0
+
0
+watch <tube>\r\n
0
+
0
+ - <tube> is a name at most 200 bytes. It specifies a tube to add to the watch
0
+ list.
0
+
0
+The reply is:
0
+
0
+WATCHING <count>\r\n
0
+
0
+ - <count> is the integer number of tubes currently in the watch list.
0
+
0
+The "ignore" command is for consumers. It removes the named tube from the
0
+watch list for the current connection.
0
+
0
+ignore <tube>\r\n
0
+
0
+The reply is one of:
0
+
0
+ - "WATCHING <count>\r\n" to indicate success.
0
+
0
+ - <count> is the integer number of tubes currently in the watch list.
0
+
0
+ - "NOT_IGNORED\r\n" if the client attempts to ignore the only tube in its
0
+ watch list.
0
+
0
 Other Commands
0
 --------------
0
 
0
@@ -315,6 +379,8 @@ scalars.
0
 
0
    - "id" is the job id
0
 
0
+ - "tube" is the name of the tube that contains this job
0
+
0
    - "state" is "ready" or "delayed" or "reserved" or "buried"
0
 
0
    - "age" is the time in seconds since the put command that created this job.
0
@@ -366,6 +432,8 @@ scalars.
0
 
0
    - "total-jobs" is the cumulative count of jobs created.
0
 
0
+ - "current-tubes" is the number of currently-existing tubes.
0
+
0
    - "current-connections" is the number of currently open connections.
0
 
0
    - "current-producers" is the number of open connections that have each
0
...
20
21
22
 
23
24
25
...
37
38
39
 
40
41
42
43
44
45
 
 
46
47
48
...
53
54
55
 
56
57
58
59
 
 
 
 
 
 
 
60
61
62
...
91
92
93
94
95
96
97
 
 
 
98
99
100
...
20
21
22
23
24
25
26
...
38
39
40
41
42
43
44
45
46
 
47
48
49
50
51
...
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
...
102
103
104
 
 
 
 
105
106
107
108
109
110
0
@@ -20,6 +20,7 @@
0
 #include <string.h>
0
 
0
 #include "job.h"
0
+#include "tube.h"
0
 #include "util.h"
0
 
0
 static unsigned long long int next_id = 1;
0
@@ -37,12 +38,14 @@ allocate_job(int body_size)
0
     j->timeout_ct = j->release_ct = j->bury_ct = j->kick_ct = 0;
0
     j->body_size = body_size;
0
     j->next = j->prev = j; /* not in a linked list */
0
+ j->tube = NULL;
0
 
0
     return j;
0
 }
0
 
0
 job
0
-make_job(unsigned int pri, unsigned int delay, unsigned int ttr, int body_size)
0
+make_job(unsigned int pri, unsigned int delay, unsigned int ttr, int body_size,
0
+ tube tube)
0
 {
0
     job j;
0
 
0
@@ -53,10 +56,18 @@ make_job(unsigned int pri, unsigned int delay, unsigned int ttr, int body_size)
0
     j->pri = pri;
0
     j->delay = delay;
0
     j->ttr = ttr;
0
+ TUBE_ASSIGN(j->tube, tube);
0
 
0
     return j;
0
 }
0
 
0
+void
0
+job_free(job j)
0
+{
0
+ if (j) TUBE_ASSIGN(j->tube, NULL);
0
+ free(j);
0
+}
0
+
0
 int
0
 job_pri_cmp(job a, job b)
0
 {
0
@@ -91,10 +102,9 @@ job_copy(job j)
0
     n = malloc(sizeof(struct job) + j->body_size);
0
     if (!n) return twarnx("OOM"), NULL;
0
 
0
- n->id = j->id;
0
- n->pri = j->pri;
0
- n->body_size = j->body_size;
0
- memcpy(n->body, j->body, j->body_size);
0
+ memcpy(n, j, sizeof(struct job) + j->body_size);
0
+ n->next = n->prev = n; /* not in a linked list */
0
+ TUBE_ASSIGN(n->tube, j->tube);
0
 
0
     return n;
0
 }
0
...
21
22
23
 
 
 
 
 
24
25
26
27
28
29
30
31
32
33
34
...
42
43
44
 
45
46
47
48
49
50
51
 
 
52
53
54
55
56
...
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 
 
35
36
37
...
45
46
47
48
49
50
51
52
53
54
 
55
56
57
 
58
59
60
0
@@ -21,14 +21,17 @@
0
 
0
 #include <time.h>
0
 
0
+typedef struct job *job;
0
+typedef int(*job_cmp_fn)(job, job);
0
+
0
+#include "tube.h"
0
+
0
 #define JOB_STATE_INVALID 0
0
 #define JOB_STATE_READY 1
0
 #define JOB_STATE_RESERVED 2
0
 #define JOB_STATE_BURIED 3
0
 #define JOB_STATE_DELAYED 4
0
 
0
-typedef struct job *job;
0
-
0
 struct job {
0
     job prev, next; /* linked list of jobs */
0
     unsigned long long int id;
0
@@ -42,15 +45,16 @@ struct job {
0
     unsigned int release_ct;
0
     unsigned int bury_ct;
0
     unsigned int kick_ct;
0
+ tube tube;
0
     char state;
0
     char body[];
0
 };
0
 
0
 job allocate_job(int body_size);
0
 job make_job(unsigned int pri, unsigned int delay, unsigned int ttr,
0
- int body_size);
0
+ int body_size, tube tube);
0
+void job_free(job j);
0
 
0
-typedef int(*job_cmp_fn)(job, job);
0
 int job_pri_cmp(job a, job b);
0
 int job_delay_cmp(job a, job b);
0
 
0
...
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
...
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
0
@@ -20,35 +20,39 @@
0
 #include <stdio.h>
0
 #include <string.h>
0
 
0
+#include "tube.h" /* hack to make cpp happy */
0
 #include "pq.h"
0
 
0
-pq
0
-make_pq(unsigned int initial_cap, job_cmp_fn cmp)
0
+void
0
+pq_init(pq q, job_cmp_fn cmp)
0
 {
0
- pq q;
0
+ if (!q) return;
0
 
0
- q = malloc(sizeof(struct pq));
0
- if (!q) return NULL;
0
-
0
- q->cap = initial_cap;
0
+ q->cap = 0;
0
     q->used = 0;
0
     q->cmp = cmp;
0
- q->heap = malloc(initial_cap * sizeof(job));
0
- if (!q->heap) return free(q), NULL;
0
+ q->heap = NULL;
0
+
0
+ return;
0
+}
0
 
0
- return q;
0
+void
0
+pq_clear(pq q)
0
+{
0
+ free(q->heap);
0
+ pq_init(q, q->cmp);
0
 }
0
 
0
 static void
0
 pq_grow(pq q)
0
 {
0
     job *nheap;
0
- unsigned int ncap = q->cap << 1;
0
+ unsigned int ncap = q->cap << 1 ? : 1;
0
 
0
     nheap = malloc(ncap * sizeof(job));
0
     if (!nheap) return;
0
 
0
- memcpy(nheap, q->heap, q->used * sizeof(job));
0
+ if (q->heap) memcpy(nheap, q->heap, q->used * sizeof(job));
0
     free(q->heap);
0
     q->heap = nheap;
0
     q->cap = ncap;
0
...
19
20
21
 
 
22
23
24
 
25
26
27
28
29
 
 
 
 
30
31
32
 
33
34
35
...
19
20
21
22
23
24
25
 
26
27
28
29
30
 
31
32
33
34
35
 
 
36
37
38
39
0
@@ -19,17 +19,21 @@
0
 #ifndef q_h
0
 #define q_h
0
 
0
+typedef struct pq *pq;
0
+
0
 #include "job.h"
0
 
0
-typedef struct pq {
0
+struct pq {
0
     unsigned int cap;
0
     unsigned int used;
0
     job_cmp_fn cmp;
0
     job *heap;
0
-} *pq;
0
+};
0
+
0
+/* initialize a priority queue */
0
+void pq_init(pq q, job_cmp_fn cmp);
0
 
0
-/* make a priority queue with initial capacity initial_cap */
0
-pq make_pq(unsigned int initial_cap, job_cmp_fn cmp);
0
+void pq_clear(pq q);
0
 
0
 /* return 1 if the job was inserted, else 0 */
0
 int pq_give(pq q, job j);
0
...
27
28
29
 
30
 
31
32
33
...
36
37
38
 
 
 
 
 
39
40
41
...
46
47
48
 
 
 
49
50
51
...
58
59
60
 
 
 
61
62
63
...
67
68
69
 
70
71
72
73
74
 
75
76
77
...
97
98
99
 
100
101
102
...
111
112
113
 
114
115
116
...
122
123
124
125
126
 
 
127
128
129
130
131
 
 
 
 
132
133
134
...
155
156
157
 
 
 
158
159
160
161
162
163
164
165
166
167
168
169
170
...
220
221
222
 
 
223
224
225
226
 
 
 
 
227
228
229
...
237
238
239
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
240
241
242
243
244
245
246
247
 
 
 
 
 
248
249
 
250
251
252
...
257
258
259
260
 
261
262
263
 
264
265
 
266
267
 
268
269
270
...
298
299
300
301
 
302
303
304
305
306
307
 
308
309
310
...
327
328
329
330
 
331
332
333
...
335
336
337
338
 
339
340
341
...
350
351
352
353
 
354
355
356
...
410
411
412
 
 
413
414
415
 
 
 
416
417
418
...
446
447
448
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
449
450
451
452
 
 
453
454
455
456
457
458
459
460
461
 
462
463
464
...
528
529
530
 
 
 
531
532
533
...
570
571
572
573
 
574
575
576
...
612
613
614
 
615
616
617
...
710
711
712
 
713
714
715
...
749
750
751
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
752
753
754
...
756
757
758
759
 
760
761
 
762
763
764
...
797
798
799
800
 
801
802
803
...
856
857
858
859
 
860
861
862
...
935
936
937
 
 
938
939
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
940
941
942
...
983
984
985
986
 
987
988
989
...
1006
1007
1008
 
1009
1010
1011
1012
1013
1014
 
1015
1016
1017
...
1152
1153
1154
1155
 
1156
1157
1158
...
1164
1165
1166
1167
1168
 
 
 
 
 
 
 
1169
...
27
28
29
30
31
32
33
34
35
...
38
39
40
41
42
43
44
45
46
47
48
...
53
54
55
56
57
58
59
60
61
...
68
69
70
71
72
73
74
75
76
...
80
81
82
83
84
85
86
87
88
89
90
91
92
...
112
113
114
115
116
117
118
...
127
128
129
130
131
132
133
...
139
140
141
 
 
142
143
144
145
 
146
 
147
148
149
150
151
152
153
...
174
175
176
177
178
179
180
181
182
183
 
 
 
 
 
 
184
185
186
...
236
237
238
239
240
241
242
243
 
244
245
246
247
248
249
250
...
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
 
 
 
288
289
290
291
292
293
 
294
295
296
297
...
302
303
304
 
305
306
307
 
308
309
 
310
311
312
313
314
315
316
...
344
345
346
 
347
348
349
350
351
352
 
353
354
355
356
...
373
374
375
 
376
377
378
379
...
381
382
383
 
384
385
386
387
...
396
397
398
 
399
400
401
402
...
456
457
458
459
460
461
462
 
463
464
465
466
467
468
...
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
 
 
516
517
518
 
519
520
521
522
523
524
 
525
526
527
528
...
592
593
594
595
596
597
598
599
600
...
637
638
639
 
640
641
642
643
...
679
680
681
682
683
684
685
...
778
779
780
781
782
783
784
...
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
...
875
876
877
 
878
879
880
881
882
883
884
...
917
918
919
 
920
921
922
923
...
976
977
978
 
979
980
981
982
...
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
...
1149
1150
1151
 
1152
1153
1154
1155
...
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
...
1320
1321
1322
 
1323
1324
1325
1326
...
1332
1333
1334
 
 
1335
1336
1337
1338
1339
1340
1341
1342
0
@@ -27,7 +27,9 @@
0
 
0
 #include "prot.h"
0
 #include "pq.h"
0
+#include "ms.h"
0
 #include "job.h"
0
+#include "tube.h"
0
 #include "conn.h"
0
 #include "util.h"
0
 #include "net.h"
0
@@ -36,6 +38,11 @@
0
 /* job body cannot be greater than this many bytes long */
0
 #define JOB_DATA_SIZE_LIMIT ((1 << 16) - 1)
0
 
0
+#define NAME_CHARS \
0
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
0
+ "abcdefghijklmnopqrstuvwxyz" \
0
+ "0123456789-+/;.$()"
0
+
0
 #define CMD_PUT "put "
0
 #define CMD_PEEK "peek"
0
 #define CMD_PEEKJOB "peek "
0
@@ -46,6 +53,9 @@
0
 #define CMD_KICK "kick "
0
 #define CMD_STATS "stats"
0
 #define CMD_JOBSTATS "stats "
0
+#define CMD_USE "use "
0
+#define CMD_WATCH "watch "
0
+#define CMD_IGNORE "ignore "
0
 
0
 #define CONSTSTRLEN(m) (sizeof(m) - 1)
0
 
0
@@ -58,6 +68,9 @@
0
 #define CMD_KICK_LEN CONSTSTRLEN(CMD_KICK)
0
 #define CMD_STATS_LEN CONSTSTRLEN(CMD_STATS)
0
 #define CMD_JOBSTATS_LEN CONSTSTRLEN(CMD_JOBSTATS)
0
+#define CMD_USE_LEN CONSTSTRLEN(CMD_USE)
0
+#define CMD_WATCH_LEN CONSTSTRLEN(CMD_WATCH)
0
+#define CMD_IGNORE_LEN CONSTSTRLEN(CMD_IGNORE)
0
 
0
 #define MSG_FOUND "FOUND"
0
 #define MSG_NOTFOUND "NOT_FOUND\r\n"
0
@@ -67,11 +80,13 @@
0
 #define MSG_BURIED "BURIED\r\n"
0
 #define MSG_BURIED_FMT "BURIED %llu\r\n"
0
 #define MSG_INSERTED_FMT "INSERTED %llu\r\n"
0
+#define MSG_NOT_IGNORED "NOT_IGNORED\r\n"
0
 
0
 #define MSG_NOTFOUND_LEN CONSTSTRLEN(MSG_NOTFOUND)
0
 #define MSG_DELETED_LEN CONSTSTRLEN(MSG_DELETED)
0
 #define MSG_RELEASED_LEN CONSTSTRLEN(MSG_RELEASED)
0
 #define MSG_BURIED_LEN CONSTSTRLEN(MSG_BURIED)
0
+#define MSG_NOT_IGNORED_LEN CONSTSTRLEN(MSG_NOT_IGNORED)
0
 
0
 #define MSG_OUT_OF_MEMORY "OUT_OF_MEMORY\r\n"
0
 #define MSG_INTERNAL_ERROR "INTERNAL_ERROR\r\n"
0
@@ -97,6 +112,7 @@
0
     "cmd-stats: %llu\n" \
0
     "job-timeouts: %llu\n" \
0
     "total-jobs: %llu\n" \
0
+ "current-tubes: %u\n" \
0
     "current-connections: %u\n" \
0
     "current-producers: %u\n" \
0
     "current-workers: %u\n" \