Skip to content

Commit c9607c6

Browse files
committed
merge end of facebook branch into trunk, after copying the old trunk to the memcached-1.1.x branch
git-svn-id: http://code.sixapart.com/svn/memcached/trunk/server@320 b0b603af-a30f-0410-a34e-baf09ae79d0b
1 parent 246a28c commit c9607c6

9 files changed

+1078
-356
lines changed

ChangeLog

+15
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
2006-08-21
2+
* Nathan Neulinger <[email protected]>: fix incompatabilities with
3+
unix domain socket support and the UDP code and clean up stale
4+
sockets
5+
6+
2006-08-20
7+
* Nathan Neulinger <[email protected]>: unix domain socket support
8+
9+
2006-05-03
10+
* Steven Grimm <[email protected]>: big bunch of changes:
11+
big CPU reduction work, UDP-based interface, increased memory
12+
efficiency. (intertwined patch, committed all together)
13+
<http://lists.danga.com/pipermail/memcached/2006-May/002164.html>
14+
or see svn commit logs
15+
116
2006-04-30
217
* River Tarnell: autoconf work for Solaris 10. Brad:
318
merge and verify it works on Nexenta.

TODO

+17
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
* bug as shown with netcat (w/ small 16 byte object reproduces)
2+
3+
>>I've done the following script to check that memcached has a key in it's
4+
>>inside, and thus know that it's working correctly:
5+
>>echo -e "get is_ok\r\nquit\r\n" | netcat $host $ip
6+
>>
7+
>>and I find that sometimes it returns the VALUE in it's inside, but other
8+
>>not.
9+
10+
* namespaces
11+
12+
* binary get protocol
13+
14+
* refresh/touch command.
15+
16+
* finer granularity of time for flush_all/delete, or generation number.
17+
118
* slab class reassignment still buggy and can crash. once that's
219
stable, server should re-assign pages every 60 seconds or so
320
to keep all classes roughly equal. [Update: fixed now?, but

configure.ac

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
AC_PREREQ(2.52)
2-
AC_INIT(memcached, 1.1.13-pre2, [email protected])
2+
AC_INIT(memcached, 1.2.0-rc1, [email protected])
33
AC_CANONICAL_SYSTEM
44
AC_CONFIG_SRCDIR(memcached.c)
55
AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)

doc/memcached.1

+18-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,10 @@ caches, so consult the README and memcached homepage for configuration
4343
suggestions.
4444
.TP
4545
.B \-p <num>
46-
Listen on port <num>, the default is port 11211.
46+
Listen on TCP port <num>, the default is port 11211.
47+
.TP
48+
.B \-U <num>
49+
Listen on UDP port <num>, the default is port 11211.
4750
.TP
4851
.B \-M
4952
Disable automatic removal of items from the cache when out of memory.
@@ -52,6 +55,20 @@ Additions will not be possible until adequate space is freed up.
5255
.B \-r
5356
Raise the core file size limit to the maximum allowable.
5457
.TP
58+
.B \-f <factor>
59+
Use <factor> as the multiplier for computing the sizes of memory chunks that
60+
items are stored in. A lower value may result in less wasted memory depending
61+
on the total amount of memory available and the distribution of item sizes.
62+
The default is 1.25.
63+
.TP
64+
.B \-s <size>
65+
Allocate a minimum of <size> bytes for the item key, value, and flags. The
66+
default is 48. If you have a lot of small keys and values, you can get a
67+
significant memory efficiency gain with a lower value. If you use a high
68+
chunk growth factor (-f option), on the other hand, you may want to increase
69+
the size to allow a bigger percentage of your items to fit in the most densely
70+
packed (smallest) chunks.
71+
.TP
5572
.B \-h
5673
Show the version of memcached and a summary of options.
5774
.TP

doc/protocol.txt

+45-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
Protocol
22
--------
33

4-
Clients of memcached communicate with server through TCP
5-
connections. A given running memcached server listens on some
4+
Clients of memcached communicate with server through TCP connections.
5+
(A UDP interface is also available; details are below under "UDP
6+
protocol.") A given running memcached server listens on some
67
(configurable) port; clients connect to that port, send commands to
78
the server, read responses, and eventually close the connection.
89

@@ -388,3 +389,45 @@ quit\r\n
388389
Upon receiving this command, the server closes the
389390
connection. However, the client may also simply close the connection
390391
when it no longer needs it, without issuing this command.
392+
393+
394+
UDP protocol
395+
------------
396+
397+
For very large installations where the number of clients is high enough
398+
that the number of TCP connections causes scaling difficulties, there is
399+
also a UDP-based interface. The UDP interface does not provide guaranteed
400+
delivery, so should only be used for operations that aren't required to
401+
succeed; typically it is used for "get" requests where a missing or
402+
incomplete response can simply be treated as a cache miss.
403+
404+
Each UDP datagram contains a simple frame header, followed by data in the
405+
same format as the TCP protocol described above. In the current
406+
implementation, requests must be contained in a single UDP datagram, but
407+
responses may span several datagrams. (The only common requests that would
408+
span multiple datagrams are huge multi-key "get" requests and "set"
409+
requests, both of which are more suitable to TCP transport for reliability
410+
reasons anyway.)
411+
412+
The frame header is 8 bytes long, as follows (all values are 16-bit integers
413+
in network byte order, high byte first):
414+
415+
0-1 Request ID
416+
2-3 Sequence number
417+
4-5 Total number of datagrams in this message
418+
6-7 Reserved for future use; must be 0
419+
420+
The request ID is supplied by the client. Typically it will be a
421+
monotonically increasing value starting from a random seed, but the client
422+
is free to use whatever request IDs it likes. The server's response will
423+
contain the same ID as the incoming request. The client uses the request ID
424+
to differentiate between responses to outstanding requests if there are
425+
several pending from the same server; any datagrams with an unknown request
426+
ID are probably delayed responses to an earlier request and should be
427+
discarded.
428+
429+
The sequence number ranges from 0 to n-1, where n is the total number of
430+
datagrams in the message. The client should concatenate the payloads of the
431+
datagrams for a given response in sequence number order; the resulting byte
432+
stream will contain a complete response in the same format as the TCP
433+
protocol (including terminating \r\n sequences).

items.c

+43-18
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,7 @@
2121
#include "memcached.h"
2222

2323

24-
/*
25-
* NOTE: we assume here for simplicity that slab ids are <=32. That's true in
26-
* the powers-of-2 implementation, but if that changes this should be changed too
27-
*/
28-
29-
#define LARGEST_ID 32
24+
#define LARGEST_ID 255
3025
static item *heads[LARGEST_ID];
3126
static item *tails[LARGEST_ID];
3227
unsigned int sizes[LARGEST_ID];
@@ -41,14 +36,31 @@ void item_init(void) {
4136
}
4237

4338

44-
item *item_alloc(char *key, int flags, time_t exptime, int nbytes) {
45-
int ntotal, len;
39+
/*
40+
* Generates the variable-sized part of the header for an object.
41+
*
42+
* suffix - Buffer for the "VALUE" line suffix (flags, size).
43+
* nsuffix - The length of the suffix is stored here.
44+
* keylen - The length of the key plus any padding required to word-align the
45+
* "VALUE" suffix (which is done to speed up copying.)
46+
*
47+
* Returns the total size of the header.
48+
*/
49+
int item_make_header(char *key, int flags, int nbytes,
50+
char *suffix, int *nsuffix, int *keylen) {
51+
*keylen = strlen(key) + 1; if(*keylen % 4) *keylen += 4 - (*keylen % 4);
52+
*nsuffix = sprintf(suffix, " %u %u\r\n", flags, nbytes - 2);
53+
return sizeof(item) + *keylen + *nsuffix + nbytes;
54+
}
55+
56+
item *item_alloc(char *key, int flags, rel_time_t exptime, int nbytes) {
57+
int nsuffix, ntotal, len;
4658
item *it;
4759
unsigned int id;
60+
char suffix[40];
4861

49-
len = strlen(key) + 1; if(len % 4) len += 4 - (len % 4);
50-
ntotal = sizeof(item) + len + nbytes;
51-
62+
ntotal = item_make_header(key, flags, nbytes, suffix, &nsuffix, &len);
63+
5264
id = slabs_clsid(ntotal);
5365
if (id == 0)
5466
return 0;
@@ -97,7 +109,8 @@ item *item_alloc(char *key, int flags, time_t exptime, int nbytes) {
97109
it->nbytes = nbytes;
98110
strcpy(ITEM_key(it), key);
99111
it->exptime = exptime;
100-
it->flags = flags;
112+
memcpy(ITEM_suffix(it), suffix, nsuffix);
113+
it->nsuffix = nsuffix;
101114
return it;
102115
}
103116

@@ -114,6 +127,18 @@ void item_free(item *it) {
114127
slabs_free(it, ntotal);
115128
}
116129

130+
/*
131+
* Returns true if an item will fit in the cache (its size does not exceed
132+
* the maximum for a cache entry.)
133+
*/
134+
int item_size_ok(char *key, int flags, int nbytes) {
135+
char prefix[40];
136+
int keylen, nsuffix;
137+
138+
return slabs_clsid(item_make_header(key, flags, nbytes,
139+
prefix, &nsuffix, &keylen)) != 0;
140+
}
141+
117142
void item_link_q(item *it) { /* item is the new head */
118143
item **head, **tail;
119144
assert(it->slabs_clsid <= LARGEST_ID);
@@ -159,7 +184,7 @@ int item_link(item *it) {
159184
assert((it->it_flags & (ITEM_LINKED|ITEM_SLABBED)) == 0);
160185
assert(it->nbytes < 1048576);
161186
it->it_flags |= ITEM_LINKED;
162-
it->time = time(0);
187+
it->time = current_time;
163188
assoc_insert(ITEM_key(it), it);
164189

165190
stats.curr_bytes += ITEM_ntotal(it);
@@ -195,7 +220,7 @@ void item_update(item *it) {
195220
assert((it->it_flags & ITEM_SLABBED) == 0);
196221

197222
item_unlink_q(it);
198-
it->time = time(0);
223+
it->time = current_time;
199224
item_link_q(it);
200225
}
201226

@@ -224,7 +249,7 @@ char *item_cachedump(unsigned int slabs_clsid, unsigned int limit, unsigned int
224249
bufcurr = 0;
225250

226251
while (it && (!limit || shown < limit)) {
227-
len = sprintf(temp, "ITEM %s [%u b; %lu s]\r\n", ITEM_key(it), it->nbytes - 2, it->time);
252+
len = sprintf(temp, "ITEM %s [%u b; %lu s]\r\n", ITEM_key(it), it->nbytes - 2, it->time + stats.started);
228253
if (bufcurr + len + 6 > memlimit) /* 6 is END\r\n\0 */
229254
break;
230255
strcpy(buffer + bufcurr, temp);
@@ -243,7 +268,7 @@ char *item_cachedump(unsigned int slabs_clsid, unsigned int limit, unsigned int
243268
void item_stats(char *buffer, int buflen) {
244269
int i;
245270
char *bufcurr = buffer;
246-
time_t now = time(0);
271+
rel_time_t now = current_time;
247272

248273
if (buflen < 4096) {
249274
strcpy(buffer, "SERVER_ERROR out of memory");
@@ -252,7 +277,7 @@ void item_stats(char *buffer, int buflen) {
252277

253278
for (i=0; i<LARGEST_ID; i++) {
254279
if (tails[i])
255-
bufcurr += sprintf(bufcurr, "STAT items:%u:number %u\r\nSTAT items:%u:age %lu\r\n",
280+
bufcurr += sprintf(bufcurr, "STAT items:%u:number %u\r\nSTAT items:%u:age %u\r\n",
256281
i, sizes[i], i, now - tails[i]->time);
257282
}
258283
strcpy(bufcurr, "END");
@@ -262,7 +287,7 @@ void item_stats(char *buffer, int buflen) {
262287
/* dumps out a list of objects of each size, with granularity of 32 bytes */
263288
char* item_stats_sizes(int *bytes) {
264289
int num_buckets = 32768; /* max 1MB object, divided into 32 bytes size buckets */
265-
unsigned int *histogram = (int*) malloc(num_buckets * sizeof(int));
290+
unsigned int *histogram = (unsigned int*) malloc(num_buckets * sizeof(int));
266291
char *buf = (char*) malloc(1024*1024*2*sizeof(char));
267292
int i;
268293

0 commit comments

Comments
 (0)