X-Git-Url: https://git.m6w6.name/?a=blobdiff_plain;f=example%2Fmemcached_light.cc;h=c76a42c24630dd40c46d317038b8d4461310b19e;hb=7781e7d0bf9fc0d986308838a3e1e47d0df3c019;hp=791d259be24379ecda39bb81916197198c7bc3b7;hpb=357b107e59d9918a0f3bdd7e4aad9493c70e03f1;p=awesomized%2Flibmemcached diff --git a/example/memcached_light.cc b/example/memcached_light.cc index 791d259b..c76a42c2 100644 --- a/example/memcached_light.cc +++ b/example/memcached_light.cc @@ -9,11 +9,11 @@ * With that in mind, let me give you some pointers into the source: * storage.c/h - Implements the item store for this server and not really * interesting for this example. - * interface_v0.c - Shows an implementation of the memcached server by using + * interface_v0.cc - Shows an implementation of the memcached server by using * the "raw" access to the packets as they arrive - * interface_v1.c - Shows an implementation of the memcached server by using + * interface_v1.cc - Shows an implementation of the memcached server by using * the more "logical" interface. - * memcached_light.c - This file sets up all of the sockets and run the main + * memcached_light.cc- This file sets up all of the sockets and run the main * message loop. * * @@ -23,14 +23,20 @@ * the library) */ -#include "config.h" +#include -#include +#include #include #include #include "example/storage.h" #include "example/memcached_light.h" +#include "util/daemon.hpp" +#include "util/log.hpp" +#include "util/pidfile.hpp" + +using namespace datadifferential; + #include #include @@ -42,8 +48,9 @@ #include #include #include -#include - +#if HAVE_UNISTD_H +# include +#endif extern memcached_binary_protocol_callback_st interface_v0_impl; extern memcached_binary_protocol_callback_st interface_v1_impl; @@ -60,15 +67,19 @@ struct connection static int maxconns= 1024; static struct connection *socket_userdata_map; -static struct event_base *event_base; +static struct event_base *event_base= NULL; struct options_st { - char *pid_file; + std::string pid_file; + std::string service; + std::string log_file; bool is_verbose; + bool opt_daemon; options_st() : - pid_file(NULL), - is_verbose(false) + service("9999"), + is_verbose(false), + opt_daemon(false) { } }; @@ -125,7 +136,7 @@ static void drive_client(memcached_socket_t fd, short, void *arg) flags|= EV_READ; } - event_set(&client->event, (intptr_t)fd, flags, drive_client, client); + event_set(&client->event, int(fd), flags, drive_client, client); event_base_set(event_base, &client->event); if (event_add(&client->event, 0) == -1) @@ -174,7 +185,7 @@ static void accept_handler(memcached_socket_t fd, short, void *arg) struct connection *client = &socket_userdata_map[sock]; client->userdata= c; - event_set(&client->event, (intptr_t)sock, EV_READ, drive_client, client); + event_set(&client->event, int(sock), EV_READ, drive_client, client); event_base_set(event_base, &client->event); if (event_add(&client->event, 0) == -1) { @@ -185,11 +196,7 @@ static void accept_handler(memcached_socket_t fd, short, void *arg) } } -/** - * Create a socket and bind it to a specific port number - * @param port the port number to bind to - */ -static int server_socket(const char *port) +static bool server_socket(util::log_info_st& log_file, const std::string& service) { struct addrinfo *ai; struct addrinfo hints; @@ -199,19 +206,23 @@ static int server_socket(const char *port) hints.ai_family= AF_UNSPEC; hints.ai_socktype= SOCK_STREAM; - int error= getaddrinfo("127.0.0.1", port, &hints, &ai); + int error= getaddrinfo("127.0.0.1", service.c_str(), &hints, &ai); if (error != 0) { if (error != EAI_SYSTEM) { - std::cerr << "getaddrinfo(): " << gai_strerror(error) << std::endl; + std::string buffer("getaddrinfo: "); + buffer+= gai_strerror(error); + log_file.write(util::VERBOSE_ERROR, buffer.c_str()); } else { - std::cerr << "getaddrinfo(): " << strerror(errno) << std::endl; + std::string buffer("getaddrinfo: "); + buffer+= strerror(errno); + log_file.write(util::VERBOSE_ERROR, buffer.c_str()); } - return 0; + return false; } struct linger ling= {0, 0}; @@ -221,7 +232,9 @@ static int server_socket(const char *port) memcached_socket_t sock= socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sock == INVALID_SOCKET) { - std::cerr << "Failed to create socket: " << strerror(errno) << std::endl; + std::string buffer("Failed to create socket: "); + buffer+= strerror(errno); + log_file.write(util::VERBOSE_ERROR, buffer.c_str()); continue; } @@ -238,7 +251,9 @@ static int server_socket(const char *port) flags= fcntl(sock, F_GETFL, 0); if (flags == -1) { - std::cerr << "Failed to get socket flags: " << strerror(errno) << std::endl; + std::string buffer("Failed to get socket flags: "); + buffer+= strerror(errno); + log_file.write(util::VERBOSE_ERROR, buffer.c_str()); closesocket(sock); continue; } @@ -247,7 +262,9 @@ static int server_socket(const char *port) { if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1) { - std::cerr << "Failed to set socket to nonblocking mode: " << strerror(errno) << std::endl; + std::string buffer("Failed to set socket to nonblocking mode: "); + buffer+= strerror(errno); + log_file.write(util::VERBOSE_ERROR, buffer.c_str()); closesocket(sock); continue; } @@ -288,14 +305,18 @@ static int server_socket(const char *port) if (listen(sock, 1024) == SOCKET_ERROR) { - std::cerr << "listen(): " << strerror(errno) << std::endl; + std::string buffer("listen(): "); + buffer+= strerror(errno); + log_file.write(util::VERBOSE_ERROR, buffer.c_str()); closesocket(sock); continue; } if (global_options.is_verbose) { - std::cout << "Listening to " << port << std::endl; + std::string buffer("Listening to: "); + buffer+= global_options.service; + log_file.write(util::VERBOSE_NOTICE, buffer.c_str()); } server_sockets[num_server_sockets++]= sock; @@ -303,7 +324,7 @@ static int server_socket(const char *port) freeaddrinfo(ai); - return (num_server_sockets > 0) ? 0 : 1; + return (num_server_sockets > 0) ? true : false; } /** @@ -414,45 +435,35 @@ int main(int argc, char **argv) { memcached_binary_protocol_callback_st *interface= &interface_v0_impl; - event_base= event_init(); - if (event_base == NULL) - { - std::cerr << "Failed to create an instance of libevent" << std::endl; - return EXIT_FAILURE; - } - - /* - * We need to initialize the handlers manually due to a bug in the - * warnings generated by struct initialization in gcc (all the way up to 4.4) - */ - initialize_interface_v0_handler(); - initialize_interface_v1_handler(); - { enum long_option_t { OPT_HELP, OPT_VERBOSE, + OPT_DAEMON, OPT_PROTOCOL_VERSION, OPT_VERSION, OPT_PORT, OPT_MAX_CONNECTIONS, + OPT_LOGFILE, OPT_PIDFILE }; static struct option long_options[]= { - {"help", no_argument, NULL, OPT_HELP}, - {"port", required_argument, NULL, OPT_PORT}, - {"verbose", no_argument, NULL, OPT_VERBOSE}, - {"protocol", required_argument, NULL, OPT_PROTOCOL_VERSION}, - {"version", no_argument, NULL, OPT_VERSION}, - {"max-connections", required_argument, NULL, OPT_MAX_CONNECTIONS}, - {"pid-file", required_argument, NULL, OPT_PIDFILE}, + { "help", no_argument, NULL, OPT_HELP }, + { "port", required_argument, NULL, OPT_PORT }, + { "verbose", no_argument, NULL, OPT_VERBOSE }, + { "daemon", no_argument, NULL, OPT_DAEMON }, + { "protocol", no_argument, NULL, OPT_PROTOCOL_VERSION }, + { "version", no_argument, NULL, OPT_VERSION }, + { "max-connections", required_argument, NULL, OPT_MAX_CONNECTIONS }, + { "pid-file", required_argument, NULL, OPT_PIDFILE }, + { "log-file", required_argument, NULL, OPT_LOGFILE }, {0, 0, 0, 0} }; + bool opt_help= false; int option_index; - bool has_port= false; bool done= false; while (done == false) { @@ -467,16 +478,26 @@ int main(int argc, char **argv) break; case OPT_PIDFILE: - global_options.pid_file= strdup(optarg); + global_options.pid_file= optarg; + break; + + case OPT_LOGFILE: + global_options.log_file= optarg; break; case OPT_VERBOSE: global_options.is_verbose= true; break; + case OPT_VERSION: + break; + + case OPT_DAEMON: + global_options.opt_daemon= true; + break; + case OPT_PORT: - has_port= true; - (void)server_socket(optarg); + global_options.service= optarg; break; case OPT_MAX_CONNECTIONS: @@ -484,12 +505,8 @@ int main(int argc, char **argv) break; case OPT_HELP: /* FALLTHROUGH */ - std::cout << "Usage: " << argv[0] << std::endl; - for (struct option *ptr_option= long_options; ptr_option->name; ptr_option++) - { - std::cout << "\t" << ptr_option->name << std::endl; - } - return EXIT_SUCCESS; + opt_help= true; + break; default: { @@ -499,42 +516,55 @@ int main(int argc, char **argv) } } - if (has_port == false) + if (opt_help) { - (void)server_socket("9999"); + std::cout << "Usage: " << argv[0] << std::endl; + for (struct option *ptr_option= long_options; ptr_option->name; ptr_option++) + { + std::cout << "\t" << ptr_option->name << std::endl; + } + return EXIT_SUCCESS; } } - if (! initialize_storage()) + if (global_options.opt_daemon) + { + util::daemonize(false, true); + } + + if (initialize_storage() == false) { /* Error message already printed */ return EXIT_FAILURE; } - if (global_options.pid_file) + util::Pidfile _pid_file(global_options.pid_file); + + if (_pid_file.create() == false) { - FILE *pid_file; - uint32_t pid; + std::cerr << "Failed to create pid-file" << _pid_file.error_message() << std::endl; + return EXIT_FAILURE; + } - pid_file= fopen(global_options.pid_file, "w+"); + util::log_info_st log_file(argv[0], global_options.log_file, false); + log_file.write(util::VERBOSE_NOTICE, "starting log"); - if (pid_file == NULL) - { - perror(strerror(get_socket_errno())); - abort(); - } + /* + * We need to initialize the handlers manually due to a bug in the + * warnings generated by struct initialization in gcc (all the way up to 4.4) + */ + initialize_interface_v0_handler(log_file); + initialize_interface_v1_handler(log_file); - pid= (uint32_t)getpid(); - if (global_options.is_verbose) - { - std::cout << "pid:" << pid << std::endl; - } - fclose(pid_file); + + if (server_socket(log_file, global_options.service) == false) + { + return EXIT_FAILURE; } if (num_server_sockets == 0) { - std::cerr << "No server sockets are available" << std::endl; + log_file.write(util::VERBOSE_ERROR, "No server sockets are available."); return EXIT_FAILURE; } @@ -550,37 +580,67 @@ int main(int argc, char **argv) struct memcached_protocol_st *protocol_handle; if ((protocol_handle= memcached_protocol_create_instance()) == NULL) { - std::cerr << "Failed to allocate protocol handle" << std::endl; + log_file.write(util::VERBOSE_ERROR, "No server sockets are available."); return EXIT_FAILURE; } socket_userdata_map= (struct connection*)calloc((size_t)(maxconns), sizeof(struct connection)); if (socket_userdata_map == NULL) { - std::cerr << "Failed to allocate room for connections" << std::endl; + log_file.write(util::VERBOSE_ERROR, "Failed to allocate room for connections"); return EXIT_FAILURE; } memcached_binary_protocol_set_callbacks(protocol_handle, interface); memcached_binary_protocol_set_pedantic(protocol_handle, true); + event_base= event_init(); + if (event_base == NULL) + { + std::cerr << "Failed to create an instance of libevent" << std::endl; + return EXIT_FAILURE; + } + for (int xx= 0; xx < num_server_sockets; ++xx) { struct connection *conn= &socket_userdata_map[server_sockets[xx]]; conn->userdata= protocol_handle; - event_set(&conn->event, (intptr_t)server_sockets[xx], EV_READ | EV_PERSIST, accept_handler, conn); + event_set(&conn->event, int(server_sockets[xx]), EV_READ | EV_PERSIST, accept_handler, conn); event_base_set(event_base, &conn->event); if (event_add(&conn->event, 0) == -1) { - std::cerr << "Failed to add event for " << server_sockets[xx] << std::endl; + log_file.write(util::VERBOSE_ERROR, "Failed to add event"); closesocket(server_sockets[xx]); } } + if (global_options.opt_daemon) + { + if (util::daemon_is_ready(true) == false) + { + log_file.write(util::VERBOSE_ERROR, "Failed for util::daemon_is_ready()"); + return EXIT_FAILURE; + } + } + + /* Serve all of the clients */ - event_base_loop(event_base, 0); + switch (event_base_loop(event_base, 0)) + { + case -1: + log_file.write(util::VERBOSE_ERROR, "event_base_loop() failed"); + break; + + case 1: + log_file.write(util::VERBOSE_ERROR, "event_base_loop(), no events were registered"); + break; + + default: + break; + } + log_file.write(util::VERBOSE_NOTICE, "exiting"); /* NOTREACHED */ return EXIT_SUCCESS;