Updated with Twitter's memcached_server_error() function.
[m6w6/libmemcached] / clients / memcp.c
1 #include "libmemcached/common.h"
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <inttypes.h>
5 #include <unistd.h>
6 #include <getopt.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <sys/types.h>
10 #include <fcntl.h>
11 #include <errno.h>
12 #include <strings.h>
13 #include <string.h>
14
15 #include <libmemcached/memcached.h>
16
17 #include "client_options.h"
18 #include "utilities.h"
19
20 #define PROGRAM_NAME "memcp"
21 #define PROGRAM_DESCRIPTION "Copy a set of files to a memcached cluster."
22
23 /* Prototypes */
24 void options_parse(int argc, char *argv[]);
25
26 static int opt_binary=0;
27 static int opt_verbose= 0;
28 static char *opt_servers= NULL;
29 static char *opt_hash= NULL;
30 static int opt_method= OPT_SET;
31 static uint32_t opt_flags= 0;
32 static time_t opt_expires= 0;
33
34 int main(int argc, char *argv[])
35 {
36 memcached_st *memc;
37 memcached_return rc;
38 memcached_server_st *servers;
39
40 options_parse(argc, argv);
41
42 memc= memcached_create(NULL);
43 process_hash_option(memc, opt_hash);
44
45 if (!opt_servers)
46 {
47 char *temp;
48
49 if ((temp= getenv("MEMCACHED_SERVERS")))
50 opt_servers= strdup(temp);
51 else
52 {
53 fprintf(stderr, "No Servers provided\n");
54 exit(1);
55 }
56 }
57
58 if (opt_servers)
59 servers= memcached_servers_parse(opt_servers);
60 else
61 servers= memcached_servers_parse(argv[--argc]);
62
63 memcached_server_push(memc, servers);
64 memcached_server_list_free(servers);
65 memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
66 (uint64_t)opt_binary);
67
68 while (optind < argc)
69 {
70 struct stat sbuf;
71 int fd;
72 char *ptr;
73 ssize_t read_length;
74 char *file_buffer_ptr;
75
76 fd= open(argv[optind], O_RDONLY);
77 if (fd < 0)
78 {
79 fprintf(stderr, "memcp: %s: %s\n", argv[optind], strerror(errno));
80 optind++;
81 continue;
82 }
83
84 (void)fstat(fd, &sbuf);
85
86 ptr= rindex(argv[optind], '/');
87 if (ptr)
88 ptr++;
89 else
90 ptr= argv[optind];
91
92 if (opt_verbose)
93 {
94 static const char *opstr[] = { "set", "add", "replace" };
95 printf("op: %s\nsource file: %s\nlength: %zu\n"
96 "key: %s\nflags: %x\nexpires: %llu\n",
97 opstr[opt_method - OPT_SET], argv[optind], (size_t)sbuf.st_size,
98 ptr, opt_flags, (unsigned long long)opt_expires);
99 }
100
101 if ((file_buffer_ptr= (char *)malloc(sizeof(char) * (size_t)sbuf.st_size)) == NULL)
102 {
103 fprintf(stderr, "malloc: %s\n", strerror(errno));
104 exit(1);
105 }
106
107 if ((read_length= read(fd, file_buffer_ptr, (size_t)sbuf.st_size)) == -1)
108 {
109 fprintf(stderr, "read: %s\n", strerror(errno));
110 exit(1);
111 }
112
113 if (read_length != sbuf.st_size)
114 {
115 fprintf(stderr, "Failure reading from file\n");
116 exit(1);
117 }
118
119 if (opt_method == OPT_ADD)
120 rc= memcached_add(memc, ptr, strlen(ptr),
121 file_buffer_ptr, (size_t)sbuf.st_size,
122 opt_expires, opt_flags);
123 else if (opt_method == OPT_REPLACE)
124 rc= memcached_replace(memc, ptr, strlen(ptr),
125 file_buffer_ptr, (size_t)sbuf.st_size,
126 opt_expires, opt_flags);
127 else
128 rc= memcached_set(memc, ptr, strlen(ptr),
129 file_buffer_ptr, (size_t)sbuf.st_size,
130 opt_expires, opt_flags);
131
132 if (rc != MEMCACHED_SUCCESS)
133 {
134 fprintf(stderr, "memcp: %s: memcache error %s",
135 ptr, memcached_strerror(memc, rc));
136 if (memc->cached_errno)
137 fprintf(stderr, " system error %s", strerror(memc->cached_errno));
138 fprintf(stderr, "\n");
139 }
140
141 free(file_buffer_ptr);
142 close(fd);
143 optind++;
144 }
145
146 memcached_free(memc);
147
148 if (opt_servers)
149 free(opt_servers);
150 if (opt_hash)
151 free(opt_hash);
152
153 return 0;
154 }
155
156 void options_parse(int argc, char *argv[])
157 {
158 int option_index= 0;
159 int option_rv;
160
161 memcached_programs_help_st help_options[]=
162 {
163 {0},
164 };
165
166 static struct option long_options[]=
167 {
168 {"version", no_argument, NULL, OPT_VERSION},
169 {"help", no_argument, NULL, OPT_HELP},
170 {"verbose", no_argument, &opt_verbose, OPT_VERBOSE},
171 {"debug", no_argument, &opt_verbose, OPT_DEBUG},
172 {"servers", required_argument, NULL, OPT_SERVERS},
173 {"flag", required_argument, NULL, OPT_FLAG},
174 {"expire", required_argument, NULL, OPT_EXPIRE},
175 {"set", no_argument, NULL, OPT_SET},
176 {"add", no_argument, NULL, OPT_ADD},
177 {"replace", no_argument, NULL, OPT_REPLACE},
178 {"hash", required_argument, NULL, OPT_HASH},
179 {"binary", no_argument, NULL, OPT_BINARY},
180 {0, 0, 0, 0},
181 };
182
183 while (1)
184 {
185 option_rv= getopt_long(argc, argv, "Vhvds:", long_options, &option_index);
186
187 if (option_rv == -1) break;
188
189 switch (option_rv)
190 {
191 case 0:
192 break;
193 case OPT_BINARY:
194 opt_binary = 1;
195 break;
196 case OPT_VERBOSE: /* --verbose or -v */
197 opt_verbose = OPT_VERBOSE;
198 break;
199 case OPT_DEBUG: /* --debug or -d */
200 opt_verbose = OPT_DEBUG;
201 break;
202 case OPT_VERSION: /* --version or -V */
203 version_command(PROGRAM_NAME);
204 break;
205 case OPT_HELP: /* --help or -h */
206 help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, help_options);
207 break;
208 case OPT_SERVERS: /* --servers or -s */
209 opt_servers= strdup(optarg);
210 break;
211 case OPT_FLAG: /* --flag */
212 opt_flags= (uint32_t)strtol(optarg, (char **)NULL, 16);
213 break;
214 case OPT_EXPIRE: /* --expire */
215 opt_expires= (time_t)strtoll(optarg, (char **)NULL, 10);
216 break;
217 case OPT_SET:
218 opt_method= OPT_SET;
219 break;
220 case OPT_REPLACE:
221 opt_method= OPT_REPLACE;
222 break;
223 case OPT_ADD:
224 opt_method= OPT_ADD;
225 case OPT_HASH:
226 opt_hash= strdup(optarg);
227 break;
228 case '?':
229 /* getopt_long already printed an error message. */
230 exit(1);
231 default:
232 abort();
233 }
234 }
235 }