Fix for bug #15450
[awesomized/libmemcached] / libmemcached / memcached.c
1 /*
2 Memcached library
3 */
4 #include "common.h"
5
6 memcached_st *memcached_create(memcached_st *ptr)
7 {
8 if (ptr == NULL)
9 {
10 ptr= (memcached_st *)calloc(1, sizeof(memcached_st));
11
12 if (! ptr)
13 {
14 return NULL; /* MEMCACHED_MEMORY_ALLOCATION_FAILURE */
15 }
16
17 ptr->options.is_allocated= true;
18 }
19 else
20 {
21 memset(ptr, 0, sizeof(memcached_st));
22 }
23
24 ptr->options.is_initialized= true;
25 ptr->options.is_purging= false;
26 ptr->options.is_processing_input= false;
27
28 memcached_set_memory_allocators(ptr, NULL, NULL, NULL, NULL);
29
30 if (! memcached_result_create(ptr, &ptr->result))
31 {
32 memcached_free(ptr);
33 return NULL;
34 }
35 ptr->poll_timeout= MEMCACHED_DEFAULT_TIMEOUT;
36 ptr->connect_timeout= MEMCACHED_DEFAULT_TIMEOUT;
37 ptr->retry_timeout= 0;
38 ptr->distribution= MEMCACHED_DISTRIBUTION_MODULA;
39
40 /* TODO, Document why we picked these defaults */
41 ptr->io_msg_watermark= 500;
42 ptr->io_bytes_watermark= 65 * 1024;
43
44 WATCHPOINT_ASSERT_INITIALIZED(&ptr->result);
45
46 return ptr;
47 }
48
49 void server_list_free(memcached_st *ptr, memcached_server_st *servers)
50 {
51 uint32_t x;
52
53 if (servers == NULL)
54 return;
55
56 for (x= 0; x < memcached_servers_count(servers); x++)
57 {
58 if (servers[x].address_info)
59 {
60 freeaddrinfo(servers[x].address_info);
61 servers[x].address_info= NULL;
62 }
63 }
64
65 if (ptr)
66 {
67 ptr->call_free(ptr, servers);
68 }
69 else
70 {
71 free(servers);
72 }
73 }
74
75 void memcached_servers_reset(memcached_st *ptr)
76 {
77 server_list_free(ptr, memcached_server_list(ptr));
78
79 memcached_server_list_set(ptr, NULL);
80 ptr->number_of_hosts= 0;
81 ptr->last_disconnected_server= NULL;
82 ptr->server_failure_limit= 0;
83 }
84
85 void memcached_free(memcached_st *ptr)
86 {
87 /* If we have anything open, lets close it now */
88 memcached_quit(ptr);
89 server_list_free(ptr, memcached_server_list(ptr));
90 memcached_result_free(&ptr->result);
91
92 if (ptr->on_cleanup)
93 ptr->on_cleanup(ptr);
94
95 if (ptr->continuum)
96 ptr->call_free(ptr, ptr->continuum);
97
98 if (memcached_is_allocated(ptr))
99 {
100 ptr->call_free(ptr, ptr);
101 }
102 else
103 {
104 ptr->options.is_initialized= false;
105 }
106 }
107
108 /*
109 clone is the destination, while source is the structure to clone.
110 If source is NULL the call is the same as if a memcached_create() was
111 called.
112 */
113 memcached_st *memcached_clone(memcached_st *clone, memcached_st *source)
114 {
115 memcached_return_t rc= MEMCACHED_SUCCESS;
116 memcached_st *new_clone;
117
118 if (source == NULL)
119 return memcached_create(clone);
120
121 if (clone && memcached_is_allocated(clone))
122 {
123 return NULL;
124 }
125
126 new_clone= memcached_create(clone);
127
128 if (new_clone == NULL)
129 return NULL;
130
131 new_clone->flags= source->flags;
132 new_clone->send_size= source->send_size;
133 new_clone->recv_size= source->recv_size;
134 new_clone->poll_timeout= source->poll_timeout;
135 new_clone->connect_timeout= source->connect_timeout;
136 new_clone->retry_timeout= source->retry_timeout;
137 new_clone->distribution= source->distribution;
138 new_clone->hash= source->hash;
139 new_clone->distribution_hash= source->distribution_hash;
140 new_clone->user_data= source->user_data;
141
142 new_clone->snd_timeout= source->snd_timeout;
143 new_clone->rcv_timeout= source->rcv_timeout;
144
145 new_clone->on_clone= source->on_clone;
146 new_clone->on_cleanup= source->on_cleanup;
147 new_clone->call_free= source->call_free;
148 new_clone->call_malloc= source->call_malloc;
149 new_clone->call_realloc= source->call_realloc;
150 new_clone->call_calloc= source->call_calloc;
151 new_clone->get_key_failure= source->get_key_failure;
152 new_clone->delete_trigger= source->delete_trigger;
153 new_clone->server_failure_limit= source->server_failure_limit;
154 new_clone->io_msg_watermark= source->io_msg_watermark;
155 new_clone->io_bytes_watermark= source->io_bytes_watermark;
156 new_clone->io_key_prefetch= source->io_key_prefetch;
157 new_clone->number_of_replicas= source->number_of_replicas;
158
159 if (memcached_server_list(source))
160 rc= memcached_server_push(new_clone, memcached_server_list(source));
161
162 if (rc != MEMCACHED_SUCCESS)
163 {
164 memcached_free(new_clone);
165
166 return NULL;
167 }
168
169
170 if (source->prefix_key[0] != 0)
171 {
172 strcpy(new_clone->prefix_key, source->prefix_key);
173 new_clone->prefix_key_length= source->prefix_key_length;
174 }
175
176 rc= run_distribution(new_clone);
177
178 if (rc != MEMCACHED_SUCCESS)
179 {
180 memcached_free(new_clone);
181
182 return NULL;
183 }
184
185 if (source->on_clone)
186 source->on_clone(source, new_clone);
187
188 return new_clone;
189 }
190
191 void *memcached_get_user_data(memcached_st *ptr)
192 {
193 return ptr->user_data;
194 }
195
196 void *memcached_set_user_data(memcached_st *ptr, void *data)
197 {
198 void *ret= ptr->user_data;
199 ptr->user_data= data;
200
201 return ret;
202 }