annotate slabs.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 30782bb1fc04
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 * Slabs memory allocation, based on powers-of-N. Slabs are up to 1MB in size
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
4 * and are divided into chunks. The chunk sizes start off at the size of the
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
5 * "item" structure plus space for a small key and value. They increase by
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
6 * a multiplier factor from there, up to half the maximum slab size. The last
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
7 * slab size is always 1MB, since that's the maximum item size allowed by the
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
8 * memcached protocol.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
9 *
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
10 * $Id: slabs.c 551 2007-05-07 21:24:31Z plindner $
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 #include "memcached.h"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
13 #include <sys/stat.h>
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
14 #include <sys/socket.h>
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
15 #include <sys/signal.h>
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
16 #include <sys/resource.h>
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
17 #include <fcntl.h>
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
18 #include <netinet/in.h>
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
19 #include <errno.h>
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
20 #include <stdlib.h>
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
21 #include <stdio.h>
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
22 #include <string.h>
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
23 #include <assert.h>
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
24
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
25 #define POWER_SMALLEST 1
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
26 #define POWER_LARGEST 200
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
27 #define POWER_BLOCK 1048576
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
28 #define CHUNK_ALIGN_BYTES (sizeof(void *))
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
29 #define DONT_PREALLOC_SLABS
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
30
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
31 /* powers-of-N allocation structures */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
32
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
33 typedef struct {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
34 unsigned int size; /* sizes of items */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
35 unsigned int perslab; /* how many items per slab */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
36
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
37 void **slots; /* list of item ptrs */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
38 unsigned int sl_total; /* size of previous array */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
39 unsigned int sl_curr; /* first free slot */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
40
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
41 void *end_page_ptr; /* pointer to next free item at end of page, or 0 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
42 unsigned int end_page_free; /* number of items remaining at end of last alloced page */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
43
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
44 unsigned int slabs; /* how many slabs were allocated for this class */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
45
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
46 void **slab_list; /* array of slab pointers */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
47 unsigned int list_size; /* size of prev array */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
48
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
49 unsigned int killing; /* index+1 of dying slab, or zero if none */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
50 } slabclass_t;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
51
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
52 static slabclass_t slabclass[POWER_LARGEST + 1];
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
53 static size_t mem_limit = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
54 static size_t mem_malloced = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
55 static int power_largest;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
56
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
57 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
58 * Forward Declarations
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
59 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
60 static int do_slabs_newslab(const unsigned int id);
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 #ifndef DONT_PREALLOC_SLABS
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
63 /* Preallocate as many slab pages as possible (called from slabs_init)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
64 on start-up, so users don't get confused out-of-memory errors when
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
65 they do have free (in-slab) space, but no space to make new slabs.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
66 if maxslabs is 18 (POWER_LARGEST - POWER_SMALLEST + 1), then all
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
67 slab types can be made. if max memory is less than 18 MB, only the
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
68 smaller ones will be made. */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
69 static void slabs_preallocate (const unsigned int maxslabs);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
70 #endif
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 /*
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
73 * Figures out which slab class (chunk size) is required to store an item of
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
74 * a given size.
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 * Given object size, return id to use when allocating/freeing memory for object
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
77 * 0 means error: can't store such a large object
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
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
80 unsigned int slabs_clsid(const size_t size) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
81 int res = POWER_SMALLEST;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
82
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
83 if (size == 0)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
84 return 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
85 while (size > slabclass[res].size)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
86 if (res++ == power_largest) /* won't fit in the biggest slab */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
87 return 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
88 return res;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
89 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
90
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 * Determines the chunk sizes and initializes the slab class descriptors
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
93 * accordingly.
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
94 */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
95 void slabs_init(const size_t limit, const double factor) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
96 int i = POWER_SMALLEST - 1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
97 unsigned int size = sizeof(item) + settings.chunk_size;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
98
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
99 /* Factor of 2.0 means use the default memcached behavior */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
100 if (factor == 2.0 && size < 128)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
101 size = 128;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
102
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
103 mem_limit = limit;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
104 memset(slabclass, 0, sizeof(slabclass));
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
105
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
106 while (++i < POWER_LARGEST && size <= POWER_BLOCK / 2) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
107 /* Make sure items are always n-byte aligned */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
108 if (size % CHUNK_ALIGN_BYTES)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
109 size += CHUNK_ALIGN_BYTES - (size % CHUNK_ALIGN_BYTES);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
110
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
111 slabclass[i].size = size;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
112 slabclass[i].perslab = POWER_BLOCK / slabclass[i].size;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
113 size *= factor;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
114 if (settings.verbose > 1) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
115 fprintf(stderr, "slab class %3d: chunk size %6u perslab %5u\n",
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
116 i, slabclass[i].size, slabclass[i].perslab);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
117 }
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
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
120 power_largest = i;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
121 slabclass[power_largest].size = POWER_BLOCK;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
122 slabclass[power_largest].perslab = 1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
123
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
124 /* for the test suite: faking of how much we've already malloc'd */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
125 {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
126 char *t_initial_malloc = getenv("T_MEMD_INITIAL_MALLOC");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
127 if (t_initial_malloc) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
128 mem_malloced = (size_t)atol(t_initial_malloc);
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
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
131 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
132
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
133 #ifndef DONT_PREALLOC_SLABS
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
134 {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
135 char *pre_alloc = getenv("T_MEMD_SLABS_ALLOC");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
136
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
137 if (pre_alloc == NULL || atoi(pre_alloc) != 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
138 slabs_preallocate(power_largest);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
139 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
140 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
141 #endif
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 #ifndef DONT_PREALLOC_SLABS
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
145 static void slabs_preallocate (const unsigned int maxslabs) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
146 int i;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
147 unsigned int prealloc = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
148
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
149 /* pre-allocate a 1MB slab in every size class so people don't get
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
150 confused by non-intuitive "SERVER_ERROR out of memory"
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
151 messages. this is the most common question on the mailing
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
152 list. if you really don't want this, you can rebuild without
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
153 these three lines. */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
154
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
155 for (i = POWER_SMALLEST; i <= POWER_LARGEST; i++) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
156 if (++prealloc > maxslabs)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
157 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
158 do_slabs_newslab(i);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
159 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
160
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
161 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
162 #endif
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
163
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
164 static int grow_slab_list (const unsigned int id) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
165 slabclass_t *p = &slabclass[id];
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
166 if (p->slabs == p->list_size) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
167 size_t new_size = (p->list_size != 0) ? p->list_size * 2 : 16;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
168 void *new_list = realloc(p->slab_list, new_size * sizeof(void *));
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
169 if (new_list == 0) return 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
170 p->list_size = new_size;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
171 p->slab_list = new_list;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
172 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
173 return 1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
174 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
175
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
176 static int do_slabs_newslab(const unsigned int id) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
177 slabclass_t *p = &slabclass[id];
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
178 #ifdef ALLOW_SLABS_REASSIGN
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
179 int len = POWER_BLOCK;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
180 #else
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
181 int len = p->size * p->perslab;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
182 #endif
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
183 char *ptr;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
184
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
185 if (mem_limit && mem_malloced + len > mem_limit && p->slabs > 0)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
186 return 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 if (grow_slab_list(id) == 0) return 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
189
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
190 ptr = malloc((size_t)len);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
191 if (ptr == 0) return 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
192
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
193 memset(ptr, 0, (size_t)len);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
194 p->end_page_ptr = ptr;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
195 p->end_page_free = p->perslab;
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 p->slab_list[p->slabs++] = ptr;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
198 mem_malloced += len;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
199 return 1;
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
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
202 /*@null@*/
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
203 void *do_slabs_alloc(const size_t size) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
204 slabclass_t *p;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
205
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
206 unsigned int id = slabs_clsid(size);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
207 if (id < POWER_SMALLEST || id > power_largest)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
208 return NULL;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
209
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
210 p = &slabclass[id];
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
211 assert(p->sl_curr == 0 || ((item *)p->slots[p->sl_curr - 1])->slabs_clsid == 0);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
212
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
213 #ifdef USE_SYSTEM_MALLOC
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
214 if (mem_limit && mem_malloced + size > mem_limit)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
215 return 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
216 mem_malloced += size;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
217 return malloc(size);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
218 #endif
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
219
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
220 /* fail unless we have space at the end of a recently allocated page,
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
221 we have something on our freelist, or we could allocate a new page */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
222 if (! (p->end_page_ptr != 0 || p->sl_curr != 0 || do_slabs_newslab(id) != 0))
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
223 return 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
224
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
225 /* return off our freelist, if we have one */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
226 if (p->sl_curr != 0)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
227 return p->slots[--p->sl_curr];
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
228
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
229 /* if we recently allocated a whole page, return from that */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
230 if (p->end_page_ptr) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
231 void *ptr = p->end_page_ptr;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
232 if (--p->end_page_free != 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
233 p->end_page_ptr += p->size;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
234 } else {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
235 p->end_page_ptr = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
236 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
237 return ptr;
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 return NULL; /* shouldn't ever get here */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
241 }
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 void do_slabs_free(void *ptr, const size_t size) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
244 unsigned char id = slabs_clsid(size);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
245 slabclass_t *p;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
246
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
247 assert(((item *)ptr)->slabs_clsid == 0);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
248 assert(id >= POWER_SMALLEST && id <= power_largest);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
249 if (id < POWER_SMALLEST || id > power_largest)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
250 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
251
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
252 p = &slabclass[id];
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
253
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
254 #ifdef USE_SYSTEM_MALLOC
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
255 mem_malloced -= size;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
256 free(ptr);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
257 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
258 #endif
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
259
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
260 if (p->sl_curr == p->sl_total) { /* need more space on the free list */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
261 int new_size = (p->sl_total != 0) ? p->sl_total * 2 : 16; /* 16 is arbitrary */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
262 void **new_slots = realloc(p->slots, new_size * sizeof(void *));
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
263 if (new_slots == 0)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
264 return;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
265 p->slots = new_slots;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
266 p->sl_total = new_size;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
267 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
268 p->slots[p->sl_curr++] = ptr;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
269 return;
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
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
272 /*@null@*/
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
273 char* do_slabs_stats(int *buflen) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
274 int i, total;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
275 char *buf = (char *)malloc(power_largest * 200 + 100);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
276 char *bufcurr = buf;
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 *buflen = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
279 if (buf == NULL) return NULL;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
280
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
281 total = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
282 for(i = POWER_SMALLEST; i <= power_largest; i++) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
283 slabclass_t *p = &slabclass[i];
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
284 if (p->slabs != 0) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
285 unsigned int perslab, slabs;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
286
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
287 slabs = p->slabs;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
288 perslab = p->perslab;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
289
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
290 bufcurr += sprintf(bufcurr, "STAT %d:chunk_size %u\r\n", i, p->size);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
291 bufcurr += sprintf(bufcurr, "STAT %d:chunks_per_page %u\r\n", i, perslab);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
292 bufcurr += sprintf(bufcurr, "STAT %d:total_pages %u\r\n", i, slabs);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
293 bufcurr += sprintf(bufcurr, "STAT %d:total_chunks %u\r\n", i, slabs*perslab);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
294 bufcurr += sprintf(bufcurr, "STAT %d:used_chunks %u\r\n", i, slabs*perslab - p->sl_curr);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
295 bufcurr += sprintf(bufcurr, "STAT %d:free_chunks %u\r\n", i, p->sl_curr);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
296 bufcurr += sprintf(bufcurr, "STAT %d:free_chunks_end %u\r\n", i, p->end_page_free);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
297 total++;
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 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
300 bufcurr += sprintf(bufcurr, "STAT active_slabs %d\r\nSTAT total_malloced %llu\r\n", total, (unsigned long long)mem_malloced);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
301 bufcurr += sprintf(bufcurr, "END\r\n");
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
302 *buflen = bufcurr - buf;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
303 return buf;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
304 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
305
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
306 #ifdef ALLOW_SLABS_REASSIGN
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
307 /* Blows away all the items in a slab class and moves its slabs to another
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
308 class. This is only used by the "slabs reassign" command, for manual tweaking
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
309 of memory allocation. It's disabled by default since it requires that all
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
310 slabs be the same size (which can waste space for chunk size mantissas of
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
311 other than 2.0).
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
312 1 = success
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
313 0 = fail
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
314 -1 = tried. busy. send again shortly. */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
315 int do_slabs_reassign(unsigned char srcid, unsigned char dstid) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
316 void *slab, *slab_end;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
317 slabclass_t *p, *dp;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
318 void *iter;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
319 bool was_busy = false;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
320
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
321 if (srcid < POWER_SMALLEST || srcid > power_largest ||
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
322 dstid < POWER_SMALLEST || dstid > power_largest)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
323 return 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
324
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
325 p = &slabclass[srcid];
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
326 dp = &slabclass[dstid];
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
327
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
328 /* fail if src still populating, or no slab to give up in src */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
329 if (p->end_page_ptr || ! p->slabs)
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
330 return 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
331
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
332 /* fail if dst is still growing or we can't make room to hold its new one */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
333 if (dp->end_page_ptr || ! grow_slab_list(dstid))
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
334 return 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
335
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
336 if (p->killing == 0) p->killing = 1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
337
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
338 slab = p->slab_list[p->killing - 1];
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
339 slab_end = (char*)slab + POWER_BLOCK;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
340
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
341 for (iter = slab; iter < slab_end; (char*)iter += p->size) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
342 item *it = (item *)iter;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
343 if (it->slabs_clsid) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
344 if (it->refcount) was_busy = true;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
345 item_unlink(it);
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
346 }
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 /* go through free list and discard items that are no longer part of this slab */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
350 {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
351 int fi;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
352 for (fi = p->sl_curr - 1; fi >= 0; fi--) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
353 if (p->slots[fi] >= slab && p->slots[fi] < slab_end) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
354 p->sl_curr--;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
355 if (p->sl_curr > fi) p->slots[fi] = p->slots[p->sl_curr];
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
356 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
357 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
358 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
359
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
360 if (was_busy) return -1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
361
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
362 /* if good, now move it to the dst slab class */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
363 p->slab_list[p->killing - 1] = p->slab_list[p->slabs - 1];
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
364 p->slabs--;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
365 p->killing = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
366 dp->slab_list[dp->slabs++] = slab;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
367 dp->end_page_ptr = slab;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
368 dp->end_page_free = dp->perslab;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
369 /* this isn't too critical, but other parts of the code do asserts to
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
370 make sure this field is always 0. */
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
371 for (iter = slab; iter < slab_end; (char*)iter += dp->size) {
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
372 ((item *)iter)->slabs_clsid = 0;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
373 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
374 return 1;
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
375 }
30782bb1fc04 memcached-1.2.3
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
376 #endif