annotate memcached.c @ 3:0b6ac95a09bb default tip

Fix unix sockets support under FreeBSD.
author Maxim Dounin <mdounin@mdounin.ru>
date Wed, 03 Oct 2007 05:34:42 +0400
parents e28ab6bd21fa
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1 /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
3 * memcached - memory caching daemon
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
4 *
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
5 * http://www.danga.com/memcached/
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
6 *
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
7 * Copyright 2003 Danga Interactive, Inc. All rights reserved.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
8 *
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
9 * Use and distribution licensed under the BSD license. See
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
10 * the LICENSE file for full text.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
11 *
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
12 * Authors:
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
13 * Anatoly Vorobey <mellon@pobox.com>
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
14 * Brad Fitzpatrick <brad@danga.com>
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
15 std *
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
16 * $Id: memcached.c 570 2007-06-20 01:21:45Z plindner $
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
17 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
18 #include "memcached.h"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
19 #include <sys/stat.h>
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
20 #include <sys/socket.h>
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
21 #include <sys/un.h>
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
22 #include <sys/signal.h>
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
23 #include <sys/resource.h>
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
24 #include <sys/uio.h>
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
25
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
26 /* some POSIX systems need the following definition
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
27 * to get mlockall flags out of sys/mman.h. */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
28 #ifndef _P1003_1B_VISIBLE
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
29 #define _P1003_1B_VISIBLE
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
30 #endif
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
31 /* need this to get IOV_MAX on some platforms. */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
32 #ifndef __need_IOV_MAX
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
33 #define __need_IOV_MAX
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
34 #endif
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
35 #include <pwd.h>
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
36 #include <sys/mman.h>
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
37 #include <fcntl.h>
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
38 #include <netinet/tcp.h>
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
39 #include <arpa/inet.h>
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
40 #include <errno.h>
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
41 #include <stdlib.h>
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
42 #include <stdio.h>
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
43 #include <string.h>
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
44 #include <time.h>
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
45 #include <assert.h>
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
46 #include <limits.h>
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
47
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
48 #ifdef HAVE_MALLOC_H
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
49 /* OpenBSD has a malloc.h, but warns to use stdlib.h instead */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
50 #ifndef __OpenBSD__
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
51 #include <malloc.h>
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
52 #endif
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
53 #endif
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
54
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
55 /* FreeBSD 4.x doesn't have IOV_MAX exposed. */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
56 #ifndef IOV_MAX
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
57 #if defined(__FreeBSD__)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
58 # define IOV_MAX 1024
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
59 #endif
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
60 #endif
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
61
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
62 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
63 * forward declarations
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
64 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
65 static void drive_machine(conn *c);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
66 static int new_socket(const bool is_udp);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
67 static int server_socket(const int port, const bool is_udp);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
68 static int try_read_command(conn *c);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
69 static int try_read_network(conn *c);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
70 static int try_read_udp(conn *c);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
71
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
72 /* stats */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
73 static void stats_reset(void);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
74 static void stats_init(void);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
75
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
76 /* defaults */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
77 static void settings_init(void);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
78
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
79 /* event handling, network IO */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
80 static void event_handler(const int fd, const short which, void *arg);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
81 static void conn_close(conn *c);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
82 static void conn_init(void);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
83 static void accept_new_conns(const bool do_accept);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
84 static bool update_event(conn *c, const int new_flags);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
85 static void complete_nread(conn *c);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
86 static void process_command(conn *c, char *command);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
87 static int transmit(conn *c);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
88 static int ensure_iov_space(conn *c);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
89 static int add_iov(conn *c, const void *buf, int len);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
90 static int add_msghdr(conn *c);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
91
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
92
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
93 /* time handling */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
94 static void set_current_time(void); /* update the global variable holding
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
95 global 32-bit seconds-since-start time
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
96 (to avoid 64 bit time_t) */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
97
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
98 void pre_gdb(void);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
99 static void conn_free(conn *c);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
100
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
101 /** exported globals **/
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
102 struct stats stats;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
103 struct settings settings;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
104
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
105 /** file scope variables **/
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
106 static item **todelete = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
107 static int delcurr;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
108 static int deltotal;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
109 static conn *listen_conn;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
110 static struct event_base *main_base;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
111
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
112 #define TRANSMIT_COMPLETE 0
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
113 #define TRANSMIT_INCOMPLETE 1
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
114 #define TRANSMIT_SOFT_ERROR 2
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
115 #define TRANSMIT_HARD_ERROR 3
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
116
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
117 static int *buckets = 0; /* bucket->generation array for a managed instance */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
118
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
119 #define REALTIME_MAXDELTA 60*60*24*30
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
120 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
121 * given time value that's either unix time or delta from current unix time, return
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
122 * unix time. Use the fact that delta can't exceed one month (and real time value can't
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
123 * be that low).
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
124 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
125 static rel_time_t realtime(const time_t exptime) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
126 /* no. of seconds in 30 days - largest possible delta exptime */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
127
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
128 if (exptime == 0) return 0; /* 0 means never expire */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
129
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
130 if (exptime > REALTIME_MAXDELTA) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
131 /* if item expiration is at/before the server started, give it an
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
132 expiration time of 1 second after the server started.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
133 (because 0 means don't expire). without this, we'd
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
134 underflow and wrap around to some large value way in the
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
135 future, effectively making items expiring in the past
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
136 really expiring never */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
137 if (exptime <= stats.started)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
138 return (rel_time_t)1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
139 return (rel_time_t)(exptime - stats.started);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
140 } else {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
141 return (rel_time_t)(exptime + current_time);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
142 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
143 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
144
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
145 static void stats_init(void) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
146 stats.curr_items = stats.total_items = stats.curr_conns = stats.total_conns = stats.conn_structs = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
147 stats.get_cmds = stats.set_cmds = stats.get_hits = stats.get_misses = stats.evictions = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
148 stats.curr_bytes = stats.bytes_read = stats.bytes_written = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
149
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
150 /* make the time we started always be 2 seconds before we really
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
151 did, so time(0) - time.started is never zero. if so, things
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
152 like 'settings.oldest_live' which act as booleans as well as
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
153 values are now false in boolean context... */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
154 stats.started = time(0) - 2;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
155 stats_prefix_init();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
156 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
157
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
158 static void stats_reset(void) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
159 STATS_LOCK();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
160 stats.total_items = stats.total_conns = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
161 stats.get_cmds = stats.set_cmds = stats.get_hits = stats.get_misses = stats.evictions = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
162 stats.bytes_read = stats.bytes_written = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
163 stats_prefix_clear();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
164 STATS_UNLOCK();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
165 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
166
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
167 static void settings_init(void) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
168 settings.port = 11211;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
169 settings.udpport = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
170 settings.interf.s_addr = htonl(INADDR_ANY);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
171 settings.maxbytes = 67108864; /* default is 64MB: (64 * 1024 * 1024) */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
172 settings.maxconns = 1024; /* to limit connections-related memory to about 5MB */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
173 settings.verbose = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
174 settings.oldest_live = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
175 settings.evict_to_free = 1; /* push old items out of cache when memory runs out */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
176 settings.socketpath = NULL; /* by default, not using a unix socket */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
177 settings.managed = false;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
178 settings.factor = 1.25;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
179 settings.chunk_size = 48; /* space for a modest key and value */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
180 #ifdef USE_THREADS
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
181 settings.num_threads = 4;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
182 #else
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
183 settings.num_threads = 1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
184 #endif
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
185 settings.prefix_delimiter = ':';
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
186 settings.detail_enabled = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
187 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
188
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
189 /* returns true if a deleted item's delete-locked-time is over, and it
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
190 should be removed from the namespace */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
191 static bool item_delete_lock_over (item *it) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
192 assert(it->it_flags & ITEM_DELETED);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
193 return (current_time >= it->exptime);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
194 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
195
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
196 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
197 * Adds a message header to a connection.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
198 *
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
199 * Returns 0 on success, -1 on out-of-memory.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
200 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
201 static int add_msghdr(conn *c)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
202 {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
203 struct msghdr *msg;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
204
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
205 assert(c != NULL);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
206
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
207 if (c->msgsize == c->msgused) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
208 msg = realloc(c->msglist, c->msgsize * 2 * sizeof(struct msghdr));
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
209 if (! msg)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
210 return -1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
211 c->msglist = msg;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
212 c->msgsize *= 2;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
213 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
214
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
215 msg = c->msglist + c->msgused;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
216
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
217 /* this wipes msg_iovlen, msg_control, msg_controllen, and
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
218 msg_flags, the last 3 of which aren't defined on solaris: */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
219 memset(msg, 0, sizeof(struct msghdr));
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
220
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
221 msg->msg_iov = &c->iov[c->iovused];
3
0b6ac95a09bb Fix unix sockets support under FreeBSD.
Maxim Dounin <mdounin@mdounin.ru>
parents: 2
diff changeset
222
0b6ac95a09bb Fix unix sockets support under FreeBSD.
Maxim Dounin <mdounin@mdounin.ru>
parents: 2
diff changeset
223 if (c->request_addr_size > 0) {
0b6ac95a09bb Fix unix sockets support under FreeBSD.
Maxim Dounin <mdounin@mdounin.ru>
parents: 2
diff changeset
224 msg->msg_name = &c->request_addr;
0b6ac95a09bb Fix unix sockets support under FreeBSD.
Maxim Dounin <mdounin@mdounin.ru>
parents: 2
diff changeset
225 msg->msg_namelen = c->request_addr_size;
0b6ac95a09bb Fix unix sockets support under FreeBSD.
Maxim Dounin <mdounin@mdounin.ru>
parents: 2
diff changeset
226 }
0
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
227
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
228 c->msgbytes = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
229 c->msgused++;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
230
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
231 if (c->udp) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
232 /* Leave room for the UDP header, which we'll fill in later. */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
233 return add_iov(c, NULL, UDP_HEADER_SIZE);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
234 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
235
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
236 return 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
237 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
238
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
239
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
240 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
241 * Free list management for connections.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
242 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
243
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
244 static conn **freeconns;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
245 static int freetotal;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
246 static int freecurr;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
247
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
248
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
249 static void conn_init(void) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
250 freetotal = 200;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
251 freecurr = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
252 if (!(freeconns = (conn **)malloc(sizeof(conn *) * freetotal))) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
253 perror("malloc()");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
254 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
255 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
256 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
257
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
258 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
259 * Returns a connection from the freelist, if any. Should call this using
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
260 * conn_from_freelist() for thread safety.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
261 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
262 conn *do_conn_from_freelist() {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
263 conn *c;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
264
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
265 if (freecurr > 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
266 c = freeconns[--freecurr];
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
267 } else {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
268 c = NULL;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
269 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
270
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
271 return c;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
272 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
273
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
274 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
275 * Adds a connection to the freelist. 0 = success. Should call this using
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
276 * conn_add_to_freelist() for thread safety.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
277 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
278 int do_conn_add_to_freelist(conn *c) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
279 if (freecurr < freetotal) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
280 freeconns[freecurr++] = c;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
281 return 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
282 } else {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
283 /* try to enlarge free connections array */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
284 conn **new_freeconns = realloc(freeconns, sizeof(conn *) * freetotal * 2);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
285 if (new_freeconns) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
286 freetotal *= 2;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
287 freeconns = new_freeconns;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
288 freeconns[freecurr++] = c;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
289 return 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
290 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
291 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
292 return 1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
293 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
294
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
295 conn *conn_new(const int sfd, const int init_state, const int event_flags,
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
296 const int read_buffer_size, const bool is_udp, struct event_base *base) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
297 conn *c = conn_from_freelist();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
298
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
299 if (NULL == c) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
300 if (!(c = (conn *)malloc(sizeof(conn)))) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
301 perror("malloc()");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
302 return NULL;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
303 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
304 c->rbuf = c->wbuf = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
305 c->ilist = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
306 c->iov = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
307 c->msglist = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
308 c->hdrbuf = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
309
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
310 c->rsize = read_buffer_size;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
311 c->wsize = DATA_BUFFER_SIZE;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
312 c->isize = ITEM_LIST_INITIAL;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
313 c->iovsize = IOV_LIST_INITIAL;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
314 c->msgsize = MSG_LIST_INITIAL;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
315 c->hdrsize = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
316
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
317 c->rbuf = (char *)malloc((size_t)c->rsize);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
318 c->wbuf = (char *)malloc((size_t)c->wsize);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
319 c->ilist = (item **)malloc(sizeof(item *) * c->isize);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
320 c->iov = (struct iovec *)malloc(sizeof(struct iovec) * c->iovsize);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
321 c->msglist = (struct msghdr *)malloc(sizeof(struct msghdr) * c->msgsize);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
322
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
323 if (c->rbuf == 0 || c->wbuf == 0 || c->ilist == 0 || c->iov == 0 ||
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
324 c->msglist == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
325 if (c->rbuf != 0) free(c->rbuf);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
326 if (c->wbuf != 0) free(c->wbuf);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
327 if (c->ilist !=0) free(c->ilist);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
328 if (c->iov != 0) free(c->iov);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
329 if (c->msglist != 0) free(c->msglist);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
330 free(c);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
331 perror("malloc()");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
332 return NULL;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
333 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
334
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
335 STATS_LOCK();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
336 stats.conn_structs++;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
337 STATS_UNLOCK();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
338 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
339
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
340 if (settings.verbose > 1) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
341 if (init_state == conn_listening)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
342 fprintf(stderr, "<%d server listening\n", sfd);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
343 else if (is_udp)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
344 fprintf(stderr, "<%d server listening (udp)\n", sfd);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
345 else
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
346 fprintf(stderr, "<%d new client connection\n", sfd);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
347 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
348
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
349 c->sfd = sfd;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
350 c->udp = is_udp;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
351 c->state = init_state;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
352 c->rlbytes = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
353 c->rbytes = c->wbytes = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
354 c->wcurr = c->wbuf;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
355 c->rcurr = c->rbuf;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
356 c->ritem = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
357 c->icurr = c->ilist;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
358 c->ileft = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
359 c->iovused = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
360 c->msgcurr = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
361 c->msgused = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
362
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
363 c->write_and_go = conn_read;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
364 c->write_and_free = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
365 c->item = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
366 c->bucket = -1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
367 c->gen = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
368
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
369 event_set(&c->event, sfd, event_flags, event_handler, (void *)c);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
370 event_base_set(base, &c->event);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
371 c->ev_flags = event_flags;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
372
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
373 if (event_add(&c->event, 0) == -1) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
374 if (conn_add_to_freelist(c)) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
375 conn_free(c);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
376 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
377 return NULL;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
378 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
379
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
380 STATS_LOCK();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
381 stats.curr_conns++;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
382 stats.total_conns++;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
383 STATS_UNLOCK();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
384
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
385 return c;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
386 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
387
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
388 static void conn_cleanup(conn *c) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
389 assert(c != NULL);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
390
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
391 if (c->item) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
392 item_remove(c->item);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
393 c->item = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
394 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
395
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
396 if (c->ileft != 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
397 for (; c->ileft > 0; c->ileft--,c->icurr++) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
398 item_remove(*(c->icurr));
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
399 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
400 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
401
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
402 if (c->write_and_free) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
403 free(c->write_and_free);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
404 c->write_and_free = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
405 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
406 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
407
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
408 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
409 * Frees a connection.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
410 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
411 void conn_free(conn *c) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
412 if (c) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
413 if (c->hdrbuf)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
414 free(c->hdrbuf);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
415 if (c->msglist)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
416 free(c->msglist);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
417 if (c->rbuf)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
418 free(c->rbuf);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
419 if (c->wbuf)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
420 free(c->wbuf);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
421 if (c->ilist)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
422 free(c->ilist);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
423 if (c->iov)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
424 free(c->iov);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
425 free(c);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
426 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
427 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
428
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
429 static void conn_close(conn *c) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
430 assert(c != NULL);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
431
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
432 /* delete the event, the socket and the conn */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
433 event_del(&c->event);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
434
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
435 if (settings.verbose > 1)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
436 fprintf(stderr, "<%d connection closed.\n", c->sfd);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
437
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
438 close(c->sfd);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
439 accept_new_conns(true);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
440 conn_cleanup(c);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
441
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
442 /* if the connection has big buffers, just free it */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
443 if (c->rsize > READ_BUFFER_HIGHWAT || conn_add_to_freelist(c)) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
444 conn_free(c);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
445 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
446
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
447 STATS_LOCK();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
448 stats.curr_conns--;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
449 STATS_UNLOCK();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
450
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
451 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
452 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
453
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
454
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
455 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
456 * Shrinks a connection's buffers if they're too big. This prevents
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
457 * periodic large "get" requests from permanently chewing lots of server
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
458 * memory.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
459 *
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
460 * This should only be called in between requests since it can wipe output
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
461 * buffers!
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
462 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
463 static void conn_shrink(conn *c) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
464 assert(c != NULL);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
465
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
466 if (c->udp)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
467 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
468
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
469 if (c->rsize > READ_BUFFER_HIGHWAT && c->rbytes < DATA_BUFFER_SIZE) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
470 char *newbuf;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
471
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
472 if (c->rcurr != c->rbuf)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
473 memmove(c->rbuf, c->rcurr, (size_t)c->rbytes);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
474
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
475 newbuf = (char *)realloc((void *)c->rbuf, DATA_BUFFER_SIZE);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
476
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
477 if (newbuf) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
478 c->rbuf = newbuf;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
479 c->rsize = DATA_BUFFER_SIZE;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
480 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
481 /* TODO check other branch... */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
482 c->rcurr = c->rbuf;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
483 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
484
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
485 if (c->isize > ITEM_LIST_HIGHWAT) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
486 item **newbuf = (item**) realloc((void *)c->ilist, ITEM_LIST_INITIAL * sizeof(c->ilist[0]));
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
487 if (newbuf) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
488 c->ilist = newbuf;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
489 c->isize = ITEM_LIST_INITIAL;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
490 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
491 /* TODO check error condition? */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
492 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
493
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
494 if (c->msgsize > MSG_LIST_HIGHWAT) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
495 struct msghdr *newbuf = (struct msghdr *) realloc((void *)c->msglist, MSG_LIST_INITIAL * sizeof(c->msglist[0]));
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
496 if (newbuf) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
497 c->msglist = newbuf;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
498 c->msgsize = MSG_LIST_INITIAL;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
499 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
500 /* TODO check error condition? */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
501 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
502
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
503 if (c->iovsize > IOV_LIST_HIGHWAT) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
504 struct iovec *newbuf = (struct iovec *) realloc((void *)c->iov, IOV_LIST_INITIAL * sizeof(c->iov[0]));
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
505 if (newbuf) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
506 c->iov = newbuf;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
507 c->iovsize = IOV_LIST_INITIAL;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
508 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
509 /* TODO check return value */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
510 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
511 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
512
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
513 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
514 * Sets a connection's current state in the state machine. Any special
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
515 * processing that needs to happen on certain state transitions can
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
516 * happen here.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
517 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
518 static void conn_set_state(conn *c, int state) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
519 assert(c != NULL);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
520
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
521 if (state != c->state) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
522 if (state == conn_read) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
523 conn_shrink(c);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
524 assoc_move_next_bucket();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
525 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
526 c->state = state;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
527 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
528 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
529
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
530
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
531 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
532 * Ensures that there is room for another struct iovec in a connection's
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
533 * iov list.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
534 *
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
535 * Returns 0 on success, -1 on out-of-memory.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
536 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
537 static int ensure_iov_space(conn *c) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
538 assert(c != NULL);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
539
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
540 if (c->iovused >= c->iovsize) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
541 int i, iovnum;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
542 struct iovec *new_iov = (struct iovec *)realloc(c->iov,
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
543 (c->iovsize * 2) * sizeof(struct iovec));
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
544 if (! new_iov)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
545 return -1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
546 c->iov = new_iov;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
547 c->iovsize *= 2;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
548
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
549 /* Point all the msghdr structures at the new list. */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
550 for (i = 0, iovnum = 0; i < c->msgused; i++) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
551 c->msglist[i].msg_iov = &c->iov[iovnum];
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
552 iovnum += c->msglist[i].msg_iovlen;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
553 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
554 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
555
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
556 return 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
557 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
558
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
559
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
560 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
561 * Adds data to the list of pending data that will be written out to a
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
562 * connection.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
563 *
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
564 * Returns 0 on success, -1 on out-of-memory.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
565 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
566
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
567 static int add_iov(conn *c, const void *buf, int len) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
568 struct msghdr *m;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
569 int leftover;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
570 bool limit_to_mtu;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
571
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
572 assert(c != NULL);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
573
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
574 do {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
575 m = &c->msglist[c->msgused - 1];
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
576
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
577 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
578 * Limit UDP packets, and the first payloads of TCP replies, to
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
579 * UDP_MAX_PAYLOAD_SIZE bytes.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
580 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
581 limit_to_mtu = c->udp || (1 == c->msgused);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
582
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
583 /* We may need to start a new msghdr if this one is full. */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
584 if (m->msg_iovlen == IOV_MAX ||
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
585 (limit_to_mtu && c->msgbytes >= UDP_MAX_PAYLOAD_SIZE)) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
586 add_msghdr(c);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
587 m = &c->msglist[c->msgused - 1];
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
588 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
589
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
590 if (ensure_iov_space(c) != 0)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
591 return -1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
592
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
593 /* If the fragment is too big to fit in the datagram, split it up */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
594 if (limit_to_mtu && len + c->msgbytes > UDP_MAX_PAYLOAD_SIZE) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
595 leftover = len + c->msgbytes - UDP_MAX_PAYLOAD_SIZE;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
596 len -= leftover;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
597 } else {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
598 leftover = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
599 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
600
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
601 m = &c->msglist[c->msgused - 1];
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
602 m->msg_iov[m->msg_iovlen].iov_base = (void *)buf;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
603 m->msg_iov[m->msg_iovlen].iov_len = len;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
604
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
605 c->msgbytes += len;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
606 c->iovused++;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
607 m->msg_iovlen++;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
608
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
609 buf = ((char *)buf) + len;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
610 len = leftover;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
611 } while (leftover > 0);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
612
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
613 return 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
614 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
615
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
616
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
617 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
618 * Constructs a set of UDP headers and attaches them to the outgoing messages.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
619 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
620 static int build_udp_headers(conn *c) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
621 int i;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
622 unsigned char *hdr;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
623
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
624 assert(c != NULL);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
625
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
626 if (c->msgused > c->hdrsize) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
627 void *new_hdrbuf;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
628 if (c->hdrbuf)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
629 new_hdrbuf = realloc(c->hdrbuf, c->msgused * 2 * UDP_HEADER_SIZE);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
630 else
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
631 new_hdrbuf = malloc(c->msgused * 2 * UDP_HEADER_SIZE);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
632 if (! new_hdrbuf)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
633 return -1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
634 c->hdrbuf = (unsigned char *)new_hdrbuf;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
635 c->hdrsize = c->msgused * 2;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
636 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
637
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
638 hdr = c->hdrbuf;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
639 for (i = 0; i < c->msgused; i++) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
640 c->msglist[i].msg_iov[0].iov_base = hdr;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
641 c->msglist[i].msg_iov[0].iov_len = UDP_HEADER_SIZE;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
642 *hdr++ = c->request_id / 256;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
643 *hdr++ = c->request_id % 256;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
644 *hdr++ = i / 256;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
645 *hdr++ = i % 256;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
646 *hdr++ = c->msgused / 256;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
647 *hdr++ = c->msgused % 256;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
648 *hdr++ = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
649 *hdr++ = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
650 assert((void *) hdr == (void *)c->msglist[i].msg_iov[0].iov_base + UDP_HEADER_SIZE);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
651 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
652
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
653 return 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
654 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
655
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
656
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
657 static void out_string(conn *c, const char *str) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
658 size_t len;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
659
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
660 assert(c != NULL);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
661
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
662 if (settings.verbose > 1)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
663 fprintf(stderr, ">%d %s\n", c->sfd, str);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
664
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
665 len = strlen(str);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
666 if ((len + 2) > c->wsize) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
667 /* ought to be always enough. just fail for simplicity */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
668 str = "SERVER_ERROR output line too long";
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
669 len = strlen(str);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
670 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
671
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
672 memcpy(c->wbuf, str, len);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
673 memcpy(c->wbuf + len, "\r\n", 3);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
674 c->wbytes = len + 2;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
675 c->wcurr = c->wbuf;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
676
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
677 conn_set_state(c, conn_write);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
678 c->write_and_go = conn_read;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
679 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
680 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
681
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
682 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
683 * we get here after reading the value in set/add/replace commands. The command
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
684 * has been stored in c->item_comm, and the item is ready in c->item.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
685 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
686
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
687 static void complete_nread(conn *c) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
688 assert(c != NULL);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
689
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
690 item *it = c->item;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
691 int comm = c->item_comm;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
692
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
693 STATS_LOCK();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
694 stats.set_cmds++;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
695 STATS_UNLOCK();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
696
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
697 if (strncmp(ITEM_data(it) + it->nbytes - 2, "\r\n", 2) != 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
698 out_string(c, "CLIENT_ERROR bad data chunk");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
699 } else {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
700 if (store_item(it, comm)) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
701 out_string(c, "STORED");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
702 } else {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
703 out_string(c, "NOT_STORED");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
704 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
705 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
706
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
707 item_remove(c->item); /* release the c->item reference */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
708 c->item = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
709 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
710
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
711 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
712 * Stores an item in the cache according to the semantics of one of the set
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
713 * commands. In threaded mode, this is protected by the cache lock.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
714 *
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
715 * Returns true if the item was stored.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
716 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
717 int do_store_item(item *it, int comm) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
718 char *key = ITEM_key(it);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
719 bool delete_locked = false;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
720 item *old_it = do_item_get_notedeleted(key, it->nkey, &delete_locked);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
721 int stored = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
722
2
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
723 item *new_it = NULL;
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
724 int flags;
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
725
0
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
726 if (old_it != NULL && comm == NREAD_ADD) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
727 /* add only adds a nonexistent item, but promote to head of LRU */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
728 do_item_update(old_it);
2
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
729 } else if (!old_it && (comm == NREAD_REPLACE
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
730 || comm == NREAD_APPEND || comm == NREAD_PREPEND))
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
731 {
0
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
732 /* replace only replaces an existing value; don't store */
2
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
733 } else if (delete_locked && (comm == NREAD_REPLACE || comm == NREAD_ADD
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
734 || comm == NREAD_APPEND || comm == NREAD_PREPEND))
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
735 {
0
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
736 /* replace and add can't override delete locks; don't store */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
737 } else {
2
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
738
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
739 /*
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
740 * Append - combine new and old record into single one. Here it's
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
741 * atomic and thread-safe.
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
742 */
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
743
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
744 if (comm == NREAD_APPEND || comm == NREAD_PREPEND) {
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
745
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
746 /* we have it and old_it here - alloc memory to hold both */
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
747 /* flags was already lost - so recover them from ITEM_suffix(it) */
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
748
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
749 flags = (int) strtol(ITEM_suffix(it), (char **) NULL, 10);
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
750
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
751 new_it = do_item_alloc(key, it->nkey, flags, it->exptime, it->nbytes + old_it->nbytes - 2 /* CRLF */);
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
752
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
753 if (new_it == NULL) {
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
754 /* SERVER_ERROR out of memory */
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
755 return 0;
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
756 }
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
757
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
758 /* copy data from it and old_it to new_it */
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
759
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
760 if (comm == NREAD_APPEND) {
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
761 memcpy(ITEM_data(new_it), ITEM_data(old_it), old_it->nbytes);
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
762 memcpy(ITEM_data(new_it) + old_it->nbytes - 2 /* CRLF */, ITEM_data(it), it->nbytes);
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
763 } else {
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
764 /* NREAD_PREPEND */
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
765 memcpy(ITEM_data(new_it), ITEM_data(it), it->nbytes);
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
766 memcpy(ITEM_data(new_it) + it->nbytes - 2 /* CRLF */, ITEM_data(old_it), old_it->nbytes);
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
767 }
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
768
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
769 it = new_it;
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
770 }
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
771
0
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
772 /* "set" commands can override the delete lock
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
773 window... in which case we have to find the old hidden item
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
774 that's in the namespace/LRU but wasn't returned by
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
775 item_get.... because we need to replace it */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
776 if (delete_locked)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
777 old_it = do_item_get_nocheck(key, it->nkey);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
778
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
779 if (old_it != NULL)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
780 do_item_replace(old_it, it);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
781 else
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
782 do_item_link(it);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
783
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
784 stored = 1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
785 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
786
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
787 if (old_it)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
788 do_item_remove(old_it); /* release our reference */
2
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
789 if (new_it)
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
790 do_item_remove(new_it);
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
791
0
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
792 return stored;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
793 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
794
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
795 typedef struct token_s {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
796 char *value;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
797 size_t length;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
798 } token_t;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
799
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
800 #define COMMAND_TOKEN 0
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
801 #define SUBCOMMAND_TOKEN 1
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
802 #define KEY_TOKEN 1
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
803 #define KEY_MAX_LENGTH 250
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
804
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
805 #define MAX_TOKENS 6
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
806
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
807 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
808 * Tokenize the command string by replacing whitespace with '\0' and update
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
809 * the token array tokens with pointer to start of each token and length.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
810 * Returns total number of tokens. The last valid token is the terminal
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
811 * token (value points to the first unprocessed character of the string and
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
812 * length zero).
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
813 *
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
814 * Usage example:
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
815 *
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
816 * while(tokenize_command(command, ncommand, tokens, max_tokens) > 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
817 * for(int ix = 0; tokens[ix].length != 0; ix++) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
818 * ...
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
819 * }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
820 * ncommand = tokens[ix].value - command;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
821 * command = tokens[ix].value;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
822 * }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
823 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
824 static size_t tokenize_command(char *command, token_t *tokens, const size_t max_tokens) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
825 char *s, *e;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
826 size_t ntokens = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
827
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
828 assert(command != NULL && tokens != NULL && max_tokens > 1);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
829
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
830 for (s = e = command; ntokens < max_tokens - 1; ++e) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
831 if (*e == ' ') {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
832 if (s != e) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
833 tokens[ntokens].value = s;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
834 tokens[ntokens].length = e - s;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
835 ntokens++;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
836 *e = '\0';
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
837 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
838 s = e + 1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
839 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
840 else if (*e == '\0') {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
841 if (s != e) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
842 tokens[ntokens].value = s;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
843 tokens[ntokens].length = e - s;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
844 ntokens++;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
845 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
846
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
847 break; /* string end */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
848 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
849 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
850
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
851 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
852 * If we scanned the whole string, the terminal value pointer is null,
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
853 * otherwise it is the first unprocessed character.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
854 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
855 tokens[ntokens].value = *e == '\0' ? NULL : e;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
856 tokens[ntokens].length = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
857 ntokens++;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
858
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
859 return ntokens;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
860 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
861
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
862 inline static void process_stats_detail(conn *c, const char *command) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
863 assert(c != NULL);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
864
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
865 if (strcmp(command, "on") == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
866 settings.detail_enabled = 1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
867 out_string(c, "OK");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
868 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
869 else if (strcmp(command, "off") == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
870 settings.detail_enabled = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
871 out_string(c, "OK");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
872 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
873 else if (strcmp(command, "dump") == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
874 int len;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
875 char *stats = stats_prefix_dump(&len);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
876 if (NULL != stats) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
877 c->write_and_free = stats;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
878 c->wcurr = stats;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
879 c->wbytes = len;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
880 conn_set_state(c, conn_write);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
881 c->write_and_go = conn_read;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
882 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
883 else {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
884 out_string(c, "SERVER_ERROR");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
885 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
886 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
887 else {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
888 out_string(c, "CLIENT_ERROR usage: stats detail on|off|dump");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
889 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
890 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
891
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
892 static void process_stat(conn *c, token_t *tokens, const size_t ntokens) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
893 rel_time_t now = current_time;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
894 char *command;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
895 char *subcommand;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
896
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
897 assert(c != NULL);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
898
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
899 if(ntokens < 2) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
900 out_string(c, "CLIENT_ERROR bad command line");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
901 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
902 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
903
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
904 command = tokens[COMMAND_TOKEN].value;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
905
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
906 if (ntokens == 2 && strcmp(command, "stats") == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
907 char temp[1024];
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
908 pid_t pid = getpid();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
909 char *pos = temp;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
910
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
911 #ifndef WIN32
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
912 struct rusage usage;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
913 getrusage(RUSAGE_SELF, &usage);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
914 #endif /* !WIN32 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
915
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
916 STATS_LOCK();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
917 pos += sprintf(pos, "STAT pid %u\r\n", pid);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
918 pos += sprintf(pos, "STAT uptime %u\r\n", now);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
919 pos += sprintf(pos, "STAT time %ld\r\n", now + stats.started);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
920 pos += sprintf(pos, "STAT version " VERSION "\r\n");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
921 pos += sprintf(pos, "STAT pointer_size %d\r\n", 8 * sizeof(void *));
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
922 #ifndef WIN32
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
923 pos += sprintf(pos, "STAT rusage_user %ld.%06ld\r\n", usage.ru_utime.tv_sec, usage.ru_utime.tv_usec);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
924 pos += sprintf(pos, "STAT rusage_system %ld.%06ld\r\n", usage.ru_stime.tv_sec, usage.ru_stime.tv_usec);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
925 #endif /* !WIN32 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
926 pos += sprintf(pos, "STAT curr_items %u\r\n", stats.curr_items);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
927 pos += sprintf(pos, "STAT total_items %u\r\n", stats.total_items);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
928 pos += sprintf(pos, "STAT bytes %llu\r\n", stats.curr_bytes);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
929 pos += sprintf(pos, "STAT curr_connections %u\r\n", stats.curr_conns - 1); /* ignore listening conn */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
930 pos += sprintf(pos, "STAT total_connections %u\r\n", stats.total_conns);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
931 pos += sprintf(pos, "STAT connection_structures %u\r\n", stats.conn_structs);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
932 pos += sprintf(pos, "STAT cmd_get %llu\r\n", stats.get_cmds);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
933 pos += sprintf(pos, "STAT cmd_set %llu\r\n", stats.set_cmds);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
934 pos += sprintf(pos, "STAT get_hits %llu\r\n", stats.get_hits);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
935 pos += sprintf(pos, "STAT get_misses %llu\r\n", stats.get_misses);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
936 pos += sprintf(pos, "STAT evictions %llu\r\n", stats.evictions);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
937 pos += sprintf(pos, "STAT bytes_read %llu\r\n", stats.bytes_read);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
938 pos += sprintf(pos, "STAT bytes_written %llu\r\n", stats.bytes_written);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
939 pos += sprintf(pos, "STAT limit_maxbytes %llu\r\n", (uint64_t) settings.maxbytes);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
940 pos += sprintf(pos, "STAT threads %u\r\n", settings.num_threads);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
941 pos += sprintf(pos, "END");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
942 STATS_UNLOCK();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
943 out_string(c, temp);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
944 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
945 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
946
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
947 subcommand = tokens[SUBCOMMAND_TOKEN].value;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
948
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
949 if (strcmp(subcommand, "reset") == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
950 stats_reset();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
951 out_string(c, "RESET");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
952 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
953 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
954
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
955 #ifdef HAVE_MALLOC_H
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
956 #ifdef HAVE_STRUCT_MALLINFO
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
957 if (strcmp(subcommand, "malloc") == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
958 char temp[512];
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
959 struct mallinfo info;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
960 char *pos = temp;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
961
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
962 info = mallinfo();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
963 pos += sprintf(pos, "STAT arena_size %d\r\n", info.arena);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
964 pos += sprintf(pos, "STAT free_chunks %d\r\n", info.ordblks);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
965 pos += sprintf(pos, "STAT fastbin_blocks %d\r\n", info.smblks);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
966 pos += sprintf(pos, "STAT mmapped_regions %d\r\n", info.hblks);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
967 pos += sprintf(pos, "STAT mmapped_space %d\r\n", info.hblkhd);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
968 pos += sprintf(pos, "STAT max_total_alloc %d\r\n", info.usmblks);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
969 pos += sprintf(pos, "STAT fastbin_space %d\r\n", info.fsmblks);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
970 pos += sprintf(pos, "STAT total_alloc %d\r\n", info.uordblks);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
971 pos += sprintf(pos, "STAT total_free %d\r\n", info.fordblks);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
972 pos += sprintf(pos, "STAT releasable_space %d\r\nEND", info.keepcost);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
973 out_string(c, temp);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
974 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
975 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
976 #endif /* HAVE_STRUCT_MALLINFO */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
977 #endif /* HAVE_MALLOC_H */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
978
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
979 #if !defined(WIN32) || !defined(__APPLE__)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
980 if (strcmp(subcommand, "maps") == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
981 char *wbuf;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
982 int wsize = 8192; /* should be enough */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
983 int fd;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
984 int res;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
985
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
986 if (!(wbuf = (char *)malloc(wsize))) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
987 out_string(c, "SERVER_ERROR out of memory");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
988 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
989 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
990
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
991 fd = open("/proc/self/maps", O_RDONLY);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
992 if (fd == -1) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
993 out_string(c, "SERVER_ERROR cannot open the maps file");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
994 free(wbuf);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
995 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
996 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
997
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
998 res = read(fd, wbuf, wsize - 6); /* 6 = END\r\n\0 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
999 if (res == wsize - 6) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1000 out_string(c, "SERVER_ERROR buffer overflow");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1001 free(wbuf); close(fd);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1002 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1003 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1004 if (res == 0 || res == -1) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1005 out_string(c, "SERVER_ERROR can't read the maps file");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1006 free(wbuf); close(fd);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1007 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1008 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1009 memcpy(wbuf + res, "END\r\n", 6);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1010 c->write_and_free = wbuf;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1011 c->wcurr = wbuf;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1012 c->wbytes = res + 5; // Don't write the terminal '\0'
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1013 conn_set_state(c, conn_write);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1014 c->write_and_go = conn_read;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1015 close(fd);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1016 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1017 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1018 #endif
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1019
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1020 if (strcmp(subcommand, "cachedump") == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1021
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1022 char *buf;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1023 unsigned int bytes, id, limit = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1024
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1025 if(ntokens < 5) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1026 out_string(c, "CLIENT_ERROR bad command line");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1027 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1028 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1029
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1030 id = strtoul(tokens[2].value, NULL, 10);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1031 limit = strtoul(tokens[3].value, NULL, 10);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1032
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1033 if(errno == ERANGE) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1034 out_string(c, "CLIENT_ERROR bad command line format");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1035 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1036 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1037
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1038 buf = item_cachedump(id, limit, &bytes);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1039 if (buf == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1040 out_string(c, "SERVER_ERROR out of memory");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1041 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1042 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1043
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1044 c->write_and_free = buf;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1045 c->wcurr = buf;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1046 c->wbytes = bytes;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1047 conn_set_state(c, conn_write);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1048 c->write_and_go = conn_read;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1049 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1050 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1051
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1052 if (strcmp(subcommand, "slabs") == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1053 int bytes = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1054 char *buf = slabs_stats(&bytes);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1055 if (!buf) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1056 out_string(c, "SERVER_ERROR out of memory");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1057 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1058 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1059 c->write_and_free = buf;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1060 c->wcurr = buf;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1061 c->wbytes = bytes;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1062 conn_set_state(c, conn_write);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1063 c->write_and_go = conn_read;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1064 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1065 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1066
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1067 if (strcmp(subcommand, "items") == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1068 char buffer[4096];
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1069 item_stats(buffer, 4096);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1070 out_string(c, buffer);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1071 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1072 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1073
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1074 if (strcmp(subcommand, "detail") == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1075 if (ntokens < 4)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1076 process_stats_detail(c, ""); /* outputs the error message */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1077 else
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1078 process_stats_detail(c, tokens[2].value);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1079 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1080 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1081
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1082 if (strcmp(subcommand, "sizes") == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1083 int bytes = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1084 char *buf = item_stats_sizes(&bytes);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1085 if (! buf) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1086 out_string(c, "SERVER_ERROR out of memory");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1087 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1088 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1089
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1090 c->write_and_free = buf;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1091 c->wcurr = buf;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1092 c->wbytes = bytes;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1093 conn_set_state(c, conn_write);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1094 c->write_and_go = conn_read;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1095 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1096 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1097
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1098 out_string(c, "ERROR");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1099 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1100
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1101 /* ntokens is overwritten here... shrug.. */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1102 static inline void process_get_command(conn *c, token_t *tokens, size_t ntokens) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1103 char *key;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1104 size_t nkey;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1105 int i = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1106 item *it;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1107 token_t *key_token = &tokens[KEY_TOKEN];
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1108
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1109 assert(c != NULL);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1110
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1111 if (settings.managed) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1112 int bucket = c->bucket;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1113 if (bucket == -1) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1114 out_string(c, "CLIENT_ERROR no BG data in managed mode");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1115 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1116 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1117 c->bucket = -1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1118 if (buckets[bucket] != c->gen) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1119 out_string(c, "ERROR_NOT_OWNER");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1120 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1121 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1122 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1123
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1124 do {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1125 while(key_token->length != 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1126
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1127 key = key_token->value;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1128 nkey = key_token->length;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1129
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1130 if(nkey > KEY_MAX_LENGTH) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1131 out_string(c, "CLIENT_ERROR bad command line format");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1132 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1133 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1134
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1135 STATS_LOCK();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1136 stats.get_cmds++;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1137 STATS_UNLOCK();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1138 it = item_get(key, nkey);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1139 if (settings.detail_enabled) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1140 stats_prefix_record_get(key, NULL != it);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1141 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1142 if (it) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1143 if (i >= c->isize) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1144 item **new_list = realloc(c->ilist, sizeof(item *) * c->isize * 2);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1145 if (new_list) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1146 c->isize *= 2;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1147 c->ilist = new_list;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1148 } else break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1149 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1150
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1151 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1152 * Construct the response. Each hit adds three elements to the
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1153 * outgoing data list:
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1154 * "VALUE "
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1155 * key
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1156 * " " + flags + " " + data length + "\r\n" + data (with \r\n)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1157 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1158 if (add_iov(c, "VALUE ", 6) != 0 ||
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1159 add_iov(c, ITEM_key(it), it->nkey) != 0 ||
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1160 add_iov(c, ITEM_suffix(it), it->nsuffix + it->nbytes) != 0)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1161 {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1162 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1163 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1164 if (settings.verbose > 1)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1165 fprintf(stderr, ">%d sending key %s\n", c->sfd, ITEM_key(it));
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1166
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1167 /* item_get() has incremented it->refcount for us */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1168 STATS_LOCK();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1169 stats.get_hits++;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1170 STATS_UNLOCK();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1171 item_update(it);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1172 *(c->ilist + i) = it;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1173 i++;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1174
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1175 } else {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1176 STATS_LOCK();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1177 stats.get_misses++;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1178 STATS_UNLOCK();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1179 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1180
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1181 key_token++;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1182 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1183
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1184 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1185 * If the command string hasn't been fully processed, get the next set
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1186 * of tokens.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1187 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1188 if(key_token->value != NULL) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1189 ntokens = tokenize_command(key_token->value, tokens, MAX_TOKENS);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1190 key_token = tokens;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1191 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1192
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1193 } while(key_token->value != NULL);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1194
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1195 c->icurr = c->ilist;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1196 c->ileft = i;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1197
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1198 if (settings.verbose > 1)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1199 fprintf(stderr, ">%d END\n", c->sfd);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1200 add_iov(c, "END\r\n", 5);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1201
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1202 if (c->udp && build_udp_headers(c) != 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1203 out_string(c, "SERVER_ERROR out of memory");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1204 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1205 else {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1206 conn_set_state(c, conn_mwrite);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1207 c->msgcurr = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1208 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1209 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1210 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1211
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1212 static void process_update_command(conn *c, token_t *tokens, const size_t ntokens, int comm) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1213 char *key;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1214 size_t nkey;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1215 int flags;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1216 time_t exptime;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1217 int vlen;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1218 item *it;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1219
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1220 assert(c != NULL);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1221
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1222 if (tokens[KEY_TOKEN].length > KEY_MAX_LENGTH) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1223 out_string(c, "CLIENT_ERROR bad command line format");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1224 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1225 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1226
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1227 key = tokens[KEY_TOKEN].value;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1228 nkey = tokens[KEY_TOKEN].length;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1229
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1230 flags = strtoul(tokens[2].value, NULL, 10);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1231 exptime = strtol(tokens[3].value, NULL, 10);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1232 vlen = strtol(tokens[4].value, NULL, 10);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1233
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1234 if(errno == ERANGE || ((flags == 0 || exptime == 0) && errno == EINVAL)) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1235 out_string(c, "CLIENT_ERROR bad command line format");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1236 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1237 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1238
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1239 if (settings.detail_enabled) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1240 stats_prefix_record_set(key);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1241 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1242
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1243 if (settings.managed) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1244 int bucket = c->bucket;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1245 if (bucket == -1) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1246 out_string(c, "CLIENT_ERROR no BG data in managed mode");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1247 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1248 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1249 c->bucket = -1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1250 if (buckets[bucket] != c->gen) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1251 out_string(c, "ERROR_NOT_OWNER");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1252 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1253 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1254 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1255
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1256 it = item_alloc(key, nkey, flags, realtime(exptime), vlen+2);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1257
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1258 if (it == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1259 if (! item_size_ok(nkey, flags, vlen + 2))
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1260 out_string(c, "SERVER_ERROR object too large for cache");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1261 else
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1262 out_string(c, "SERVER_ERROR out of memory");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1263 /* swallow the data line */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1264 c->write_and_go = conn_swallow;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1265 c->sbytes = vlen + 2;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1266 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1267 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1268
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1269 c->item_comm = comm;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1270 c->item = it;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1271 c->ritem = ITEM_data(it);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1272 c->rlbytes = it->nbytes;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1273 conn_set_state(c, conn_nread);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1274 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1275
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1276 static void process_arithmetic_command(conn *c, token_t *tokens, const size_t ntokens, const int incr) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1277 char temp[32];
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1278 item *it;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1279 unsigned int delta;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1280 char *key;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1281 size_t nkey;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1282
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1283 assert(c != NULL);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1284
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1285 if(tokens[KEY_TOKEN].length > KEY_MAX_LENGTH) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1286 out_string(c, "CLIENT_ERROR bad command line format");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1287 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1288 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1289
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1290 key = tokens[KEY_TOKEN].value;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1291 nkey = tokens[KEY_TOKEN].length;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1292
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1293 if (settings.managed) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1294 int bucket = c->bucket;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1295 if (bucket == -1) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1296 out_string(c, "CLIENT_ERROR no BG data in managed mode");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1297 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1298 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1299 c->bucket = -1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1300 if (buckets[bucket] != c->gen) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1301 out_string(c, "ERROR_NOT_OWNER");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1302 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1303 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1304 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1305
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1306 delta = strtoul(tokens[2].value, NULL, 10);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1307
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1308 if(errno == ERANGE) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1309 out_string(c, "CLIENT_ERROR bad command line format");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1310 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1311 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1312
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1313 it = item_get(key, nkey);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1314 if (!it) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1315 out_string(c, "NOT_FOUND");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1316 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1317 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1318
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1319 out_string(c, add_delta(it, incr, delta, temp));
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1320 item_remove(it); /* release our reference */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1321 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1322
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1323 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1324 * adds a delta value to a numeric item.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1325 *
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1326 * it item to adjust
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1327 * incr true to increment value, false to decrement
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1328 * delta amount to adjust value by
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1329 * buf buffer for response string
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1330 *
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1331 * returns a response string to send back to the client.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1332 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1333 char *do_add_delta(item *it, const int incr, unsigned int delta, char *buf) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1334 char *ptr;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1335 unsigned int value;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1336 int res;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1337
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1338 ptr = ITEM_data(it);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1339 while ((*ptr != '\0') && (*ptr < '0' && *ptr > '9')) ptr++; // BUG: can't be true
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1340
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1341 value = strtol(ptr, NULL, 10);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1342
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1343 if(errno == ERANGE) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1344 return "CLIENT_ERROR cannot increment or decrement non-numeric value";
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1345 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1346
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1347 if (incr != 0)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1348 value += delta;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1349 else {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1350 if (delta >= value) value = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1351 else value -= delta;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1352 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1353 snprintf(buf, 32, "%u", value);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1354 res = strlen(buf);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1355 if (res + 2 > it->nbytes) { /* need to realloc */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1356 item *new_it;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1357 new_it = do_item_alloc(ITEM_key(it), it->nkey, atoi(ITEM_suffix(it) + 1), it->exptime, res + 2 );
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1358 if (new_it == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1359 return "SERVER_ERROR out of memory";
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1360 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1361 memcpy(ITEM_data(new_it), buf, res);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1362 memcpy(ITEM_data(new_it) + res, "\r\n", 3);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1363 do_item_replace(it, new_it);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1364 do_item_remove(new_it); /* release our reference */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1365 } else { /* replace in-place */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1366 memcpy(ITEM_data(it), buf, res);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1367 memset(ITEM_data(it) + res, ' ', it->nbytes - res - 2);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1368 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1369
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1370 return buf;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1371 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1372
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1373 static void process_delete_command(conn *c, token_t *tokens, const size_t ntokens) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1374 char *key;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1375 size_t nkey;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1376 item *it;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1377 time_t exptime = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1378
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1379 assert(c != NULL);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1380
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1381 if (settings.managed) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1382 int bucket = c->bucket;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1383 if (bucket == -1) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1384 out_string(c, "CLIENT_ERROR no BG data in managed mode");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1385 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1386 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1387 c->bucket = -1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1388 if (buckets[bucket] != c->gen) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1389 out_string(c, "ERROR_NOT_OWNER");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1390 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1391 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1392 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1393
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1394 key = tokens[KEY_TOKEN].value;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1395 nkey = tokens[KEY_TOKEN].length;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1396
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1397 if(nkey > KEY_MAX_LENGTH) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1398 out_string(c, "CLIENT_ERROR bad command line format");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1399 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1400 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1401
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1402 if(ntokens == 4) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1403 exptime = strtol(tokens[2].value, NULL, 10);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1404
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1405 if(errno == ERANGE) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1406 out_string(c, "CLIENT_ERROR bad command line format");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1407 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1408 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1409 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1410
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1411 if (settings.detail_enabled) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1412 stats_prefix_record_delete(key);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1413 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1414
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1415 it = item_get(key, nkey);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1416 if (it) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1417 if (exptime == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1418 item_unlink(it);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1419 item_remove(it); /* release our reference */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1420 out_string(c, "DELETED");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1421 } else {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1422 /* our reference will be transfered to the delete queue */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1423 out_string(c, defer_delete(it, exptime));
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1424 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1425 } else {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1426 out_string(c, "NOT_FOUND");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1427 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1428 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1429
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1430 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1431 * Adds an item to the deferred-delete list so it can be reaped later.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1432 *
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1433 * Returns the result to send to the client.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1434 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1435 char *do_defer_delete(item *it, time_t exptime)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1436 {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1437 if (delcurr >= deltotal) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1438 item **new_delete = realloc(todelete, sizeof(item *) * deltotal * 2);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1439 if (new_delete) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1440 todelete = new_delete;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1441 deltotal *= 2;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1442 } else {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1443 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1444 * can't delete it immediately, user wants a delay,
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1445 * but we ran out of memory for the delete queue
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1446 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1447 item_remove(it); /* release reference */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1448 return "SERVER_ERROR out of memory";
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1449 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1450 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1451
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1452 /* use its expiration time as its deletion time now */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1453 it->exptime = realtime(exptime);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1454 it->it_flags |= ITEM_DELETED;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1455 todelete[delcurr++] = it;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1456
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1457 return "DELETED";
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1458 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1459
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1460 static void process_verbosity_command(conn *c, token_t *tokens, const size_t ntokens) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1461 unsigned int level;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1462
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1463 assert(c != NULL);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1464
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1465 level = strtoul(tokens[1].value, NULL, 10);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1466 settings.verbose = level > MAX_VERBOSITY_LEVEL ? MAX_VERBOSITY_LEVEL : level;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1467 out_string(c, "OK");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1468 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1469 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1470
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1471 static void process_command(conn *c, char *command) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1472
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1473 token_t tokens[MAX_TOKENS];
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1474 size_t ntokens;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1475 int comm;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1476
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1477 assert(c != NULL);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1478
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1479 if (settings.verbose > 1)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1480 fprintf(stderr, "<%d %s\n", c->sfd, command);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1481
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1482 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1483 * for commands set/add/replace, we build an item and read the data
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1484 * directly into it, then continue in nread_complete().
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1485 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1486
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1487 c->msgcurr = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1488 c->msgused = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1489 c->iovused = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1490 if (add_msghdr(c) != 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1491 out_string(c, "SERVER_ERROR out of memory");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1492 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1493 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1494
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1495 ntokens = tokenize_command(command, tokens, MAX_TOKENS);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1496
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1497 if (ntokens >= 3 &&
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1498 ((strcmp(tokens[COMMAND_TOKEN].value, "get") == 0) ||
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1499 (strcmp(tokens[COMMAND_TOKEN].value, "bget") == 0))) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1500
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1501 process_get_command(c, tokens, ntokens);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1502
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1503 } else if (ntokens == 6 &&
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1504 ((strcmp(tokens[COMMAND_TOKEN].value, "add") == 0 && (comm = NREAD_ADD)) ||
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1505 (strcmp(tokens[COMMAND_TOKEN].value, "set") == 0 && (comm = NREAD_SET)) ||
2
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
1506 (strcmp(tokens[COMMAND_TOKEN].value, "append") == 0 && (comm = NREAD_APPEND)) ||
e28ab6bd21fa Append/prepend commands.
Maxim Dounin <mdounin@mdounin.ru>
parents: 0
diff changeset
1507 (strcmp(tokens[COMMAND_TOKEN].value, "prepend") == 0 && (comm = NREAD_PREPEND)) ||
0
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1508 (strcmp(tokens[COMMAND_TOKEN].value, "replace") == 0 && (comm = NREAD_REPLACE)))) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1509
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1510 process_update_command(c, tokens, ntokens, comm);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1511
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1512 } else if (ntokens == 4 && (strcmp(tokens[COMMAND_TOKEN].value, "incr") == 0)) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1513
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1514 process_arithmetic_command(c, tokens, ntokens, 1);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1515
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1516 } else if (ntokens == 4 && (strcmp(tokens[COMMAND_TOKEN].value, "decr") == 0)) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1517
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1518 process_arithmetic_command(c, tokens, ntokens, 0);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1519
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1520 } else if (ntokens >= 3 && ntokens <= 4 && (strcmp(tokens[COMMAND_TOKEN].value, "delete") == 0)) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1521
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1522 process_delete_command(c, tokens, ntokens);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1523
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1524 } else if (ntokens == 3 && strcmp(tokens[COMMAND_TOKEN].value, "own") == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1525 unsigned int bucket, gen;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1526 if (!settings.managed) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1527 out_string(c, "CLIENT_ERROR not a managed instance");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1528 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1529 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1530
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1531 if (sscanf(tokens[1].value, "%u:%u", &bucket,&gen) == 2) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1532 if ((bucket < 0) || (bucket >= MAX_BUCKETS)) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1533 out_string(c, "CLIENT_ERROR bucket number out of range");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1534 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1535 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1536 buckets[bucket] = gen;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1537 out_string(c, "OWNED");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1538 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1539 } else {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1540 out_string(c, "CLIENT_ERROR bad format");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1541 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1542 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1543
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1544 } else if (ntokens == 3 && (strcmp(tokens[COMMAND_TOKEN].value, "disown")) == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1545
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1546 int bucket;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1547 if (!settings.managed) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1548 out_string(c, "CLIENT_ERROR not a managed instance");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1549 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1550 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1551 if (sscanf(tokens[1].value, "%u", &bucket) == 1) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1552 if ((bucket < 0) || (bucket >= MAX_BUCKETS)) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1553 out_string(c, "CLIENT_ERROR bucket number out of range");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1554 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1555 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1556 buckets[bucket] = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1557 out_string(c, "DISOWNED");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1558 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1559 } else {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1560 out_string(c, "CLIENT_ERROR bad format");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1561 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1562 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1563
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1564 } else if (ntokens == 3 && (strcmp(tokens[COMMAND_TOKEN].value, "bg")) == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1565 int bucket, gen;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1566 if (!settings.managed) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1567 out_string(c, "CLIENT_ERROR not a managed instance");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1568 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1569 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1570 if (sscanf(tokens[1].value, "%u:%u", &bucket, &gen) == 2) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1571 /* we never write anything back, even if input's wrong */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1572 if ((bucket < 0) || (bucket >= MAX_BUCKETS) || (gen <= 0)) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1573 /* do nothing, bad input */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1574 } else {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1575 c->bucket = bucket;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1576 c->gen = gen;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1577 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1578 conn_set_state(c, conn_read);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1579 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1580 } else {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1581 out_string(c, "CLIENT_ERROR bad format");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1582 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1583 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1584
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1585 } else if (ntokens >= 2 && (strcmp(tokens[COMMAND_TOKEN].value, "stats") == 0)) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1586
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1587 process_stat(c, tokens, ntokens);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1588
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1589 } else if (ntokens >= 2 && ntokens <= 3 && (strcmp(tokens[COMMAND_TOKEN].value, "flush_all") == 0)) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1590 time_t exptime = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1591 set_current_time();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1592
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1593 if(ntokens == 2) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1594 settings.oldest_live = current_time - 1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1595 item_flush_expired();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1596 out_string(c, "OK");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1597 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1598 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1599
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1600 exptime = strtol(tokens[1].value, NULL, 10);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1601 if(errno == ERANGE) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1602 out_string(c, "CLIENT_ERROR bad command line format");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1603 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1604 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1605
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1606 settings.oldest_live = realtime(exptime) - 1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1607 item_flush_expired();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1608 out_string(c, "OK");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1609 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1610
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1611 } else if (ntokens == 2 && (strcmp(tokens[COMMAND_TOKEN].value, "version") == 0)) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1612
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1613 out_string(c, "VERSION " VERSION);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1614
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1615 } else if (ntokens == 2 && (strcmp(tokens[COMMAND_TOKEN].value, "quit") == 0)) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1616
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1617 conn_set_state(c, conn_closing);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1618
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1619 } else if (ntokens == 5 && (strcmp(tokens[COMMAND_TOKEN].value, "slabs") == 0 &&
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1620 strcmp(tokens[COMMAND_TOKEN + 1].value, "reassign") == 0)) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1621 #ifdef ALLOW_SLABS_REASSIGN
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1622
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1623 int src, dst, rv;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1624
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1625 src = strtol(tokens[2].value, NULL, 10);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1626 dst = strtol(tokens[3].value, NULL, 10);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1627
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1628 if(errno == ERANGE) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1629 out_string(c, "CLIENT_ERROR bad command line format");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1630 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1631 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1632
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1633 rv = slabs_reassign(src, dst);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1634 if (rv == 1) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1635 out_string(c, "DONE");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1636 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1637 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1638 if (rv == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1639 out_string(c, "CANT");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1640 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1641 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1642 if (rv == -1) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1643 out_string(c, "BUSY");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1644 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1645 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1646 #else
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1647 out_string(c, "CLIENT_ERROR Slab reassignment not supported");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1648 #endif
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1649 } else if (ntokens == 3 && (strcmp(tokens[COMMAND_TOKEN].value, "verbosity") == 0)) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1650 process_verbosity_command(c, tokens, ntokens);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1651 } else {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1652 out_string(c, "ERROR");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1653 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1654 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1655 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1656
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1657 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1658 * if we have a complete line in the buffer, process it.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1659 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1660 static int try_read_command(conn *c) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1661 char *el, *cont;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1662
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1663 assert(c != NULL);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1664 assert(c->rcurr <= (c->rbuf + c->rsize));
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1665
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1666 if (c->rbytes == 0)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1667 return 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1668 el = memchr(c->rcurr, '\n', c->rbytes);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1669 if (!el)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1670 return 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1671 cont = el + 1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1672 if ((el - c->rcurr) > 1 && *(el - 1) == '\r') {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1673 el--;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1674 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1675 *el = '\0';
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1676
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1677 assert(cont <= (c->rcurr + c->rbytes));
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1678
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1679 process_command(c, c->rcurr);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1680
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1681 c->rbytes -= (cont - c->rcurr);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1682 c->rcurr = cont;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1683
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1684 assert(c->rcurr <= (c->rbuf + c->rsize));
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1685
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1686 return 1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1687 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1688
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1689 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1690 * read a UDP request.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1691 * return 0 if there's nothing to read.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1692 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1693 static int try_read_udp(conn *c) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1694 int res;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1695
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1696 assert(c != NULL);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1697
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1698 c->request_addr_size = sizeof(c->request_addr);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1699 res = recvfrom(c->sfd, c->rbuf, c->rsize,
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1700 0, &c->request_addr, &c->request_addr_size);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1701 if (res > 8) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1702 unsigned char *buf = (unsigned char *)c->rbuf;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1703 STATS_LOCK();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1704 stats.bytes_read += res;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1705 STATS_UNLOCK();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1706
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1707 /* Beginning of UDP packet is the request ID; save it. */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1708 c->request_id = buf[0] * 256 + buf[1];
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1709
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1710 /* If this is a multi-packet request, drop it. */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1711 if (buf[4] != 0 || buf[5] != 1) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1712 out_string(c, "SERVER_ERROR multi-packet request not supported");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1713 return 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1714 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1715
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1716 /* Don't care about any of the rest of the header. */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1717 res -= 8;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1718 memmove(c->rbuf, c->rbuf + 8, res);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1719
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1720 c->rbytes += res;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1721 c->rcurr = c->rbuf;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1722 return 1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1723 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1724 return 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1725 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1726
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1727 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1728 * read from network as much as we can, handle buffer overflow and connection
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1729 * close.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1730 * before reading, move the remaining incomplete fragment of a command
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1731 * (if any) to the beginning of the buffer.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1732 * return 0 if there's nothing to read on the first read.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1733 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1734 static int try_read_network(conn *c) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1735 int gotdata = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1736 int res;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1737
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1738 assert(c != NULL);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1739
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1740 if (c->rcurr != c->rbuf) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1741 if (c->rbytes != 0) /* otherwise there's nothing to copy */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1742 memmove(c->rbuf, c->rcurr, c->rbytes);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1743 c->rcurr = c->rbuf;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1744 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1745
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1746 while (1) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1747 if (c->rbytes >= c->rsize) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1748 char *new_rbuf = realloc(c->rbuf, c->rsize * 2);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1749 if (!new_rbuf) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1750 if (settings.verbose > 0)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1751 fprintf(stderr, "Couldn't realloc input buffer\n");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1752 c->rbytes = 0; /* ignore what we read */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1753 out_string(c, "SERVER_ERROR out of memory");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1754 c->write_and_go = conn_closing;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1755 return 1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1756 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1757 c->rcurr = c->rbuf = new_rbuf;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1758 c->rsize *= 2;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1759 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1760
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1761 /* unix socket mode doesn't need this, so zeroed out. but why
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1762 * is this done for every command? presumably for UDP
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1763 * mode. */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1764 if (!settings.socketpath) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1765 c->request_addr_size = sizeof(c->request_addr);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1766 } else {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1767 c->request_addr_size = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1768 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1769
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1770 res = read(c->sfd, c->rbuf + c->rbytes, c->rsize - c->rbytes);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1771 if (res > 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1772 STATS_LOCK();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1773 stats.bytes_read += res;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1774 STATS_UNLOCK();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1775 gotdata = 1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1776 c->rbytes += res;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1777 continue;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1778 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1779 if (res == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1780 /* connection closed */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1781 conn_set_state(c, conn_closing);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1782 return 1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1783 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1784 if (res == -1) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1785 if (errno == EAGAIN || errno == EWOULDBLOCK) break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1786 else return 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1787 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1788 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1789 return gotdata;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1790 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1791
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1792 static bool update_event(conn *c, const int new_flags) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1793 assert(c != NULL);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1794
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1795 struct event_base *base = c->event.ev_base;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1796 if (c->ev_flags == new_flags)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1797 return true;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1798 if (event_del(&c->event) == -1) return false;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1799 event_set(&c->event, c->sfd, new_flags, event_handler, (void *)c);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1800 event_base_set(base, &c->event);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1801 c->ev_flags = new_flags;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1802 if (event_add(&c->event, 0) == -1) return false;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1803 return true;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1804 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1805
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1806 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1807 * Sets whether we are listening for new connections or not.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1808 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1809 void accept_new_conns(const bool do_accept) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1810 if (! is_listen_thread())
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1811 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1812 if (do_accept) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1813 update_event(listen_conn, EV_READ | EV_PERSIST);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1814 if (listen(listen_conn->sfd, 1024) != 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1815 perror("listen");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1816 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1817 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1818 else {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1819 update_event(listen_conn, 0);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1820 if (listen(listen_conn->sfd, 0) != 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1821 perror("listen");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1822 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1823 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1824 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1825
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1826
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1827 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1828 * Transmit the next chunk of data from our list of msgbuf structures.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1829 *
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1830 * Returns:
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1831 * TRANSMIT_COMPLETE All done writing.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1832 * TRANSMIT_INCOMPLETE More data remaining to write.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1833 * TRANSMIT_SOFT_ERROR Can't write any more right now.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1834 * TRANSMIT_HARD_ERROR Can't write (c->state is set to conn_closing)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1835 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1836 static int transmit(conn *c) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1837 assert(c != NULL);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1838
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1839 if (c->msgcurr < c->msgused &&
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1840 c->msglist[c->msgcurr].msg_iovlen == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1841 /* Finished writing the current msg; advance to the next. */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1842 c->msgcurr++;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1843 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1844 if (c->msgcurr < c->msgused) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1845 ssize_t res;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1846 struct msghdr *m = &c->msglist[c->msgcurr];
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1847
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1848 res = sendmsg(c->sfd, m, 0);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1849 if (res > 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1850 STATS_LOCK();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1851 stats.bytes_written += res;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1852 STATS_UNLOCK();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1853
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1854 /* We've written some of the data. Remove the completed
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1855 iovec entries from the list of pending writes. */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1856 while (m->msg_iovlen > 0 && res >= m->msg_iov->iov_len) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1857 res -= m->msg_iov->iov_len;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1858 m->msg_iovlen--;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1859 m->msg_iov++;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1860 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1861
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1862 /* Might have written just part of the last iovec entry;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1863 adjust it so the next write will do the rest. */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1864 if (res > 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1865 m->msg_iov->iov_base += res;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1866 m->msg_iov->iov_len -= res;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1867 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1868 return TRANSMIT_INCOMPLETE;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1869 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1870 if (res == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1871 if (!update_event(c, EV_WRITE | EV_PERSIST)) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1872 if (settings.verbose > 0)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1873 fprintf(stderr, "Couldn't update event\n");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1874 conn_set_state(c, conn_closing);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1875 return TRANSMIT_HARD_ERROR;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1876 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1877 return TRANSMIT_SOFT_ERROR;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1878 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1879 /* if res==0 or res==-1 and error is not EAGAIN or EWOULDBLOCK,
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1880 we have a real error, on which we close the connection */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1881 if (settings.verbose > 0)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1882 perror("Failed to write, and not due to blocking");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1883
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1884 if (c->udp)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1885 conn_set_state(c, conn_read);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1886 else
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1887 conn_set_state(c, conn_closing);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1888 return TRANSMIT_HARD_ERROR;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1889 } else {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1890 return TRANSMIT_COMPLETE;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1891 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1892 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1893
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1894 static void drive_machine(conn *c) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1895 bool stop = false;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1896 int sfd, flags = 1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1897 socklen_t addrlen;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1898 struct sockaddr addr;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1899 int res;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1900
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1901 assert(c != NULL);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1902
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1903 while (!stop) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1904
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1905 switch(c->state) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1906 case conn_listening:
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1907 addrlen = sizeof(addr);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1908 if ((sfd = accept(c->sfd, &addr, &addrlen)) == -1) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1909 if (errno == EAGAIN || errno == EWOULDBLOCK) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1910 /* these are transient, so don't log anything */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1911 stop = true;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1912 } else if (errno == EMFILE) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1913 if (settings.verbose > 0)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1914 fprintf(stderr, "Too many open connections\n");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1915 accept_new_conns(false);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1916 stop = true;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1917 } else {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1918 perror("accept()");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1919 stop = true;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1920 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1921 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1922 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1923 if ((flags = fcntl(sfd, F_GETFL, 0)) < 0 ||
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1924 fcntl(sfd, F_SETFL, flags | O_NONBLOCK) < 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1925 perror("setting O_NONBLOCK");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1926 close(sfd);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1927 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1928 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1929 dispatch_conn_new(sfd, conn_read, EV_READ | EV_PERSIST,
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1930 DATA_BUFFER_SIZE, false);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1931 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1932
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1933 case conn_read:
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1934 if (try_read_command(c) != 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1935 continue;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1936 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1937 if ((c->udp ? try_read_udp(c) : try_read_network(c)) != 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1938 continue;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1939 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1940 /* we have no command line and no data to read from network */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1941 if (!update_event(c, EV_READ | EV_PERSIST)) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1942 if (settings.verbose > 0)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1943 fprintf(stderr, "Couldn't update event\n");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1944 conn_set_state(c, conn_closing);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1945 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1946 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1947 stop = true;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1948 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1949
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1950 case conn_nread:
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1951 /* we are reading rlbytes into ritem; */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1952 if (c->rlbytes == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1953 complete_nread(c);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1954 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1955 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1956 /* first check if we have leftovers in the conn_read buffer */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1957 if (c->rbytes > 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1958 int tocopy = c->rbytes > c->rlbytes ? c->rlbytes : c->rbytes;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1959 memcpy(c->ritem, c->rcurr, tocopy);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1960 c->ritem += tocopy;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1961 c->rlbytes -= tocopy;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1962 c->rcurr += tocopy;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1963 c->rbytes -= tocopy;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1964 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1965 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1966
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1967 /* now try reading from the socket */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1968 res = read(c->sfd, c->ritem, c->rlbytes);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1969 if (res > 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1970 STATS_LOCK();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1971 stats.bytes_read += res;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1972 STATS_UNLOCK();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1973 c->ritem += res;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1974 c->rlbytes -= res;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1975 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1976 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1977 if (res == 0) { /* end of stream */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1978 conn_set_state(c, conn_closing);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1979 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1980 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1981 if (res == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1982 if (!update_event(c, EV_READ | EV_PERSIST)) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1983 if (settings.verbose > 0)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1984 fprintf(stderr, "Couldn't update event\n");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1985 conn_set_state(c, conn_closing);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1986 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1987 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1988 stop = true;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1989 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1990 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1991 /* otherwise we have a real error, on which we close the connection */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1992 if (settings.verbose > 0)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1993 fprintf(stderr, "Failed to read, and not due to blocking\n");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1994 conn_set_state(c, conn_closing);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1995 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1996
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1997 case conn_swallow:
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1998 /* we are reading sbytes and throwing them away */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1999 if (c->sbytes == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2000 conn_set_state(c, conn_read);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2001 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2002 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2003
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2004 /* first check if we have leftovers in the conn_read buffer */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2005 if (c->rbytes > 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2006 int tocopy = c->rbytes > c->sbytes ? c->sbytes : c->rbytes;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2007 c->sbytes -= tocopy;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2008 c->rcurr += tocopy;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2009 c->rbytes -= tocopy;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2010 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2011 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2012
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2013 /* now try reading from the socket */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2014 res = read(c->sfd, c->rbuf, c->rsize > c->sbytes ? c->sbytes : c->rsize);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2015 if (res > 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2016 STATS_LOCK();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2017 stats.bytes_read += res;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2018 STATS_UNLOCK();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2019 c->sbytes -= res;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2020 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2021 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2022 if (res == 0) { /* end of stream */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2023 conn_set_state(c, conn_closing);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2024 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2025 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2026 if (res == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2027 if (!update_event(c, EV_READ | EV_PERSIST)) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2028 if (settings.verbose > 0)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2029 fprintf(stderr, "Couldn't update event\n");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2030 conn_set_state(c, conn_closing);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2031 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2032 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2033 stop = true;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2034 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2035 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2036 /* otherwise we have a real error, on which we close the connection */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2037 if (settings.verbose > 0)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2038 fprintf(stderr, "Failed to read, and not due to blocking\n");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2039 conn_set_state(c, conn_closing);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2040 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2041
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2042 case conn_write:
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2043 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2044 * We want to write out a simple response. If we haven't already,
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2045 * assemble it into a msgbuf list (this will be a single-entry
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2046 * list for TCP or a two-entry list for UDP).
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2047 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2048 if (c->iovused == 0 || (c->udp && c->iovused == 1)) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2049 if (add_iov(c, c->wcurr, c->wbytes) != 0 ||
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2050 (c->udp && build_udp_headers(c) != 0)) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2051 if (settings.verbose > 0)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2052 fprintf(stderr, "Couldn't build response\n");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2053 conn_set_state(c, conn_closing);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2054 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2055 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2056 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2057
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2058 /* fall through... */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2059
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2060 case conn_mwrite:
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2061 switch (transmit(c)) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2062 case TRANSMIT_COMPLETE:
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2063 if (c->state == conn_mwrite) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2064 while (c->ileft > 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2065 item *it = *(c->icurr);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2066 assert((it->it_flags & ITEM_SLABBED) == 0);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2067 item_remove(it);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2068 c->icurr++;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2069 c->ileft--;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2070 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2071 conn_set_state(c, conn_read);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2072 } else if (c->state == conn_write) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2073 if (c->write_and_free) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2074 free(c->write_and_free);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2075 c->write_and_free = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2076 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2077 conn_set_state(c, c->write_and_go);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2078 } else {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2079 if (settings.verbose > 0)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2080 fprintf(stderr, "Unexpected state %d\n", c->state);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2081 conn_set_state(c, conn_closing);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2082 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2083 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2084
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2085 case TRANSMIT_INCOMPLETE:
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2086 case TRANSMIT_HARD_ERROR:
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2087 break; /* Continue in state machine. */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2088
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2089 case TRANSMIT_SOFT_ERROR:
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2090 stop = true;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2091 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2092 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2093 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2094
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2095 case conn_closing:
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2096 if (c->udp)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2097 conn_cleanup(c);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2098 else
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2099 conn_close(c);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2100 stop = true;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2101 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2102 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2103 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2104
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2105 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2106 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2107
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2108 void event_handler(const int fd, const short which, void *arg) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2109 conn *c;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2110
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2111 c = (conn *)arg;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2112 assert(c != NULL);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2113
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2114 c->which = which;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2115
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2116 /* sanity */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2117 if (fd != c->sfd) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2118 if (settings.verbose > 0)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2119 fprintf(stderr, "Catastrophic: event fd doesn't match conn fd!\n");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2120 conn_close(c);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2121 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2122 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2123
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2124 drive_machine(c);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2125
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2126 /* wait for next event */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2127 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2128 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2129
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2130 static int new_socket(const bool is_udp) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2131 int sfd;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2132 int flags;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2133
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2134 if ((sfd = socket(AF_INET, is_udp ? SOCK_DGRAM : SOCK_STREAM, 0)) == -1) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2135 perror("socket()");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2136 return -1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2137 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2138
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2139 if ((flags = fcntl(sfd, F_GETFL, 0)) < 0 ||
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2140 fcntl(sfd, F_SETFL, flags | O_NONBLOCK) < 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2141 perror("setting O_NONBLOCK");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2142 close(sfd);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2143 return -1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2144 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2145 return sfd;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2146 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2147
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2148
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2149 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2150 * Sets a socket's send buffer size to the maximum allowed by the system.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2151 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2152 static void maximize_sndbuf(const int sfd) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2153 socklen_t intsize = sizeof(int);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2154 int last_good = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2155 int min, max, avg;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2156 int old_size;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2157
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2158 /* Start with the default size. */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2159 if (getsockopt(sfd, SOL_SOCKET, SO_SNDBUF, &old_size, &intsize) != 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2160 if (settings.verbose > 0)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2161 perror("getsockopt(SO_SNDBUF)");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2162 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2163 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2164
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2165 /* Binary-search for the real maximum. */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2166 min = old_size;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2167 max = MAX_SENDBUF_SIZE;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2168
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2169 while (min <= max) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2170 avg = ((unsigned int)(min + max)) / 2;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2171 if (setsockopt(sfd, SOL_SOCKET, SO_SNDBUF, (void *)&avg, intsize) == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2172 last_good = avg;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2173 min = avg + 1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2174 } else {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2175 max = avg - 1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2176 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2177 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2178
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2179 if (settings.verbose > 1)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2180 fprintf(stderr, "<%d send buffer was %d, now %d\n", sfd, old_size, last_good);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2181 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2182
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2183
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2184 static int server_socket(const int port, const bool is_udp) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2185 int sfd;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2186 struct linger ling = {0, 0};
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2187 struct sockaddr_in addr;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2188 int flags =1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2189
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2190 if ((sfd = new_socket(is_udp)) == -1) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2191 return -1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2192 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2193
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2194 setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags));
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2195 if (is_udp) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2196 maximize_sndbuf(sfd);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2197 } else {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2198 setsockopt(sfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags));
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2199 setsockopt(sfd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling));
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2200 setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags));
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2201 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2202
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2203 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2204 * the memset call clears nonstandard fields in some impementations
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2205 * that otherwise mess things up.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2206 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2207 memset(&addr, 0, sizeof(addr));
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2208
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2209 addr.sin_family = AF_INET;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2210 addr.sin_port = htons(port);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2211 addr.sin_addr = settings.interf;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2212 if (bind(sfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2213 perror("bind()");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2214 close(sfd);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2215 return -1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2216 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2217 if (!is_udp && listen(sfd, 1024) == -1) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2218 perror("listen()");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2219 close(sfd);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2220 return -1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2221 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2222 return sfd;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2223 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2224
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2225 static int new_socket_unix(void) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2226 int sfd;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2227 int flags;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2228
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2229 if ((sfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2230 perror("socket()");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2231 return -1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2232 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2233
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2234 if ((flags = fcntl(sfd, F_GETFL, 0)) < 0 ||
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2235 fcntl(sfd, F_SETFL, flags | O_NONBLOCK) < 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2236 perror("setting O_NONBLOCK");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2237 close(sfd);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2238 return -1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2239 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2240 return sfd;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2241 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2242
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2243 static int server_socket_unix(const char *path) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2244 int sfd;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2245 struct linger ling = {0, 0};
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2246 struct sockaddr_un addr;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2247 struct stat tstat;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2248 int flags =1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2249
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2250 if (!path) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2251 return -1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2252 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2253
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2254 if ((sfd = new_socket_unix()) == -1) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2255 return -1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2256 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2257
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2258 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2259 * Clean up a previous socket file if we left it around
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2260 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2261 if (lstat(path, &tstat) == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2262 if (S_ISSOCK(tstat.st_mode))
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2263 unlink(path);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2264 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2265
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2266 setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags));
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2267 setsockopt(sfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags));
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2268 setsockopt(sfd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling));
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2269
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2270 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2271 * the memset call clears nonstandard fields in some impementations
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2272 * that otherwise mess things up.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2273 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2274 memset(&addr, 0, sizeof(addr));
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2275
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2276 addr.sun_family = AF_UNIX;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2277 strcpy(addr.sun_path, path);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2278 if (bind(sfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2279 perror("bind()");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2280 close(sfd);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2281 return -1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2282 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2283 if (listen(sfd, 1024) == -1) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2284 perror("listen()");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2285 close(sfd);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2286 return -1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2287 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2288 return sfd;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2289 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2290
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2291 /* listening socket */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2292 static int l_socket = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2293
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2294 /* udp socket */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2295 static int u_socket = -1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2296
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2297 /* invoke right before gdb is called, on assert */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2298 void pre_gdb(void) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2299 int i;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2300 if (l_socket > -1) close(l_socket);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2301 if (u_socket > -1) close(u_socket);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2302 for (i = 3; i <= 500; i++) close(i); /* so lame */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2303 kill(getpid(), SIGABRT);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2304 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2305
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2306 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2307 * We keep the current time of day in a global variable that's updated by a
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2308 * timer event. This saves us a bunch of time() system calls (we really only
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2309 * need to get the time once a second, whereas there can be tens of thousands
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2310 * of requests a second) and allows us to use server-start-relative timestamps
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2311 * rather than absolute UNIX timestamps, a space savings on systems where
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2312 * sizeof(time_t) > sizeof(unsigned int).
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2313 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2314 volatile rel_time_t current_time;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2315 static struct event clockevent;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2316
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2317 /* time-sensitive callers can call it by hand with this, outside the normal ever-1-second timer */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2318 static void set_current_time(void) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2319 current_time = (rel_time_t) (time(0) - stats.started);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2320 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2321
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2322 static void clock_handler(const int fd, const short which, void *arg) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2323 struct timeval t = {.tv_sec = 1, .tv_usec = 0};
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2324 static bool initialized = false;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2325
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2326 if (initialized) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2327 /* only delete the event if it's actually there. */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2328 evtimer_del(&clockevent);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2329 } else {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2330 initialized = true;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2331 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2332
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2333 evtimer_set(&clockevent, clock_handler, 0);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2334 event_base_set(main_base, &clockevent);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2335 evtimer_add(&clockevent, &t);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2336
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2337 set_current_time();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2338 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2339
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2340 static struct event deleteevent;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2341
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2342 static void delete_handler(const int fd, const short which, void *arg) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2343 struct timeval t = {.tv_sec = 5, .tv_usec = 0};
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2344 static bool initialized = false;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2345
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2346 if (initialized) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2347 /* some versions of libevent don't like deleting events that don't exist,
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2348 so only delete once we know this event has been added. */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2349 evtimer_del(&deleteevent);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2350 } else {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2351 initialized = true;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2352 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2353
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2354 evtimer_set(&deleteevent, delete_handler, 0);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2355 event_base_set(main_base, &deleteevent);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2356 evtimer_add(&deleteevent, &t);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2357 run_deferred_deletes();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2358 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2359
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2360 /* Call run_deferred_deletes instead of this. */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2361 void do_run_deferred_deletes(void)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2362 {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2363 int i, j = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2364
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2365 for (i = 0; i < delcurr; i++) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2366 item *it = todelete[i];
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2367 if (item_delete_lock_over(it)) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2368 assert(it->refcount > 0);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2369 it->it_flags &= ~ITEM_DELETED;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2370 do_item_unlink(it);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2371 do_item_remove(it);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2372 } else {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2373 todelete[j++] = it;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2374 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2375 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2376 delcurr = j;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2377 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2378
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2379 static void usage(void) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2380 printf(PACKAGE " " VERSION "\n");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2381 printf("-p <num> TCP port number to listen on (default: 11211)\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2382 "-U <num> UDP port number to listen on (default: 0, off)\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2383 "-s <file> unix socket path to listen on (disables network support)\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2384 "-l <ip_addr> interface to listen on, default is INDRR_ANY\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2385 "-d run as a daemon\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2386 "-r maximize core file limit\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2387 "-u <username> assume identity of <username> (only when run as root)\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2388 "-m <num> max memory to use for items in megabytes, default is 64 MB\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2389 "-M return error on memory exhausted (rather than removing items)\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2390 "-c <num> max simultaneous connections, default is 1024\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2391 "-k lock down all paged memory\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2392 "-v verbose (print errors/warnings while in event loop)\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2393 "-vv very verbose (also print client commands/reponses)\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2394 "-h print this help and exit\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2395 "-i print memcached and libevent license\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2396 "-b run a managed instanced (mnemonic: buckets)\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2397 "-P <file> save PID in <file>, only used with -d option\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2398 "-f <factor> chunk size growth factor, default 1.25\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2399 "-n <bytes> minimum space allocated for key+value+flags, default 48\n");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2400 #ifdef USE_THREADS
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2401 printf("-t <num> number of threads to use, default 4\n");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2402 #endif
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2403 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2404 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2405
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2406 static void usage_license(void) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2407 printf(PACKAGE " " VERSION "\n\n");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2408 printf(
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2409 "Copyright (c) 2003, Danga Interactive, Inc. <http://www.danga.com/>\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2410 "All rights reserved.\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2411 "\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2412 "Redistribution and use in source and binary forms, with or without\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2413 "modification, are permitted provided that the following conditions are\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2414 "met:\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2415 "\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2416 " * Redistributions of source code must retain the above copyright\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2417 "notice, this list of conditions and the following disclaimer.\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2418 "\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2419 " * Redistributions in binary form must reproduce the above\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2420 "copyright notice, this list of conditions and the following disclaimer\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2421 "in the documentation and/or other materials provided with the\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2422 "distribution.\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2423 "\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2424 " * Neither the name of the Danga Interactive nor the names of its\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2425 "contributors may be used to endorse or promote products derived from\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2426 "this software without specific prior written permission.\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2427 "\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2428 "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2429 "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2430 "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2431 "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2432 "OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2433 "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2434 "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2435 "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2436 "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2437 "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2438 "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2439 "\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2440 "\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2441 "This product includes software developed by Niels Provos.\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2442 "\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2443 "[ libevent ]\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2444 "\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2445 "Copyright 2000-2003 Niels Provos <provos@citi.umich.edu>\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2446 "All rights reserved.\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2447 "\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2448 "Redistribution and use in source and binary forms, with or without\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2449 "modification, are permitted provided that the following conditions\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2450 "are met:\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2451 "1. Redistributions of source code must retain the above copyright\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2452 " notice, this list of conditions and the following disclaimer.\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2453 "2. Redistributions in binary form must reproduce the above copyright\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2454 " notice, this list of conditions and the following disclaimer in the\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2455 " documentation and/or other materials provided with the distribution.\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2456 "3. All advertising materials mentioning features or use of this software\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2457 " must display the following acknowledgement:\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2458 " This product includes software developed by Niels Provos.\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2459 "4. The name of the author may not be used to endorse or promote products\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2460 " derived from this software without specific prior written permission.\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2461 "\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2462 "THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2463 "IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2464 "OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2465 "IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2466 "INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2467 "NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2468 "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2469 "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2470 "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2471 "THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2472 );
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2473
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2474 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2475 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2476
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2477 static void save_pid(const pid_t pid, const char *pid_file) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2478 FILE *fp;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2479 if (pid_file == NULL)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2480 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2481
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2482 if (!(fp = fopen(pid_file, "w"))) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2483 fprintf(stderr, "Could not open the pid file %s for writing\n", pid_file);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2484 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2485 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2486
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2487 fprintf(fp,"%ld\n", (long)pid);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2488 if (fclose(fp) == -1) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2489 fprintf(stderr, "Could not close the pid file %s.\n", pid_file);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2490 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2491 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2492 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2493
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2494 static void remove_pidfile(const char *pid_file) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2495 if (pid_file == NULL)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2496 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2497
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2498 if (unlink(pid_file) != 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2499 fprintf(stderr, "Could not remove the pid file %s.\n", pid_file);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2500 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2501
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2502 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2503
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2504
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2505 static void sig_handler(const int sig) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2506 printf("SIGINT handled.\n");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2507 exit(EXIT_SUCCESS);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2508 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2509
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2510 int main (int argc, char **argv) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2511 int c;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2512 struct in_addr addr;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2513 bool lock_memory = false;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2514 bool daemonize = false;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2515 int maxcore = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2516 char *username = NULL;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2517 char *pid_file = NULL;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2518 struct passwd *pw;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2519 struct sigaction sa;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2520 struct rlimit rlim;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2521
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2522 /* handle SIGINT */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2523 signal(SIGINT, sig_handler);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2524
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2525 /* init settings */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2526 settings_init();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2527
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2528 /* set stderr non-buffering (for running under, say, daemontools) */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2529 setbuf(stderr, NULL);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2530
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2531 /* process arguments */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2532 while ((c = getopt(argc, argv, "bp:s:U:m:Mc:khirvdl:u:P:f:s:n:t:D:")) != -1) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2533 switch (c) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2534 case 'U':
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2535 settings.udpport = atoi(optarg);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2536 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2537 case 'b':
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2538 settings.managed = true;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2539 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2540 case 'p':
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2541 settings.port = atoi(optarg);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2542 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2543 case 's':
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2544 settings.socketpath = optarg;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2545 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2546 case 'm':
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2547 settings.maxbytes = ((size_t)atoi(optarg)) * 1024 * 1024;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2548 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2549 case 'M':
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2550 settings.evict_to_free = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2551 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2552 case 'c':
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2553 settings.maxconns = atoi(optarg);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2554 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2555 case 'h':
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2556 usage();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2557 exit(EXIT_SUCCESS);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2558 case 'i':
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2559 usage_license();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2560 exit(EXIT_SUCCESS);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2561 case 'k':
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2562 lock_memory = true;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2563 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2564 case 'v':
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2565 settings.verbose++;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2566 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2567 case 'l':
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2568 if (inet_pton(AF_INET, optarg, &addr) <= 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2569 fprintf(stderr, "Illegal address: %s\n", optarg);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2570 return 1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2571 } else {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2572 settings.interf = addr;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2573 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2574 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2575 case 'd':
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2576 daemonize = true;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2577 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2578 case 'r':
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2579 maxcore = 1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2580 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2581 case 'u':
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2582 username = optarg;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2583 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2584 case 'P':
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2585 pid_file = optarg;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2586 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2587 case 'f':
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2588 settings.factor = atof(optarg);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2589 if (settings.factor <= 1.0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2590 fprintf(stderr, "Factor must be greater than 1\n");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2591 return 1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2592 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2593 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2594 case 'n':
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2595 settings.chunk_size = atoi(optarg);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2596 if (settings.chunk_size == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2597 fprintf(stderr, "Chunk size must be greater than 0\n");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2598 return 1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2599 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2600 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2601 case 't':
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2602 settings.num_threads = atoi(optarg);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2603 if (settings.num_threads == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2604 fprintf(stderr, "Number of threads must be greater than 0\n");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2605 return 1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2606 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2607 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2608 case 'D':
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2609 if (! optarg || ! optarg[0]) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2610 fprintf(stderr, "No delimiter specified\n");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2611 return 1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2612 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2613 settings.prefix_delimiter = optarg[0];
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2614 settings.detail_enabled = 1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2615 break;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2616 default:
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2617 fprintf(stderr, "Illegal argument \"%c\"\n", c);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2618 return 1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2619 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2620 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2621
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2622 if (maxcore != 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2623 struct rlimit rlim_new;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2624 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2625 * First try raising to infinity; if that fails, try bringing
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2626 * the soft limit to the hard.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2627 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2628 if (getrlimit(RLIMIT_CORE, &rlim) == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2629 rlim_new.rlim_cur = rlim_new.rlim_max = RLIM_INFINITY;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2630 if (setrlimit(RLIMIT_CORE, &rlim_new)!= 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2631 /* failed. try raising just to the old max */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2632 rlim_new.rlim_cur = rlim_new.rlim_max = rlim.rlim_max;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2633 (void)setrlimit(RLIMIT_CORE, &rlim_new);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2634 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2635 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2636 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2637 * getrlimit again to see what we ended up with. Only fail if
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2638 * the soft limit ends up 0, because then no core files will be
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2639 * created at all.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2640 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2641
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2642 if ((getrlimit(RLIMIT_CORE, &rlim) != 0) || rlim.rlim_cur == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2643 fprintf(stderr, "failed to ensure corefile creation\n");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2644 exit(EXIT_FAILURE);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2645 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2646 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2647
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2648 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2649 * If needed, increase rlimits to allow as many connections
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2650 * as needed.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2651 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2652
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2653 if (getrlimit(RLIMIT_NOFILE, &rlim) != 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2654 fprintf(stderr, "failed to getrlimit number of files\n");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2655 exit(EXIT_FAILURE);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2656 } else {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2657 int maxfiles = settings.maxconns;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2658 if (rlim.rlim_cur < maxfiles)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2659 rlim.rlim_cur = maxfiles + 3;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2660 if (rlim.rlim_max < rlim.rlim_cur)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2661 rlim.rlim_max = rlim.rlim_cur;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2662 if (setrlimit(RLIMIT_NOFILE, &rlim) != 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2663 fprintf(stderr, "failed to set rlimit for open files. Try running as root or requesting smaller maxconns value.\n");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2664 exit(EXIT_FAILURE);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2665 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2666 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2667
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2668 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2669 * initialization order: first create the listening sockets
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2670 * (may need root on low ports), then drop root if needed,
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2671 * then daemonise if needed, then init libevent (in some cases
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2672 * descriptors created by libevent wouldn't survive forking).
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2673 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2674
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2675 /* create the listening socket and bind it */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2676 if (settings.socketpath == NULL) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2677 l_socket = server_socket(settings.port, 0);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2678 if (l_socket == -1) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2679 fprintf(stderr, "failed to listen\n");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2680 exit(EXIT_FAILURE);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2681 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2682 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2683
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2684 if (settings.udpport > 0 && settings.socketpath == NULL) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2685 /* create the UDP listening socket and bind it */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2686 u_socket = server_socket(settings.udpport, 1);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2687 if (u_socket == -1) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2688 fprintf(stderr, "failed to listen on UDP port %d\n", settings.udpport);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2689 exit(EXIT_FAILURE);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2690 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2691 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2692
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2693 /* lose root privileges if we have them */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2694 if (getuid() == 0 || geteuid() == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2695 if (username == 0 || *username == '\0') {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2696 fprintf(stderr, "can't run as root without the -u switch\n");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2697 return 1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2698 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2699 if ((pw = getpwnam(username)) == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2700 fprintf(stderr, "can't find the user %s to switch to\n", username);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2701 return 1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2702 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2703 if (setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2704 fprintf(stderr, "failed to assume identity of user %s\n", username);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2705 return 1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2706 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2707 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2708
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2709 /* create unix mode sockets after dropping privileges */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2710 if (settings.socketpath != NULL) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2711 l_socket = server_socket_unix(settings.socketpath);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2712 if (l_socket == -1) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2713 fprintf(stderr, "failed to listen\n");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2714 exit(EXIT_FAILURE);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2715 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2716 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2717
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2718 /* daemonize if requested */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2719 /* if we want to ensure our ability to dump core, don't chdir to / */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2720 if (daemonize) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2721 int res;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2722 res = daemon(maxcore, settings.verbose);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2723 if (res == -1) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2724 fprintf(stderr, "failed to daemon() in order to daemonize\n");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2725 return 1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2726 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2727 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2728
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2729 /* initialize main thread libevent instance */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2730 main_base = event_init();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2731
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2732 /* initialize other stuff */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2733 item_init();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2734 stats_init();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2735 assoc_init();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2736 conn_init();
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2737 slabs_init(settings.maxbytes, settings.factor);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2738
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2739 /* managed instance? alloc and zero a bucket array */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2740 if (settings.managed) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2741 buckets = malloc(sizeof(int) * MAX_BUCKETS);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2742 if (buckets == 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2743 fprintf(stderr, "failed to allocate the bucket array");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2744 exit(EXIT_FAILURE);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2745 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2746 memset(buckets, 0, sizeof(int) * MAX_BUCKETS);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2747 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2748
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2749 /* lock paged memory if needed */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2750 if (lock_memory) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2751 #ifdef HAVE_MLOCKALL
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2752 mlockall(MCL_CURRENT | MCL_FUTURE);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2753 #else
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2754 fprintf(stderr, "warning: mlockall() not supported on this platform. proceeding without.\n");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2755 #endif
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2756 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2757
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2758 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2759 * ignore SIGPIPE signals; we can use errno==EPIPE if we
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2760 * need that information
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2761 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2762 sa.sa_handler = SIG_IGN;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2763 sa.sa_flags = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2764 if (sigemptyset(&sa.sa_mask) == -1 ||
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2765 sigaction(SIGPIPE, &sa, 0) == -1) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2766 perror("failed to ignore SIGPIPE; sigaction");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2767 exit(EXIT_FAILURE);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2768 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2769 /* create the initial listening connection */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2770 if (!(listen_conn = conn_new(l_socket, conn_listening,
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2771 EV_READ | EV_PERSIST, 1, false, main_base))) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2772 fprintf(stderr, "failed to create listening connection");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2773 exit(EXIT_FAILURE);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2774 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2775 /* save the PID in if we're a daemon */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2776 if (daemonize)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2777 save_pid(getpid(), pid_file);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2778 /* start up worker threads if MT mode */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2779 thread_init(settings.num_threads, main_base);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2780 /* initialise clock event */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2781 clock_handler(0, 0, 0);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2782 /* initialise deletion array and timer event */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2783 deltotal = 200;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2784 delcurr = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2785 todelete = malloc(sizeof(item *) * deltotal);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2786 delete_handler(0, 0, 0); /* sets up the event */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2787 /* create the initial listening udp connection, monitored on all threads */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2788 if (u_socket > -1) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2789 for (c = 0; c < settings.num_threads; c++) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2790 /* this is guaranteed to hit all threads because we round-robin */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2791 dispatch_conn_new(u_socket, conn_read, EV_READ | EV_PERSIST,
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2792 UDP_READ_BUFFER_SIZE, 1);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2793 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2794 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2795 /* enter the event loop */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2796 event_base_loop(main_base, 0);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2797 /* remove the PID file if we're a daemon */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2798 if (daemonize)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2799 remove_pidfile(pid_file);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2800 return 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2801 }