emit messages to stderr when write fails
[awesomized/libmemcached] / lib / memcached_get.c
1 #include <memcached.h>
2
3 char *memcached_get(memcached_st *ptr, char *key, size_t key_length,
4 size_t *value_length,
5 uint16_t *flags,
6 memcached_return *error)
7 {
8 size_t send_length, sent_length;
9 char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
10 char *string_ptr;
11 unsigned int server_key;
12
13 *value_length= 0;
14 *error= memcached_connect(ptr);
15
16 if (*error != MEMCACHED_SUCCESS)
17 return NULL;
18
19 server_key= memcached_generate_hash(key, key_length) % ptr->number_of_hosts;
20
21 send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, "get %.*s\r\n",
22 (int)key_length, key);
23
24 if (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE)
25 {
26 *error= MEMCACHED_WRITE_FAILURE;
27 return NULL;
28 }
29
30 sent_length= write(ptr->hosts[server_key].fd, buffer, send_length);
31
32 if (sent_length == -1)
33 {
34 fprintf(stderr, "error %s: write: %m\n", __FUNCTION__);
35 *error= MEMCACHED_WRITE_FAILURE;
36 return NULL;
37 }
38
39 if (sent_length != send_length)
40 {
41 fprintf(stderr, "error %s: short write %d %d: %m\n",
42 __FUNCTION__, sent_length, send_length);
43 *error= MEMCACHED_WRITE_FAILURE;
44 return NULL;
45 }
46
47 memset(buffer, 0, MEMCACHED_DEFAULT_COMMAND_SIZE);
48 *error= memcached_response(ptr, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, server_key);
49
50 if (*error == MEMCACHED_SUCCESS)
51 {
52 char *end_ptr;
53
54 string_ptr= buffer;
55 string_ptr+= 6; /* "VALUE " */
56
57 /* We do nothing with the key, since we only asked for one key */
58 for (end_ptr= string_ptr; *end_ptr != ' '; end_ptr++);
59
60 /* Flags fetch */
61 string_ptr= end_ptr + 1;
62 for (end_ptr= string_ptr; *end_ptr != ' '; end_ptr++);
63 *flags= (uint16_t)strtol(string_ptr, &end_ptr, 10);
64
65 /* Length fetch */
66 string_ptr= end_ptr + 1;
67 for (end_ptr= string_ptr; *end_ptr != ' '; end_ptr++);
68 *value_length= strtoll(string_ptr, &end_ptr, 10);
69
70 /* Skip past the \r\n */
71 string_ptr= end_ptr +2;
72
73 if (*value_length)
74 {
75 size_t need_to_copy;
76 char *pos_ptr;
77 char *value;
78
79 value= (char *)malloc(*value_length * sizeof(char));
80
81 if (!value)
82 {
83 *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
84 return NULL;
85 }
86
87 need_to_copy= (*value_length < (size_t)(buffer-string_ptr))
88 ? *value_length
89 : (size_t)(buffer-string_ptr) ;
90
91 pos_ptr= memcpy(value, string_ptr, need_to_copy);
92
93 if ( need_to_copy > *value_length)
94 {
95 size_t read_length;
96 size_t need_to_read;
97
98 need_to_read= *value_length - need_to_copy;
99
100 read_length= read(ptr->hosts[server_key].fd, pos_ptr, need_to_read);
101 if (read_length != need_to_read)
102 {
103 free(value);
104 *error= MEMCACHED_PARTIAL_READ;
105
106 return NULL;
107 }
108 }
109
110 return value;
111 }
112 }
113
114 return NULL;
115 }