From: Brian Aker Date: Tue, 19 Jul 2011 05:28:50 +0000 (-0700) Subject: Merge in util library. X-Git-Tag: 0.51~1^2~2^2 X-Git-Url: https://git.m6w6.name/?a=commitdiff_plain;h=23d5278248d8f3deff5903d17b6d55cc503ef3a9;p=awesomized%2Flibmemcached Merge in util library. --- diff --git a/util/daemon.cc b/util/daemon.cc new file mode 100644 index 00000000..3b129d18 --- /dev/null +++ b/util/daemon.cc @@ -0,0 +1,194 @@ +/* $Header: /cvsroot/wikipedia/willow/src/bin/willow/daemon.c,v 1.1 2005/05/02 19:15:21 kateturner Exp $ */ +/* $NetBSD: daemon.c,v 1.9 2003/08/07 16:42:46 agc Exp $ */ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 2010 + * Stewart Smith + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#if defined __SUNPRO_C || defined __DECC || defined __HP_cc +# pragma ident "@(#)$Header: /cvsroot/wikipedia/willow/src/bin/willow/daemon.c,v 1.1 2005/05/02 19:15:21 kateturner Exp $" +# pragma ident "$NetBSD: daemon.c,v 1.9 2003/08/07 16:42:46 agc Exp $" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +namespace datadifferential { +namespace util { + +pid_t parent_pid; + +extern "C" +{ + +static void sigusr1_handler(int sig) +{ + if (sig == SIGUSR1) + { + _exit(EXIT_SUCCESS); + } +} + +} + +bool daemon_is_ready(bool close_io) +{ + if (kill(parent_pid, SIGUSR1) == -1) + { + perror("kill"); + return false; + } + + if (not close_io) + { + return true;; + } + + int fd; + if ((fd = open("/dev/null", O_RDWR, 0)) < 0) + { + perror("open"); + return false; + } + else + { + if (dup2(fd, STDIN_FILENO) < 0) + { + perror("dup2 stdin"); + return false; + } + + if (dup2(fd, STDOUT_FILENO) < 0) + { + perror("dup2 stdout"); + return false; + } + + if (dup2(fd, STDERR_FILENO) < 0) + { + perror("dup2 stderr"); + return false; + } + + if (fd > STDERR_FILENO) + { + if (close(fd) < 0) + { + perror("close"); + return false; + } + } + } + + return true; +} + +#ifndef __INTEL_COMPILER +#pragma GCC diagnostic ignored "-Wold-style-cast" +#endif + +bool daemonize(bool is_chdir, bool wait_sigusr1) +{ + struct sigaction new_action; + + new_action.sa_handler= sigusr1_handler; + sigemptyset(&new_action.sa_mask); + new_action.sa_flags= 0; + sigaction(SIGUSR1, &new_action, NULL); + + parent_pid= getpid(); + + pid_t child= fork(); + + switch (child) + { + case -1: + return false; + + case 0: + break; + + default: + if (wait_sigusr1) + { + /* parent */ + int exit_code= EXIT_FAILURE; + int status; + while (waitpid(child, &status, 0) != child) + { } + + if (WIFEXITED(status)) + { + exit_code= WEXITSTATUS(status); + } + if (WIFSIGNALED(status)) + { + exit_code= EXIT_FAILURE; + } + _exit(exit_code); + } + else + { + _exit(EXIT_SUCCESS); + } + } + + /* child */ + if (setsid() == -1) + { + perror("setsid"); + return false; + } + + if (is_chdir) + { + if (chdir("/") < 0) + { + perror("chdir"); + return false; + } + } + + return true; +} + +} /* namespace util */ +} /* namespace datadifferential */ diff --git a/util/daemon.hpp b/util/daemon.hpp new file mode 100644 index 00000000..170f52db --- /dev/null +++ b/util/daemon.hpp @@ -0,0 +1,43 @@ +/* $Header: /cvsroot/wikipedia/willow/src/bin/willow/daemon.c,v 1.1 2005/05/02 19:15:21 kateturner Exp $ */ +/* $NetBSD: daemon.c,v 1.9 2003/08/07 16:42:46 agc Exp $ */ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 2010 + * Stewart Smith + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#pragma once + +namespace datadifferential { +namespace util { + +bool daemon_is_ready(bool close_io); +bool daemonize(bool is_chdir= true, bool wait_sigusr1= true); + +} /* namespace util */ +} /* namespace datadifferential */ diff --git a/util/include.am b/util/include.am new file mode 100644 index 00000000..9eed1999 --- /dev/null +++ b/util/include.am @@ -0,0 +1,18 @@ +# vim:ft=automake +# DataDifferential Utility Library +# Copyright (C) 2011 Data Differential +# All rights reserved. +# +# Use and distribution licensed under the BSD license. See +# the COPYING file in the parent directory for full text. +# +# Included from Top Level Makefile.am +# All paths should be given relative to the root + + +noinst_HEADERS+= \ + util/daemon.hpp \ + util/instance.hpp \ + util/operation.hpp \ + util/string.hpp \ + util/pidfile.hpp diff --git a/util/instance.cc b/util/instance.cc new file mode 100644 index 00000000..a5c289ef --- /dev/null +++ b/util/instance.cc @@ -0,0 +1,304 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * DataDifferential Utility Library + * + * Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * The names of its contributors may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include + +#include "util/instance.hpp" + +#include +#include +#include +#include +#include +#include +#include + + +namespace datadifferential { +namespace util { + +Instance::Instance(const std::string& hostname_arg, const std::string& service_arg) : + _host(hostname_arg), + _service(service_arg), + _sockfd(INVALID_SOCKET), + state(NOT_WRITING), + _addrinfo(0), + _addrinfo_next(0), + _finish_fn(NULL), + _operations() + { + } + +Instance::Instance(const std::string& hostname_arg, const in_port_t port_arg) : + _host(hostname_arg), + _sockfd(INVALID_SOCKET), + state(NOT_WRITING), + _addrinfo(0), + _addrinfo_next(0), + _finish_fn(NULL), + _operations() + { + char tmp[BUFSIZ]; + snprintf(tmp, sizeof(tmp), "%u", static_cast(port_arg)); + _service= tmp; + } + +Instance::~Instance() +{ + close_socket(); + free_addrinfo(); + for (Operation::vector::iterator iter= _operations.begin(); iter != _operations.end(); ++iter) + { + delete *iter; + } + _operations.clear(); + + delete _finish_fn; +} + +bool Instance::run() +{ + while (not _operations.empty()) + { + Operation::vector::value_type operation= _operations.back(); + + switch (state) + { + case NOT_WRITING: + { + free_addrinfo(); + + struct addrinfo ai; + memset(&ai, 0, sizeof(struct addrinfo)); + ai.ai_socktype= SOCK_STREAM; + ai.ai_protocol= IPPROTO_TCP; + + int ret= getaddrinfo(_host.c_str(), _service.c_str(), &ai, &_addrinfo); + if (ret) + { + std::stringstream message; + message << "Failed to connect on " << _host.c_str() << ":" << _service.c_str() << " with " << gai_strerror(ret); + _last_error= message.str(); + return false; + } + } + _addrinfo_next= _addrinfo; + state= CONNECT; + break; + + case NEXT_CONNECT_ADDRINFO: + if (_addrinfo_next->ai_next == NULL) + { + std::stringstream message; + message << "Error connecting to " << _host.c_str() << "." << std::endl; + _last_error= message.str(); + return false; + } + _addrinfo_next= _addrinfo_next->ai_next; + + + case CONNECT: + close_socket(); + + _sockfd= socket(_addrinfo_next->ai_family, + _addrinfo_next->ai_socktype, + _addrinfo_next->ai_protocol); + if (_sockfd == INVALID_SOCKET) + { + perror("socket"); + continue; + } + + if (connect(_sockfd, _addrinfo_next->ai_addr, _addrinfo_next->ai_addrlen) < 0) + { + switch(errno) + { + case EAGAIN: + case EINTR: + state= CONNECT; + break; + + case EINPROGRESS: + state= CONNECTING; + break; + + case ECONNREFUSED: + case ENETUNREACH: + case ETIMEDOUT: + default: + state= NEXT_CONNECT_ADDRINFO; + break; + } + } + else + { + state= CONNECTING; + } + break; + + case CONNECTING: + // Add logic for poll() for nonblocking. + state= CONNECTED; + break; + + case CONNECTED: + case WRITING: + { + size_t packet_length= operation->size(); + const char *packet= operation->ptr(); + + while(packet_length) + { + ssize_t write_size= send(_sockfd, packet, packet_length, 0); + + if (write_size < 0) + { + switch(errno) + { + default: + std::cerr << "Failed during send(" << strerror(errno) << ")" << std::endl; + break; + } + } + + packet_length-= static_cast(write_size); + packet+= static_cast(write_size); + } + } + state= READING; + break; + + case READING: + if (operation->has_response()) + { + size_t total_read; + ssize_t read_length; + + do + { + char buffer[BUFSIZ]; + read_length= recv(_sockfd, buffer, sizeof(buffer), 0); + + if (read_length < 0) + { + switch(errno) + { + default: + std::cerr << "Error occured while reading data from " << _host.c_str() << std::endl; + return false; + } + } + + operation->push(buffer, static_cast(read_length)); + total_read+= static_cast(read_length); + } while (more_to_read()); + } // end has_response + + state= FINISHED; + break; + + case FINISHED: + std::string response; + bool success= operation->response(response); + if (_finish_fn) + { + if (not _finish_fn->call(success, response)) + { + // Error was sent from _finish_fn + return false; + } + } + + if (operation->reconnect()) + { + } + _operations.pop_back(); + delete operation; + + state= CONNECTED; + break; + } // end switch + } + + return true; +} // end run() + +bool Instance::more_to_read() const +{ + struct pollfd fds; + fds.fd= _sockfd; + fds.events = POLLIN; + + if (poll(&fds, 1, 5) < 1) // Default timeout is 5 + { + return false; + } + + return true; +} + +void Instance::close_socket() +{ + if (_sockfd == INVALID_SOCKET) + return; + + /* in case of death shutdown to avoid blocking at close() */ + if (shutdown(_sockfd, SHUT_RDWR) == SOCKET_ERROR && get_socket_errno() != ENOTCONN) + { + perror("shutdown"); + } + else if (closesocket(_sockfd) == SOCKET_ERROR) + { + perror("close"); + } + + _sockfd= INVALID_SOCKET; +} + +void Instance::free_addrinfo() +{ + if (not _addrinfo) + return; + + freeaddrinfo(_addrinfo); + _addrinfo= NULL; + _addrinfo_next= NULL; +} + +} /* namespace util */ +} /* namespace datadifferential */ diff --git a/util/instance.hpp b/util/instance.hpp new file mode 100644 index 00000000..ff750f4f --- /dev/null +++ b/util/instance.hpp @@ -0,0 +1,116 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * DataDifferential Utility Library + * + * Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * The names of its contributors may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "util/operation.hpp" + +struct addrinfo; + +namespace datadifferential { +namespace util { + +class Instance +{ +private: + enum connection_state_t { + NOT_WRITING, + NEXT_CONNECT_ADDRINFO, + CONNECT, + CONNECTING, + CONNECTED, + WRITING, + READING, + FINISHED + }; + std::string _last_error; + +public: // Callbacks + class Finish { + + public: + virtual ~Finish() { } + + virtual bool call(const bool, const std::string &)= 0; + }; + + +public: + Instance(const std::string& hostname_arg, const std::string& service_arg); + + Instance(const std::string& hostname_arg, const in_port_t port_arg); + + ~Instance(); + + bool run(); + + void set_finish(Finish *arg) + { + _finish_fn= arg; + } + + void push(util::Operation *next) + { + _operations.push_back(next); + } + +private: + void close_socket(); + + void free_addrinfo(); + + bool more_to_read() const; + + std::string _host; + std::string _service; + int _sockfd; + connection_state_t state; + struct addrinfo *_addrinfo; + struct addrinfo *_addrinfo_next; + Finish *_finish_fn; + Operation::vector _operations; +}; + +} /* namespace util */ +} /* namespace datadifferential */ diff --git a/util/operation.hpp b/util/operation.hpp new file mode 100644 index 00000000..5c8c26ed --- /dev/null +++ b/util/operation.hpp @@ -0,0 +1,125 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * DataDifferential Utility Library + * + * Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * The names of its contributors may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#pragma once + + +#include +#include +#include + +namespace datadifferential { +namespace util { + +class Operation { + typedef std::vector Packet; + +public: + typedef std::vector vector; + + Operation(const char *command, size_t command_length, bool expect_response= true) : + _expect_response(expect_response), + packet(), + _response() + { + packet.resize(command_length); + memcpy(&packet[0], command, command_length); + } + + ~Operation() + { } + + size_t size() const + { + return packet.size(); + } + + const char* ptr() const + { + return &(packet)[0]; + } + + bool has_response() const + { + return _expect_response; + } + + void push(const char *buffer, size_t buffer_size) + { + size_t response_size= _response.size(); + _response.resize(response_size +buffer_size); + memcpy(&_response[0] +response_size, buffer, buffer_size); + } + + // Return false on error + bool response(std::string &arg) + { + if (_response.empty()) + return false; + + if (not memcmp("OK\r\n", &_response[0], 3)) + { } + else if (not memcmp("OK ", &_response[0], 3)) + { + arg.append(&_response[3], _response.size() -3); + } + else if (not memcmp("ERR ", &_response[0], 4)) + { + arg.append(&_response[4], _response.size() -4); + return false; + } + else + { + arg.append(&_response[0], _response.size()); + } + + return true; + } + + bool reconnect() const + { + return false; + } + +private: + bool _expect_response; + Packet packet; + Packet _response; +}; + +} /* namespace util */ +} /* namespace datadifferential */ diff --git a/util/pidfile.cc b/util/pidfile.cc new file mode 100644 index 00000000..14b28479 --- /dev/null +++ b/util/pidfile.cc @@ -0,0 +1,107 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * DataDifferential Utility Library + * + * Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * The names of its contributors may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "config.h" + +#include "util/pidfile.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace datadifferential { +namespace util { + +Pidfile::Pidfile(const std::string &arg) : + _last_errno(0), + _filename(arg) +{ +} + + +Pidfile::~Pidfile() +{ + if (not _filename.empty() and (unlink(_filename.c_str()) == -1)) + { + _error_message+= "Could not remove the pid file: "; + _error_message+= _filename; + } +} + +bool Pidfile::create() +{ + if (_filename.empty()) + return true; + + int file; + if ((file = open(_filename.c_str(), O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU|S_IRGRP|S_IROTH)) < 0) + { + _error_message+= "Could not open pid file for writing: "; + _error_message+= _filename; + return false; + } + + char buffer[BUFSIZ]; + + unsigned long temp= static_cast(getpid()); + int length= snprintf(buffer, sizeof(buffer), "%lu\n", temp); + + if (write(file, buffer, length) != length) + { + _error_message+= "Could not write pid to file: "; + _error_message+= _filename; + + return false; + } + + if (close(file < 0)) + { + _error_message+= "Could not close() file after writing pid to it: "; + _error_message+= _filename; + return false; + } + + return true; +} + +} /* namespace util */ +} /* namespace datadifferential */ diff --git a/util/pidfile.hpp b/util/pidfile.hpp new file mode 100644 index 00000000..71d89e11 --- /dev/null +++ b/util/pidfile.hpp @@ -0,0 +1,67 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * DataDifferential Utility Library + * + * Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * The names of its contributors may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#pragma once + + +#include + +namespace datadifferential { +namespace util { + +class Pidfile +{ +public: + Pidfile(const std::string &arg); + + ~Pidfile(); + + const std::string &error_message() + { + return _error_message; + } + + bool create(); + +private: + int _last_errno; + std::string _filename; + std::string _error_message; +}; + +} /* namespace util */ +} /* namespace datadifferential */ diff --git a/util/string.hpp b/util/string.hpp new file mode 100644 index 00000000..58d0ce27 --- /dev/null +++ b/util/string.hpp @@ -0,0 +1,53 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * DataDifferential Utility Library + * + * Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * The names of its contributors may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +/* + Simple defines +*/ + +#include +#include + +#pragma once + +#define util_literal_param(X) (X), (static_cast((sizeof(X) - 1))) +#define util_literal_param_size(X) static_cast(sizeof(X) - 1) + +#define util_string_make_from_cstr(X) (X), ((X) ? strlen(X) : 0) + +#define util_array_length(__array) sizeof(__array)/sizeof(&__array) +