Index: projects/zfsd/head/cddl/sbin/zfsd/Makefile.common =================================================================== --- projects/zfsd/head/cddl/sbin/zfsd/Makefile.common (revision 289683) +++ projects/zfsd/head/cddl/sbin/zfsd/Makefile.common (revision 289684) @@ -1,44 +1,44 @@ # $FreeBSD$ SRCS= callout.cc \ case_file.cc \ zfsd_event.cc \ vdev.cc \ vdev_iterator.cc \ zfsd.cc \ zfsd_exception.cc \ zpool_list.cc \ zfsd_main.cc NO_MAN= YES WARNS?= 3 # Ignore warnings about Solaris specific pragmas. IGNORE_PRAGMA= YES INCFLAGS+= -I${SRCDIR}/cddl/contrib/opensolaris/lib/libzpool/common INCFLAGS+= -I${SRCDIR}/cddl/compat/opensolaris/include INCFLAGS+= -I${SRCDIR}/cddl/compat/opensolaris/lib/libumem INCFLAGS+= -I${SRCDIR}/sys/cddl/compat/opensolaris INCFLAGS+= -I${SRCDIR}/cddl/contrib/opensolaris/head INCFLAGS+= -I${SRCDIR}/cddl/contrib/opensolaris/lib/libuutil/common INCFLAGS+= -I${SRCDIR}/cddl/contrib/opensolaris/lib/libumem/common INCFLAGS+= -I${SRCDIR}/cddl/contrib/opensolaris/lib/libzfs_core/common INCFLAGS+= -I${SRCDIR}/cddl/contrib/opensolaris/lib/libzfs/common INCFLAGS+= -I${SRCDIR}/cddl/contrib/opensolaris/lib/libnvpair INCFLAGS+= -I${SRCDIR}/sys/cddl/contrib/opensolaris/common/zfs INCFLAGS+= -I${SRCDIR}/sys/cddl/contrib/opensolaris/uts/common INCFLAGS+= -I${SRCDIR}/sys/cddl/contrib/opensolaris/uts/common/fs/zfs INCFLAGS+= -I${SRCDIR}/sys/cddl/contrib/opensolaris/uts/common/sys CFLAGS= -g -DNEED_SOLARIS_BOOLEAN ${INCFLAGS} -DPADD= ${LIBDEVCTL} ${LIBZFS} ${LIBZFS_CORE} ${LIBUTIL} ${LIBGEOM} \ +DPADD= ${LIBDEVDCTL} ${LIBZFS} ${LIBZFS_CORE} ${LIBUTIL} ${LIBGEOM} \ ${LIBBSDXML} ${LIBSBUF} ${LIBNVPAIR} ${LIBUUTIL} -LDADD= -ldevctl -lzfs -lzfs_core -lutil -lgeom -lbsdxml -lsbuf -lnvpair -luutil +LDADD= -ldevdctl -lzfs -lzfs_core -lutil -lgeom -lbsdxml -lsbuf -lnvpair -luutil cscope: find ${.CURDIR} -type f -a \( -name "*.[ch]" -o -name "*.cc" \) \ > ${.CURDIR}/cscope.files cd ${.CURDIR} && cscope -buq ${INCFLAGS} Index: projects/zfsd/head/lib/libdevctl/event.h =================================================================== --- projects/zfsd/head/lib/libdevctl/event.h (revision 289683) +++ projects/zfsd/head/lib/libdevctl/event.h (nonexistent) @@ -1,379 +0,0 @@ -/*- - * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation - * All rights reserved. - * - * 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, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * - * NO WARRANTY - * 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 MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. - * - * Authors: Justin T. Gibbs (Spectra Logic Corporation) - * - * $FreeBSD$ - */ - -/** - * \file devctl_event.h - * - * \brief Class hierarchy used to express events received via - * the devctl API. - */ - -#ifndef _DEVCTL_EVENT_H_ -#define _DEVCTL_EVENT_H_ - -/*============================ Namespace Control =============================*/ -namespace DevCtl -{ - -/*=========================== Forward Declarations ===========================*/ -class EventFactory; - -/*============================= Class Definitions ============================*/ -/*-------------------------------- NVPairMap ---------------------------------*/ -/** - * NVPairMap is a specialization of the standard map STL container. - */ -typedef std::map NVPairMap; - -/*----------------------------------- Event ----------------------------------*/ -/** - * \brief Container for the name => value pairs that comprise the content of - * a device control event. - * - * All name => value data for events can be accessed via the Contains() - * and Value() methods. name => value pairs for data not explicitly - * received as a name => value pair are synthesized during parsing. For - * example, ATTACH and DETACH events have "device-name" and "parent" - * name => value pairs added. - */ -class Event -{ - friend class EventFactory; - -public: - /** Event type */ - enum Type { - /** Generic event notification. */ - NOTIFY = '!', - - /** A driver was not found for this device. */ - NOMATCH = '?', - - /** A bus device instance has been added. */ - ATTACH = '+', - - /** A bus device instance has been removed. */ - DETACH = '-' - }; - - /** - * Factory method type to construct an Event given - * the type of event and an NVPairMap populated from - * the event string received from devd. - */ - typedef Event* (BuildMethod)(Type, NVPairMap &, const std::string &); - - /** Generic Event object factory. */ - static BuildMethod Builder; - - static Event *CreateEvent(const EventFactory &factory, - const std::string &eventString); - - /** - * Provide a user friendly string representation of an - * event type. - * - * \param type The type of event to map to a string. - * - * \return A user friendly string representing the input type. - */ - static const char *TypeToString(Type type); - - /** - * Determine the availability of a name => value pair by name. - * - * \param name The key name to search for in this event instance. - * - * \return true if the specified key is available in this - * event, otherwise false. - */ - bool Contains(const std::string &name) const; - - /** - * \param key The name of the key for which to retrieve its - * associated value. - * - * \return A const reference to the string representing the - * value associated with key. - * - * \note For key's with no registered value, the empty string - * is returned. - */ - const std::string &Value(const std::string &key) const; - - /** - * Get the type of this event instance. - * - * \return The type of this event instance. - */ - Type GetType() const; - - /** - * Get the orginal DevCtl event string for this event. - * - * \return The DevCtl event string. - */ - const std::string &GetEventString() const; - - /** - * Convert the event instance into a string suitable for - * printing to the console or emitting to syslog. - * - * \return A string of formatted event data. - */ - std::string ToString() const; - - /** - * Pretty-print this event instance to cout. - */ - void Print() const; - - /** - * Pretty-print this event instance to syslog. - * - * \param priority The logging priority/facility. - * See syslog(3). - */ - void Log(int priority) const; - - /** - * Create and return a fully independent clone - * of this event. - */ - virtual Event *DeepCopy() const; - - /** Destructor */ - virtual ~Event(); - - /** - * Interpret and perform any actions necessary to - * consume the event. - * - * \return True if this event should be queued for later reevaluation - */ - virtual bool Process() const; - - /** - * Get the time that the event was created - */ - timeval GetTimestamp() const; - - /** - * Add a timestamp to the event string, if one does not already exist - * TODO: make this an instance method that operates on the std::map - * instead of the string. We must fix zfsd's CaseFile serialization - * routines first, so that they don't need the raw event string. - * - * \param[in,out] eventString The devd event string to modify - */ - static void TimestampEventString(std::string &eventString); - - /** - * Access all parsed key => value pairs. - */ - const NVPairMap &GetMap() const; - -protected: - /** Table entries used to map a type to a user friendly string. */ - struct EventTypeRecord - { - Type m_type; - const char *m_typeName; - }; - - /** - * Constructor - * - * \param type The type of event to create. - */ - Event(Type type, NVPairMap &map, const std::string &eventString); - - /** Deep copy constructor. */ - Event(const Event &src); - - /** Always empty string returned when NVPairMap lookups fail. */ - static const std::string s_theEmptyString; - - /** Unsorted table of event types. */ - static EventTypeRecord s_typeTable[]; - - /** The type of this event. */ - const Type m_type; - - /** - * Event attribute storage. - * - * \note Although stored by reference (since m_nvPairs can - * never be NULL), the NVPairMap referenced by this field - * is dynamically allocated and owned by this event object. - * m_nvPairs must be deleted at event desctruction. - */ - NVPairMap &m_nvPairs; - - /** - * The unaltered event string, as received from devd, used to - * create this event object. - */ - std::string m_eventString; - -private: - /** - * Ingest event data from the supplied string. - * - * \param[in] eventString The string of devd event data to parse. - * \param[out] nvpairs Returns the parsed data - */ - static void ParseEventString(Type type, const std::string &eventString, - NVPairMap &nvpairs); -}; - -inline Event::Type -Event::GetType() const -{ - return (m_type); -} - -inline const std::string & -Event::GetEventString() const -{ - return (m_eventString); -} - -inline const NVPairMap & -Event::GetMap() const -{ - return (m_nvPairs); -} - -/*--------------------------------- EventList --------------------------------*/ -/** - * EventList is a specialization of the standard list STL container. - */ -typedef std::list EventList; - -/*-------------------------------- DevfsEvent --------------------------------*/ -class DevfsEvent : public Event -{ -public: - /** Specialized Event object factory for Devfs events. */ - static BuildMethod Builder; - - virtual Event *DeepCopy() const; - - /** - * Interpret and perform any actions necessary to - * consume the event. - * \return True if this event should be queued for later reevaluation - */ - virtual bool Process() const; - - bool IsDiskDev() const; - bool IsWholeDev() const; - bool DevName(std::string &name) const; - bool DevPath(std::string &path) const; - bool PhysicalPath(std::string &path) const; - -protected: - /** - * Determine if the given device name references a potential - * disk device. - * - * \param devName The device name to test. - */ - static bool IsDiskDev(const std::string &devName); - - /** - * Given the device name of a disk, determine if the device - * represents the whole device, not just a partition. - * - * \param devName Device name of disk device to test. - * - * \return True if the device name represents the whole device. - * Otherwise false. - */ - static bool IsWholeDev(const std::string &devName); - - /** DeepCopy Constructor. */ - DevfsEvent(const DevfsEvent &src); - - /** Constructor */ - DevfsEvent(Type, NVPairMap &, const std::string &); -}; - -/*--------------------------------- ZfsEvent ---------------------------------*/ -class ZfsEvent : public Event -{ -public: - /** Specialized Event object factory for ZFS events. */ - static BuildMethod Builder; - - virtual Event *DeepCopy() const; - - const std::string &PoolName() const; - Guid PoolGUID() const; - Guid VdevGUID() const; - -protected: - /** Constructor */ - ZfsEvent(Type, NVPairMap &, const std::string &); - - /** Deep copy constructor. */ - ZfsEvent(const ZfsEvent &src); - - Guid m_poolGUID; - Guid m_vdevGUID; -}; - -//- ZfsEvent Inline Public Methods -------------------------------------------- -inline const std::string& -ZfsEvent::PoolName() const -{ - /* The pool name is reported as the subsystem of ZFS events. */ - return (Value("subsystem")); -} - -inline Guid -ZfsEvent::PoolGUID() const -{ - return (m_poolGUID); -} - -inline Guid -ZfsEvent::VdevGUID() const -{ - return (m_vdevGUID); -} - -} // namespace DevCtl -#endif /*_DEVCTL_EVENT_H_ */ Index: projects/zfsd/head/lib/libdevctl/guid.h =================================================================== --- projects/zfsd/head/lib/libdevctl/guid.h (revision 289683) +++ projects/zfsd/head/lib/libdevctl/guid.h (nonexistent) @@ -1,143 +0,0 @@ -/*- - * Copyright (c) 2012, 2013 Spectra Logic Corporation - * All rights reserved. - * - * 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, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * - * NO WARRANTY - * 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 MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. - * - * Authors: Alan Somers (Spectra Logic Corporation) - * - * $FreeBSD$ - */ - -/** - * \file devctl_guid.h - * - * Definition of the Guid class. - */ -#ifndef _DEVCTL_GUID_H_ -#define _DEVCTL_GUID_H_ - -/*============================ Namespace Control =============================*/ -namespace DevCtl -{ - -/*============================= Class Definitions ============================*/ -/*----------------------------------- Guid -----------------------------------*/ -/** - * \brief Object that represents guids. - * - * It can generally be manipulated as a uint64_t, but with a special - * value INVALID_GUID that does not equal any valid guid. - * - * As of this writing, this class is only used to to represent ZFS - * guids in events and spa_generate_guid() in spa_misc.c explicitly - * refuses to return a guid of 0. So this class uses 0 as the value - * for INVALID_GUID. In the future, if 0 is allowed to be a valid - * guid, the implementation of this class must change. - */ -class Guid -{ -public: - /* Constructors */ - Guid(); - Guid(uint64_t guid); - Guid(const std::string &guid); - - /* Assignment */ - Guid& operator=(const Guid& rhs); - - /* Test the validity of this guid. */ - bool IsValid() const; - - /* Comparison to other Guid operators */ - bool operator==(const Guid& rhs) const; - bool operator!=(const Guid& rhs) const; - - /* Integer conversion operators */ - operator uint64_t() const; - operator bool() const; - - static const uint64_t INVALID_GUID = 0; -protected: - /* The integer value of the GUID. */ - uint64_t m_GUID; -}; - -//- Guid Inline Public Methods ------------------------------------------------ -inline -Guid::Guid() - : m_GUID(INVALID_GUID) -{ -} - -inline -Guid::Guid(uint64_t guid) - : m_GUID(guid) -{ -} - -inline Guid& -Guid::operator=(const Guid &rhs) -{ - m_GUID = rhs.m_GUID; - return (*this); -} - -inline bool -Guid::IsValid() const -{ - return (m_GUID != INVALID_GUID); -} - -inline bool -Guid::operator==(const Guid& rhs) const -{ - return (m_GUID == rhs.m_GUID); -} - -inline bool -Guid::operator!=(const Guid& rhs) const -{ - return (m_GUID != rhs.m_GUID); -} - -inline -Guid::operator uint64_t() const -{ - return (m_GUID); -} - -inline -Guid::operator bool() const -{ - return (m_GUID != INVALID_GUID); -} - -/** Convert the GUID into its string representation */ -std::ostream& operator<< (std::ostream& out, Guid g); - -} // namespace DevCtl -#endif /* _DEVCTL_GUID_H_ */ Index: projects/zfsd/head/lib/libdevctl/reader.cc =================================================================== --- projects/zfsd/head/lib/libdevctl/reader.cc (revision 289683) +++ projects/zfsd/head/lib/libdevctl/reader.cc (nonexistent) @@ -1,99 +0,0 @@ -/*- - * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation - * All rights reserved. - * - * 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, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * - * NO WARRANTY - * 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 MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. - * - * Authors: Alan Somers (Spectra Logic Corporation) - */ - -/** - * \file reader.cc - */ - -#include -#include - -#include -#include -#include -#include - -#include - -#include "reader.h" - -__FBSDID("$FreeBSD$"); - -/*============================ Namespace Control =============================*/ -namespace DevCtl -{ - -//- FDReader Public Methods --------------------------------------------------- -FDReader::FDReader(int fd) - : m_fd(fd) -{ -} - -ssize_t -FDReader::read(char* buf, size_t count) -{ - return (::read(m_fd, buf, count)); -} - -ssize_t -FDReader::in_avail() const -{ - int bytes; - if (ioctl(m_fd, FIONREAD, &bytes)) { - syslog(LOG_ERR, "ioctl FIONREAD: %s", strerror(errno)); - return (-1); - } - return (bytes); -} - -//- IstreamReader Inline Public Methods ---------------------------------------- -IstreamReader::IstreamReader(std::istream* stream) - : m_stream(stream) -{ -} - -ssize_t -IstreamReader::read(char* buf, size_t count) -{ - m_stream->read(buf, count); - if (m_stream->fail()) - return (-1); - return (m_stream->gcount()); -} - -ssize_t -IstreamReader::in_avail() const -{ - return (m_stream->rdbuf()->in_avail()); -} - -} // namespace DevCtl Index: projects/zfsd/head/lib/libdevctl/event_factory.cc =================================================================== --- projects/zfsd/head/lib/libdevctl/event_factory.cc (revision 289683) +++ projects/zfsd/head/lib/libdevctl/event_factory.cc (nonexistent) @@ -1,99 +0,0 @@ -/*- - * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation - * All rights reserved. - * - * 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, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * - * NO WARRANTY - * 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 MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. - * - * Authors: Justin T. Gibbs (Spectra Logic Corporation) - */ - -/** - * \file event_factory.cc - */ -#include -#include - -#include -#include -#include - -#include "guid.h" -#include "event.h" -#include "event_factory.h" - -__FBSDID("$FreeBSD$"); - -/*================================== Macros ==================================*/ -#define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*x)) - -/*============================ Namespace Control =============================*/ -namespace DevCtl -{ - -/*=========================== Class Implementations ==========================*/ -/*------------------------------- EventFactory -------------------------------*/ -//- Event Public Methods ------------------------------------------------------- -EventFactory::EventFactory(Event::BuildMethod *defaultBuildMethod) - : m_defaultBuildMethod(defaultBuildMethod) -{ -} - -void -EventFactory::UpdateRegistry(Record regEntries[], size_t numEntries) -{ - EventFactory::Record *rec(regEntries); - EventFactory::Record *lastRec(rec + numEntries - 1); - - for (; rec <= lastRec; rec++) { - Key key(rec->m_type, rec->m_subsystem); - - if (rec->m_buildMethod == NULL) - m_registry.erase(key); - else - m_registry[key] = rec->m_buildMethod; - } -} - -Event * -EventFactory::Build(Event::Type type, NVPairMap &nvpairs, - const std::string eventString) const -{ - Key key(type, nvpairs["system"]); - Event::BuildMethod *buildMethod(m_defaultBuildMethod); - - Registry::const_iterator foundMethod(m_registry.find(key)); - if (foundMethod != m_registry.end()) - buildMethod = foundMethod->second; - - if (buildMethod == NULL) { - delete &nvpairs; - return (NULL); - } - - return (buildMethod(type, nvpairs, eventString)); -} - -} // namespace DevCtl Index: projects/zfsd/head/lib/libdevctl/consumer.cc =================================================================== --- projects/zfsd/head/lib/libdevctl/consumer.cc (revision 289683) +++ projects/zfsd/head/lib/libdevctl/consumer.cc (nonexistent) @@ -1,258 +0,0 @@ -/*- - * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation - * All rights reserved. - * - * 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, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * - * NO WARRANTY - * 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 MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. - * - * Authors: Justin T. Gibbs (Spectra Logic Corporation) - */ - -/** - * \file consumer.cc - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "guid.h" -#include "event.h" -#include "event_factory.h" -#include "exception.h" - -#include "consumer.h" - -__FBSDID("$FreeBSD$"); - -/*================================== Macros ==================================*/ -#define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*x)) - -/*============================ Namespace Control =============================*/ -using std::string; -namespace DevCtl -{ - -/*============================= Class Definitions ============================*/ -/*----------------------------- DevCtl::Consumer -----------------------------*/ -//- Consumer Static Private Data ----------------------------------------------- -const char Consumer::s_devdSockPath[] = "/var/run/devd.seqpacket.pipe"; - -//- Consumer Public Methods ---------------------------------------------------- -Consumer::Consumer(Event::BuildMethod *defBuilder, - EventFactory::Record *regEntries, - size_t numEntries) - : m_devdSockFD(-1), - m_eventFactory(defBuilder), - m_replayingEvents(false) -{ - m_eventFactory.UpdateRegistry(regEntries, numEntries); -} - -Consumer::~Consumer() -{ - DisconnectFromDevd(); -} - -bool -Consumer::ConnectToDevd() -{ - struct sockaddr_un devdAddr; - int sLen; - int result; - - if (m_devdSockFD != -1) { - /* Already connected. */ - syslog(LOG_DEBUG, "%s: Already connected.", __func__); - return (true); - } - syslog(LOG_INFO, "%s: Connecting to devd.", __func__); - - memset(&devdAddr, 0, sizeof(devdAddr)); - devdAddr.sun_family= AF_UNIX; - strlcpy(devdAddr.sun_path, s_devdSockPath, sizeof(devdAddr.sun_path)); - sLen = SUN_LEN(&devdAddr); - - m_devdSockFD = socket(AF_UNIX, SOCK_SEQPACKET, 0); - if (m_devdSockFD == -1) - err(1, "Unable to create socket"); - if (fcntl(m_devdSockFD, F_SETFL, O_NONBLOCK) < 0) - err(1, "fcntl"); - result = connect(m_devdSockFD, - reinterpret_cast(&devdAddr), - sLen); - if (result == -1) { - syslog(LOG_INFO, "Unable to connect to devd"); - DisconnectFromDevd(); - return (false); - } - - syslog(LOG_INFO, "Connection to devd successful"); - return (true); -} - -void -Consumer::DisconnectFromDevd() -{ - if (m_devdSockFD != -1) - syslog(LOG_INFO, "Disconnecting from devd."); - - close(m_devdSockFD); - m_devdSockFD = -1; -} - -std::string -Consumer::ReadEvent() -{ - char buf[MAX_EVENT_SIZE + 1]; - ssize_t len; - - len = ::recv(m_devdSockFD, buf, MAX_EVENT_SIZE, MSG_WAITALL); - if (len == -1) - return (std::string("")); - else { - /* NULL-terminate the result */ - buf[len] = '\0'; - return (std::string(buf)); - } -} - -void -Consumer::ReplayUnconsumedEvents(bool discardUnconsumed) -{ - EventList::iterator event(m_unconsumedEvents.begin()); - bool replayed_any = (event != m_unconsumedEvents.end()); - - m_replayingEvents = true; - if (replayed_any) - syslog(LOG_INFO, "Started replaying unconsumed events"); - while (event != m_unconsumedEvents.end()) { - bool consumed((*event)->Process()); - if (consumed || discardUnconsumed) { - delete *event; - event = m_unconsumedEvents.erase(event); - } else { - event++; - } - } - if (replayed_any) - syslog(LOG_INFO, "Finished replaying unconsumed events"); - m_replayingEvents = false; -} - -bool -Consumer::SaveEvent(const Event &event) -{ - if (m_replayingEvents) - return (false); - m_unconsumedEvents.push_back(event.DeepCopy()); - return (true); -} - -Event * -Consumer::NextEvent() -{ - if (!Connected()) - return(NULL); - - Event *event(NULL); - try { - string evString; - - evString = ReadEvent(); - if (! evString.empty()) { - Event::TimestampEventString(evString); - event = Event::CreateEvent(m_eventFactory, evString); - } - } catch (const Exception &exp) { - exp.Log(); - DisconnectFromDevd(); - } - return (event); -} - -/* Capture and process buffered events. */ -void -Consumer::ProcessEvents() -{ - Event *event; - while ((event = NextEvent()) != NULL) { - if (event->Process()) - SaveEvent(*event); - delete event; - } -} - -void -Consumer::FlushEvents() -{ - std::string s; - - do - s = ReadEvent(); - while (! s.empty()) ; -} - -bool -Consumer::EventsPending() -{ - struct pollfd fds[1]; - int result; - - do { - fds->fd = m_devdSockFD; - fds->events = POLLIN; - fds->revents = 0; - result = poll(fds, NUM_ELEMENTS(fds), /*timeout*/0); - } while (result == -1 && errno == EINTR); - - if (result == -1) - err(1, "Polling for devd events failed"); - - if ((fds->revents & POLLERR) != 0) - throw Exception("Consumer::EventsPending(): " - "POLLERR detected on devd socket."); - - if ((fds->revents & POLLHUP) != 0) - throw Exception("Consumer::EventsPending(): " - "POLLHUP detected on devd socket."); - - return ((fds->revents & POLLIN) != 0); -} - -} // namespace DevCtl Index: projects/zfsd/head/lib/libdevctl/consumer.h =================================================================== --- projects/zfsd/head/lib/libdevctl/consumer.h (revision 289683) +++ projects/zfsd/head/lib/libdevctl/consumer.h (nonexistent) @@ -1,186 +0,0 @@ -/*- - * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation - * All rights reserved. - * - * 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, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * - * NO WARRANTY - * 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 MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. - * - * Authors: Justin T. Gibbs (Spectra Logic Corporation) - * - * $FreeBSD$ - */ - -/** - * \file devctl_consumer.h - */ -#ifndef _DEVCTL_CONSUMER_H_ -#define _DEVCTL_CONSUMER_H_ - -/*============================ Namespace Control =============================*/ -namespace DevCtl -{ - -/*=========================== Forward Declarations ===========================*/ -class Event; -class EventBuffer; -class FDReader; - -/*============================ Class Declarations ============================*/ -/*----------------------------- DevCtl::Consumer -----------------------------*/ - -/** - */ -class Consumer -{ -public: - Consumer(Event::BuildMethod *defBuilder = NULL, - EventFactory::Record *regEntries = NULL, - size_t numEntries = 0); - virtual ~Consumer(); - - bool Connected() const; - - /** - * Return file descriptor useful for client's wishing to poll(2) - * for new events. - */ - int GetPollFd(); - - /** - * Queue an event for deferred processing or replay. - */ - bool SaveEvent(const Event &event); - - /** - * Reprocess any events saved via the SaveEvent() facility. - * - * \param discardUnconsumed If true, events that are not conumed - * during replay are discarded. - */ - void ReplayUnconsumedEvents(bool discardUnconsumed); - - /** Return an event, if one is available. */ - Event *NextEvent(); - - /** - * Extract events and invoke each event's Process method. - */ - void ProcessEvents(); - - /** Discard all data pending in m_devdSockFD. */ - void FlushEvents(); - - /** - * Test for data pending in m_devdSockFD - * - * \return True if data is pending. Otherwise false. - */ - bool EventsPending(); - - /** - * Open a connection to devd's unix domain socket. - * - * \return True if the connection attempt is successsful. Otherwise - * false. - */ - bool ConnectToDevd(); - - /** - * Close a connection (if any) to devd's unix domain socket. - */ - void DisconnectFromDevd(); - - EventFactory GetFactory(); - -protected: - /** - * \brief Reads the most recent record - * - * On error, "" is returned, and errno will be set by the OS - * - * \returns A string containing the record - */ - std::string ReadEvent(); - - enum { - /* - * The maximum event size supported by libdevctl. - */ - MAX_EVENT_SIZE = 8192, - }; - - static const char s_devdSockPath[]; - - /** - * File descriptor representing the unix domain socket - * connection with devd. - */ - int m_devdSockFD; - - /** - * Reader tied to the devd socket. - */ - FDReader *m_reader; - - /** - * Default EventBuffer connected to m_reader. - */ - EventBuffer *m_eventBuffer; - - EventFactory m_eventFactory; - - /** Queued events for replay. */ - EventList m_unconsumedEvents; - - /** - * Flag controlling whether events can be queued. This boolean - * is set during event replay to ensure that previosuly deferred - * events are not requeued and thus retained forever. - */ - bool m_replayingEvents; -}; - -//- Consumer Const Public Inline Methods --------------------------------------- -inline bool -Consumer::Connected() const -{ - return (m_devdSockFD != -1); -} - -//- Consumer Public Inline Methods --------------------------------------------- -inline int -Consumer::GetPollFd() -{ - return (m_devdSockFD); -} - -inline EventFactory -Consumer::GetFactory() -{ - return (m_eventFactory); -} - -} // namespace DevCtl -#endif /* _DEVCTL_CONSUMER_H_ */ Index: projects/zfsd/head/lib/libdevctl/event_factory.h =================================================================== --- projects/zfsd/head/lib/libdevctl/event_factory.h (revision 289683) +++ projects/zfsd/head/lib/libdevctl/event_factory.h (nonexistent) @@ -1,94 +0,0 @@ -/*- - * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation - * All rights reserved. - * - * 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, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * - * NO WARRANTY - * 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 MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. - * - * Authors: Justin T. Gibbs (Spectra Logic Corporation) - * - * $FreeBSD$ - */ - -/** - * \file devctl_event_factory.h - */ - -#ifndef _DEVCTL_EVENT_FACTORY_H_ -#define _DEVCTL_EVENT_FACTORY_H_ - -/*============================ Namespace Control =============================*/ -namespace DevCtl -{ - -/*============================= Class Definitions ============================*/ -/*------------------------------- EventFactory -------------------------------*/ -/** - * \brief Container for "event type" => "event object" creaction methods. - */ -class EventFactory -{ -public: - /** - * Event creation handlers are matched by event type and a - * string representing the system emitting the event. - */ - typedef std::pair Key; - - /** Map type for Factory method lookups. */ - typedef std::map Registry; - - /** Table record of factory methods to add to our registry. */ - struct Record - { - Event::Type m_type; - const char *m_subsystem; - Event::BuildMethod *m_buildMethod; - }; - - const Registry &GetRegistry() const; - Event *Build(Event::Type type, NVPairMap &nvpairs, - const std::string eventString) const; - - EventFactory(Event::BuildMethod *defaultBuildMethod = NULL); - - void UpdateRegistry(Record regEntries[], size_t numEntries); - - -protected: - /** Registry of event factory methods providing O(log(n)) lookup. */ - Registry m_registry; - - Event::BuildMethod *m_defaultBuildMethod; -}; - -inline const EventFactory::Registry & -EventFactory::GetRegistry() const -{ - return (m_registry); -} - -} // namespace DevCtl -#endif /*_DEVCTL_EVENT_FACTORY_H_ */ Index: projects/zfsd/head/lib/libdevctl/event_buffer.cc =================================================================== --- projects/zfsd/head/lib/libdevctl/event_buffer.cc (revision 289683) +++ projects/zfsd/head/lib/libdevctl/event_buffer.cc (nonexistent) @@ -1,216 +0,0 @@ -/*- - * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation - * All rights reserved. - * - * 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, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * - * NO WARRANTY - * 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 MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. - * - * Authors: Justin T. Gibbs (Spectra Logic Corporation) - */ - -/** - * \file event_buffer.cc - */ - -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include "event_buffer.h" -#include "exception.h" -#include "reader.h" - -__FBSDID("$FreeBSD$"); - -/*============================ Namespace Control =============================*/ -using std::string; -using std::stringstream; -namespace DevCtl -{ - -/*============================= Class Definitions ============================*/ -/*-------------------------------- EventBuffer -------------------------------*/ -//- EventBuffer Static Data ---------------------------------------------------- -/** - * NOTIFY, NOMATCH, ATTACH, DETACH. See DevCtlEvent::Type. - */ -const char EventBuffer::s_eventStartTokens[] = "!?+-"; - -/** - * Events are terminated by a newline. - */ -const char EventBuffer::s_eventEndTokens[] = "\n"; - -/** - * Key=Value pairs are terminated by whitespace. - */ -const char EventBuffer::s_keyPairSepTokens[] = " \t\n"; - -//- EventBuffer Public Methods ------------------------------------------------- -EventBuffer::EventBuffer(Reader& reader) - : m_reader(reader), - m_validLen(0), - m_parsedLen(0), - m_nextEventOffset(0), - m_synchronized(true) -{ -} - -bool -EventBuffer::ExtractEvent(string &eventString) -{ - stringstream tsField; - timeval now; - - gettimeofday(&now, NULL); - tsField << " timestamp=" << now.tv_sec; - - while (UnParsed() > 0 || Fill()) { - - /* - * If the valid data in the buffer isn't enough to hold - * a full event, try reading more. - */ - if (NextEventMaxLen() < MIN_EVENT_SIZE) { - m_parsedLen += UnParsed(); - continue; - } - - char *nextEvent(m_buf + m_nextEventOffset); - bool truncated(true); - size_t eventLen(strcspn(nextEvent, s_eventEndTokens)); - - if (!m_synchronized) { - /* Discard data until an end token is read. */ - if (nextEvent[eventLen] != '\0') - m_synchronized = true; - m_nextEventOffset += eventLen; - m_parsedLen = m_nextEventOffset; - continue; - } else if (nextEvent[eventLen] == '\0') { - - m_parsedLen += eventLen; - if (m_parsedLen < MAX_EVENT_SIZE) { - /* - * Ran out of buffer before hitting - * a full event. Fill() and try again. - */ - continue; - } - syslog(LOG_WARNING, "Overran event buffer\n\tm_nextEventOffset" - "=%zd\n\tm_parsedLen=%zd\n\tm_validLen=%zd", - m_nextEventOffset, m_parsedLen, m_validLen); - } else { - /* - * Include the normal terminator in the extracted - * event data. - */ - eventLen += 1; - truncated = false; - } - - m_nextEventOffset += eventLen; - m_parsedLen = m_nextEventOffset; - eventString.assign(nextEvent, eventLen); - - if (truncated) { - size_t fieldEnd; - - /* Break cleanly at the end of a key<=>value pair. */ - fieldEnd = eventString.find_last_of(s_keyPairSepTokens); - if (fieldEnd != string::npos) - eventString.erase(fieldEnd); - eventString += '\n'; - - m_synchronized = false; - syslog(LOG_WARNING, - "Truncated %zd characters from event.", - eventLen - fieldEnd); - } - - /* - * Add a timestamp as the final field of the event if it is - * not already present. - */ - if (eventString.find("timestamp=") == string::npos) { - size_t eventEnd(eventString.find_last_not_of('\n') + 1); - - eventString.insert(eventEnd, tsField.str()); - } - - return (true); - } - return (false); -} - -//- EventBuffer Private Methods ------------------------------------------------ -bool -EventBuffer::Fill() -{ - ssize_t avail; - ssize_t consumed(0); - - /* Compact the buffer. */ - if (m_nextEventOffset != 0) { - memmove(m_buf, m_buf + m_nextEventOffset, - m_validLen - m_nextEventOffset); - m_validLen -= m_nextEventOffset; - m_parsedLen -= m_nextEventOffset; - m_nextEventOffset = 0; - } - - /* Fill any empty space. */ - avail = m_reader.in_avail(); - if (avail > 0) { - size_t want; - - want = std::min((size_t)avail, MAX_READ_SIZE - m_validLen); - consumed = m_reader.read(m_buf + m_validLen, want); - if (consumed == -1) { - if (errno == EINTR) - return (false); - else - err(1, "EventBuffer::Fill(): Read failed"); - } - } else if (avail == -1) { - throw Exception("EventBuffer::Fill(): Reader disconnected"); - } - - m_validLen += consumed; - /* Guarantee our buffer is always NUL terminated. */ - m_buf[m_validLen] = '\0'; - - return (consumed > 0); -} - -} // namespace DevCtl Index: projects/zfsd/head/lib/libdevctl/exception.cc =================================================================== --- projects/zfsd/head/lib/libdevctl/exception.cc (revision 289683) +++ projects/zfsd/head/lib/libdevctl/exception.cc (nonexistent) @@ -1,125 +0,0 @@ -/*- - * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation - * All rights reserved. - * - * 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, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * - * NO WARRANTY - * 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 MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. - * - * Authors: Justin T. Gibbs (Spectra Logic Corporation) - */ - -/** - * \file exception.cc - */ -#include - -#include - -#include -#include -#include -#include - -#include "exception.h" - -__FBSDID("$FreeBSD$"); - -/*============================ Namespace Control =============================*/ -using std::string; -using std::stringstream; -using std::endl; -namespace DevCtl -{ - -/*=========================== Class Implementations ==========================*/ -/*--------------------------------- Exception --------------------------------*/ -void -Exception::FormatLog(const char *fmt, va_list ap) -{ - char buf[256]; - - vsnprintf(buf, sizeof(buf), fmt, ap); - m_log = buf; -} - -Exception::Exception(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - FormatLog(fmt, ap); - va_end(ap); -} - -Exception::Exception() -{ -} - -void -Exception::Log() const -{ - syslog(LOG_ERR, "%s", m_log.c_str()); -} - -/*------------------------------ ParseException ------------------------------*/ -//- ParseException Inline Public Methods --------------------------------------- -ParseException::ParseException(Type type, const std::string &parsedBuffer, - size_t offset) - : Exception(), - m_type(type), - m_parsedBuffer(parsedBuffer), - m_offset(offset) -{ - stringstream logstream; - - logstream << "Parsing "; - - switch (Type()) { - case INVALID_FORMAT: - logstream << "invalid format "; - break; - case DISCARDED_EVENT_TYPE: - logstream << "discarded event "; - break; - case UNKNOWN_EVENT_TYPE: - logstream << "unknown event "; - break; - default: - break; - } - logstream << "exception on buffer: \'"; - if (GetOffset() == 0) { - logstream << m_parsedBuffer << '\'' << endl; - } else { - string markedBuffer(m_parsedBuffer); - - markedBuffer.insert(GetOffset(), ""); - logstream << markedBuffer << '\'' << endl; - } - - GetString() = logstream.str(); -} - -} // namespace DevCtl Index: projects/zfsd/head/lib/libdevctl/event_buffer.h =================================================================== --- projects/zfsd/head/lib/libdevctl/event_buffer.h (revision 289683) +++ projects/zfsd/head/lib/libdevctl/event_buffer.h (nonexistent) @@ -1,188 +0,0 @@ -/*- - * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation - * All rights reserved. - * - * 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, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * - * NO WARRANTY - * 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 MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. - * - * Authors: Justin T. Gibbs (Spectra Logic Corporation) - * - * $FreeBSD$ - */ - -/** - * \file devctl_event_buffer.h - */ -#ifndef _DEVCTL_EVENT_BUFFER_H_ -#define _DEVCTL_EVENT_BUFFER_H_ - -/*============================ Namespace Control =============================*/ -namespace DevCtl -{ - -/*=========================== Forward Declarations ===========================*/ -class Reader; - -/*============================= Class Definitions ============================*/ -/*-------------------------------- EventBuffer -------------------------------*/ -/** - * \brief Class buffering event data from Devd or a similar source and - * splitting it into individual event strings. - * - * Users of this class initialize it with a Reader associated with the unix - * domain socket connection with devd or a compatible source. The lifetime of - * an EventBuffer instance should match that of the Reader passed to it. This - * is required as data from partially received events is retained in the - * EventBuffer in order to allow reconstruction of these events across multiple - * reads of the stream. - * - * Once the program determines that the Reader is ready for reading, the - * EventBuffer::ExtractEvent() should be called in a loop until the method - * returns false. - */ -class EventBuffer -{ -public: - /** - * Constructor - * - * \param reader The data source on which to buffer/parse event data. - */ - EventBuffer(Reader& reader); - - /** - * Pull a single event string out of the event buffer. - * - * \param eventString The extracted event data (if available). - * - * \return true if event data is available and eventString has - * been populated. Otherwise false. - */ - bool ExtractEvent(std::string &eventString); - -private: - enum { - /** - * Size of an empty event (start and end token with - * no data. The EventBuffer parsing needs at least - * this much data in the buffer for safe event extraction. - */ - MIN_EVENT_SIZE = 2, - - /* - * The maximum event size supported by ZFSD. - * Events larger than this size (minus 1) are - * truncated at the end of the last fully received - * key/value pair. - */ - MAX_EVENT_SIZE = 8192, - - /** - * The maximum amount of buffer data to read at - * a single time from the Devd file descriptor. - */ - MAX_READ_SIZE = MAX_EVENT_SIZE, - - /** - * The size of EventBuffer's buffer of Devd event data. - * This is one larger than the maximum supported event - * size, which alows us to always include a terminating - * NUL without overwriting any received data. - */ - EVENT_BUFSIZE = MAX_EVENT_SIZE + /*NUL*/1 - }; - - /** The amount of data in m_buf we have yet to look at. */ - size_t UnParsed() const; - - /** The amount of data in m_buf available for the next event. */ - size_t NextEventMaxLen() const; - - /** Fill the event buffer with event data from Devd. */ - bool Fill(); - - /** Characters we treat as beginning an event string. */ - static const char s_eventStartTokens[]; - - /** Characters we treat as ending an event string. */ - static const char s_eventEndTokens[]; - - /** Characters found between successive "key=value" strings. */ - static const char s_keyPairSepTokens[]; - - /** Temporary space for event data during our parsing. Laid out like - * this: - * <---------------------------------------------------------> - * | | | | | - * m_buf---| | | | | - * m_nextEventOffset-- | | | - * m_parsedLen------------- | | - * m_validLen-------------------------- | - * EVENT_BUFSIZE------------------------------------------------------ - * - * Data before m_nextEventOffset has already been processed. - * - * Data between m_nextEvenOffset and m_parsedLen has been parsed, but - * not processed as a single event. - * - * Data between m_parsedLen and m_validLen has been read from the - * source, but not yet parsed. - * - * Between m_validLen and EVENT_BUFSIZE is empty space. - * - * */ - char m_buf[EVENT_BUFSIZE]; - - /** Reference to the reader linked to devd's domain socket. */ - Reader& m_reader; - - /** Offset within m_buf to the beginning of free space. */ - size_t m_validLen; - - /** Offset within m_buf to the beginning of data not yet parsed */ - size_t m_parsedLen; - - /** Offset within m_buf to the start token of the next event. */ - size_t m_nextEventOffset; - - /** The EventBuffer is aligned and tracking event records. */ - bool m_synchronized; -}; - -//- EventBuffer Inline Private Methods ----------------------------------------- -inline size_t -EventBuffer::UnParsed() const -{ - return (m_validLen - m_parsedLen); -} - -inline size_t -EventBuffer::NextEventMaxLen() const -{ - return (m_validLen - m_nextEventOffset); -} - -} // namespace DevCtl -#endif /* _DEVCTL_EVENT_BUFFER_H_ */ Index: projects/zfsd/head/lib/libdevctl/event.cc =================================================================== --- projects/zfsd/head/lib/libdevctl/event.cc (revision 289683) +++ projects/zfsd/head/lib/libdevctl/event.cc (nonexistent) @@ -1,557 +0,0 @@ -/*- - * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation - * All rights reserved. - * - * 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, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * - * NO WARRANTY - * 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 MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. - * - * Authors: Justin T. Gibbs (Spectra Logic Corporation) - */ - -/** - * \file event.cc - * - * Implementation of the class hierarchy used to express events - * received via the devctl API. - */ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "guid.h" -#include "event.h" -#include "event_factory.h" -#include "exception.h" - -__FBSDID("$FreeBSD$"); - -/*================================== Macros ==================================*/ -#define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*x)) - -/*============================ Namespace Control =============================*/ -using std::cout; -using std::endl; -using std::string; -using std::stringstream; - -namespace DevCtl -{ - -/*=========================== Class Implementations ==========================*/ -/*----------------------------------- Event ----------------------------------*/ -//- Event Static Protected Data ------------------------------------------------ -const string Event::s_theEmptyString; - -Event::EventTypeRecord Event::s_typeTable[] = -{ - { Event::NOTIFY, "Notify" }, - { Event::NOMATCH, "No Driver Match" }, - { Event::ATTACH, "Attach" }, - { Event::DETACH, "Detach" } -}; - -//- Event Static Public Methods ------------------------------------------------ -Event * -Event::Builder(Event::Type type, NVPairMap &nvPairs, - const string &eventString) -{ - return (new Event(type, nvPairs, eventString)); -} - -Event * -Event::CreateEvent(const EventFactory &factory, const string &eventString) -{ - NVPairMap &nvpairs(*new NVPairMap); - Type type(static_cast(eventString[0])); - - try { - ParseEventString(type, eventString, nvpairs); - } catch (const ParseException &exp) { - if (exp.GetType() == ParseException::INVALID_FORMAT) - exp.Log(); - return (NULL); - } - - /* - * Allow entries in our table for events with no system specified. - * These entries should specify the string "none". - */ - NVPairMap::iterator system_item(nvpairs.find("system")); - if (system_item == nvpairs.end()) - nvpairs["system"] = "none"; - - return (factory.Build(type, nvpairs, eventString)); -} - -const char * -Event::TypeToString(Event::Type type) -{ - EventTypeRecord *rec(s_typeTable); - EventTypeRecord *lastRec(s_typeTable + NUM_ELEMENTS(s_typeTable) - 1); - - for (; rec <= lastRec; rec++) { - if (rec->m_type == type) - return (rec->m_typeName); - } - return ("Unknown"); -} - -//- Event Public Methods ------------------------------------------------------- -const string & -Event::Value(const string &varName) const -{ - NVPairMap::const_iterator item(m_nvPairs.find(varName)); - if (item == m_nvPairs.end()) - return (s_theEmptyString); - - return (item->second); -} - -bool -Event::Contains(const string &varName) const -{ - return (m_nvPairs.find(varName) != m_nvPairs.end()); -} - -string -Event::ToString() const -{ - stringstream result; - - NVPairMap::const_iterator devName(m_nvPairs.find("device-name")); - if (devName != m_nvPairs.end()) - result << devName->second << ": "; - - NVPairMap::const_iterator systemName(m_nvPairs.find("system")); - if (systemName != m_nvPairs.end() - && systemName->second != "none") - result << systemName->second << ": "; - - result << TypeToString(GetType()) << ' '; - - for (NVPairMap::const_iterator curVar = m_nvPairs.begin(); - curVar != m_nvPairs.end(); curVar++) { - if (curVar == devName || curVar == systemName) - continue; - - result << ' ' - << curVar->first << "=" << curVar->second; - } - result << endl; - - return (result.str()); -} - -void -Event::Print() const -{ - cout << ToString() << std::flush; -} - -void -Event::Log(int priority) const -{ - syslog(priority, "%s", ToString().c_str()); -} - -//- Event Virtual Public Methods ----------------------------------------------- -Event::~Event() -{ - delete &m_nvPairs; -} - -Event * -Event::DeepCopy() const -{ - return (new Event(*this)); -} - -bool -Event::Process() const -{ - return (false); -} - -timeval -Event::GetTimestamp() const -{ - timeval tv_timestamp; - struct tm tm_timestamp; - - if (!Contains("timestamp")) { - throw Exception("Event contains no timestamp: %s", - m_eventString.c_str()); - } - strptime(Value(string("timestamp")).c_str(), "%s", &tm_timestamp); - tv_timestamp.tv_sec = mktime(&tm_timestamp); - tv_timestamp.tv_usec = 0; - return (tv_timestamp); -} - - -//- Event Protected Methods ---------------------------------------------------- -Event::Event(Type type, NVPairMap &map, const string &eventString) - : m_type(type), - m_nvPairs(map), - m_eventString(eventString) -{ -} - -Event::Event(const Event &src) - : m_type(src.m_type), - m_nvPairs(*new NVPairMap(src.m_nvPairs)), - m_eventString(src.m_eventString) -{ -} - -void -Event::ParseEventString(Event::Type type, - const string &eventString, - NVPairMap& nvpairs) -{ - size_t start; - size_t end; - - switch (type) { - case ATTACH: - case DETACH: - - /* - * \ - * at \ - * on - * - * Handle all data that doesn't conform to the - * "name=value" format, and let the generic parser - * below handle the rest. - * - * Type is a single char. Skip it. - */ - start = 1; - end = eventString.find_first_of(" \t\n", start); - if (end == string::npos) - throw ParseException(ParseException::INVALID_FORMAT, - eventString, start); - - nvpairs["device-name"] = eventString.substr(start, end - start); - - start = eventString.find(" on ", end); - if (end == string::npos) - throw ParseException(ParseException::INVALID_FORMAT, - eventString, start); - start += 4; - end = eventString.find_first_of(" \t\n", start); - nvpairs["parent"] = eventString.substr(start, end); - break; - case NOTIFY: - break; - case NOMATCH: - throw ParseException(ParseException::DISCARDED_EVENT_TYPE, - eventString); - default: - throw ParseException(ParseException::UNKNOWN_EVENT_TYPE, - eventString); - } - - /* Process common "key=value" format. */ - for (start = 1; start < eventString.length(); start = end + 1) { - - /* Find the '=' in the middle of the key/value pair. */ - end = eventString.find('=', start); - if (end == string::npos) - break; - - /* - * Find the start of the key by backing up until - * we hit whitespace or '!' (event type "notice"). - * Due to the devctl format, all key/value pair must - * start with one of these two characters. - */ - start = eventString.find_last_of("! \t\n", end); - if (start == string::npos) - throw ParseException(ParseException::INVALID_FORMAT, - eventString, end); - start++; - string key(eventString.substr(start, end - start)); - - /* - * Walk forward from the '=' until either we exhaust - * the buffer or we hit whitespace. - */ - start = end + 1; - if (start >= eventString.length()) - throw ParseException(ParseException::INVALID_FORMAT, - eventString, end); - end = eventString.find_first_of(" \t\n", start); - if (end == string::npos) - end = eventString.length() - 1; - string value(eventString.substr(start, end - start)); - - nvpairs[key] = value; - } -} - -void -Event::TimestampEventString(std::string &eventString) -{ - if (eventString.size() > 0) { - /* - * Add a timestamp as the final field of the event if it is - * not already present. - */ - if (eventString.find("timestamp=") == string::npos) { - const size_t bufsize = 32; // Long enough for a 64-bit int - timeval now; - struct tm* time_s; - char timebuf[bufsize]; - - size_t eventEnd(eventString.find_last_not_of('\n') + 1); - if (gettimeofday(&now, NULL) != 0) - err(1, "gettimeofday"); - time_s = gmtime(&now.tv_sec); - strftime(timebuf, bufsize, " timestamp=%s", time_s); - eventString.insert(eventEnd, timebuf); - } - } -} - -/*-------------------------------- DevfsEvent --------------------------------*/ -//- DevfsEvent Static Public Methods ------------------------------------------- -Event * -DevfsEvent::Builder(Event::Type type, NVPairMap &nvPairs, - const string &eventString) -{ - return (new DevfsEvent(type, nvPairs, eventString)); -} - -//- DevfsEvent Static Protected Methods ---------------------------------------- -bool -DevfsEvent::IsDiskDev(const string &devName) -{ - static const char *diskDevNames[] = - { - "da", - "ada" - }; - - const char **diskName(diskDevNames); - const char **lastDiskName(diskDevNames - + NUM_ELEMENTS(diskDevNames) - 1); - size_t find_start = devName.rfind('/'); - if (find_start == string::npos) { - find_start = 0; - } else { - /* Just after the last '/'. */ - find_start++; - } - - for (; diskName <= lastDiskName; diskName++) { - - size_t loc(devName.find(*diskName, find_start)); - if (loc == find_start) { - size_t prefixLen(strlen(*diskName)); - - if (devName.length() - find_start >= prefixLen - && isdigit(devName[find_start + prefixLen])) - return (true); - } - } - - return (false); -} - -bool -DevfsEvent::IsWholeDev(const string &devName) -{ - string::const_iterator i(devName.begin()); - - size_t start = devName.rfind('/'); - if (start == string::npos) { - start = 0; - } else { - /* Just after the last '/'. */ - start++; - } - i += start; - - /* alpha prefix followed only by digits. */ - for (; i < devName.end() && !isdigit(*i); i++) - ; - - if (i == devName.end()) - return (false); - - for (; i < devName.end() && isdigit(*i); i++) - ; - - return (i == devName.end()); -} - -//- DevfsEvent Virtual Public Methods ------------------------------------------ -Event * -DevfsEvent::DeepCopy() const -{ - return (new DevfsEvent(*this)); -} - -bool -DevfsEvent::Process() const -{ - return (true); -} - -//- DevfsEvent Public Methods -------------------------------------------------- -bool -DevfsEvent::IsDiskDev() const -{ - string devName; - - return (DevName(devName) && IsDiskDev(devName)); -} - -bool -DevfsEvent::IsWholeDev() const -{ - string devName; - - return (DevName(devName) && IsDiskDev() && IsWholeDev(devName)); -} - -bool -DevfsEvent::DevName(std::string &name) const -{ - if (Value("subsystem") != "CDEV") - return (false); - - name = Value("cdev"); - return (!name.empty()); -} - -bool -DevfsEvent::DevPath(std::string &path) const -{ - string devName; - - if (!DevName(devName)) - return (false); - - string devPath(_PATH_DEV + devName); - int devFd(open(devPath.c_str(), O_RDONLY)); - if (devFd == -1) - return (false); - - /* Normalize the device name in case the DEVFS event is for a link. */ - devName = fdevname(devFd); - path = _PATH_DEV + devName; - - close(devFd); - - return (true); -} - -bool -DevfsEvent::PhysicalPath(std::string &path) const -{ - string devPath; - - if (!DevPath(devPath)) - return (false); - - int devFd(open(devPath.c_str(), O_RDONLY)); - if (devFd == -1) - return (false); - - char physPath[MAXPATHLEN]; - physPath[0] = '\0'; - bool result(ioctl(devFd, DIOCGPHYSPATH, physPath) == 0); - close(devFd); - if (result) - path = physPath; - return (result); -} - -//- DevfsEvent Protected Methods ----------------------------------------------- -DevfsEvent::DevfsEvent(Event::Type type, NVPairMap &nvpairs, - const string &eventString) - : Event(type, nvpairs, eventString) -{ -} - -DevfsEvent::DevfsEvent(const DevfsEvent &src) - : Event(src) -{ -} - -/*--------------------------------- ZfsEvent ---------------------------------*/ -//- ZfsEvent Static Public Methods --------------------------------------------- -Event * -ZfsEvent::Builder(Event::Type type, NVPairMap &nvpairs, - const string &eventString) -{ - return (new ZfsEvent(type, nvpairs, eventString)); -} - -//- ZfsEvent Virtual Public Methods -------------------------------------------- -Event * -ZfsEvent::DeepCopy() const -{ - return (new ZfsEvent(*this)); -} - -//- ZfsEvent Protected Methods ------------------------------------------------- -ZfsEvent::ZfsEvent(Event::Type type, NVPairMap &nvpairs, - const string &eventString) - : Event(type, nvpairs, eventString), - m_poolGUID(Guid(Value("pool_guid"))), - m_vdevGUID(Guid(Value("vdev_guid"))) -{ -} - -ZfsEvent::ZfsEvent(const ZfsEvent &src) - : Event(src), - m_poolGUID(src.m_poolGUID), - m_vdevGUID(src.m_vdevGUID) -{ -} - -} // namespace DevCtl Index: projects/zfsd/head/lib/libdevctl/Makefile =================================================================== --- projects/zfsd/head/lib/libdevctl/Makefile (revision 289683) +++ projects/zfsd/head/lib/libdevctl/Makefile (nonexistent) @@ -1,19 +0,0 @@ -# $FreeBSD: stable/9/lib/libdevinfo/Makefile 201381 2010-01-02 09:58:07Z ed $ - -LIB= devctl -INCS= consumer.h \ - event.h \ - event_factory.h \ - exception.h \ - guid.h -SRCS= consumer.cc \ - event.cc \ - event_factory.cc \ - exception.cc \ - guid.cc - -INCSDIR= ${INCLUDEDIR}/devctl - -WARNS?= 3 - -.include Index: projects/zfsd/head/lib/libdevctl/exception.h =================================================================== --- projects/zfsd/head/lib/libdevctl/exception.h (revision 289683) +++ projects/zfsd/head/lib/libdevctl/exception.h (nonexistent) @@ -1,166 +0,0 @@ -/*- - * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation - * All rights reserved. - * - * 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, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * - * NO WARRANTY - * 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 MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. - * - * Authors: Justin T. Gibbs (Spectra Logic Corporation) - */ - -/** - * \file zfsd_exception.h - * - * Definition of the ZfsdException class hierarchy. All exceptions - * explicitly thrown by Zfsd are defined here. - */ -#ifndef _DEVCTL_EXCEPTION_H_ -#define _DEVCTL_EXCEPTION_H_ - -/*============================ Namespace Control =============================*/ -namespace DevCtl -{ - -/*============================= Class Definitions ============================*/ - -/*--------------------------------- Exception --------------------------------*/ -/** - * \brief Class allowing unified reporting/logging of exceptional events. - */ -class Exception -{ -public: - /** - * \brief Exception constructor allowing arbitrary string - * data to be reported. - * - * \param fmt Printf-like string format specifier. - */ - Exception(const char *fmt, ...); - - /** - * \brief Augment/Modify a Exception's string data. - */ - std::string& GetString(); - - /** - * \brief Emit exception data to syslog(3). - */ - virtual void Log() const; - -protected: - Exception(); - - /** - * \brief Convert exception string format and arguments provided - * in event constructors into a linear string. - */ - void FormatLog(const char *fmt, va_list ap); - - std::string m_log; -}; - -inline std::string & -Exception::GetString() -{ - return (m_log); -} - -/*------------------------------ ParseException ------------------------------*/ -/** - * Exception thrown when an event string is not converted to an actionable - * Event object. - */ -class ParseException : public Exception -{ -public: - enum Type - { - /** Improperly formatted event string encounterd. */ - INVALID_FORMAT, - - /** No handlers for this event type. */ - DISCARDED_EVENT_TYPE, - - /** Unhandled event type. */ - UNKNOWN_EVENT_TYPE - }; - - /** - * Constructor - * - * \param type The type of this exception. - * \param parsedBuffer The parsing buffer active at the time of - * the exception. - * \param offset The location in the parse buffer where this - * exception occurred. - */ - ParseException(Type type, const std::string &parsedBuffer, - size_t offset = 0); - - /** - * Accessor - * - * \return The classification for this exception. - */ - Type GetType() const; - - /** - * Accessor - * - * \return The offset into the event string where this exception - * occurred. - */ - size_t GetOffset() const; - -private: - /** The type of this exception. */ - Type m_type; - - /** The parsing buffer that was active at the time of the exception. */ - const std::string m_parsedBuffer; - - /** - * The offset into the event string buffer from where this - * exception was triggered. - */ - size_t m_offset; -}; - -//- ParseException Inline Const Public Methods --------------------------------- -inline ParseException::Type -ParseException::GetType() const -{ - return (m_type); -} - -inline size_t -ParseException::GetOffset() const -{ - return (m_offset); -} - -} // namespace DevCtl -#endif /* _DEVCTL_EXCEPTION_H_ */ Index: projects/zfsd/head/lib/libdevctl/reader.h =================================================================== --- projects/zfsd/head/lib/libdevctl/reader.h (revision 289683) +++ projects/zfsd/head/lib/libdevctl/reader.h (nonexistent) @@ -1,136 +0,0 @@ -/*- - * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation - * All rights reserved. - * - * 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, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * - * NO WARRANTY - * 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 MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. - * - * Authors: Justin T. Gibbs (Spectra Logic Corporation) - * - * $FreeBSD$ - */ - -/** - * \file devctl_reader.h - */ -#ifndef _DEVCTL_READER_H_ -#define _DEVCTL_READER_H_ - -/*=========================== Forward Declarations ===========================*/ - -/*============================ Namespace Control =============================*/ -namespace DevCtl -{ - -/*============================= Class Definitions ============================*/ - -/*-------------------------------- Reader -------------------------------*/ -/** - * \brief A class that presents a common interface to both file descriptors - * and istreams. - * - * Standard C++ provides no way to create an iostream from a file descriptor or - * a FILE. The GNU, Apache, HPUX, and Solaris C++ libraries all provide - * non-standard ways to construct such a stream using similar semantics, but - * FreeBSD's C++ library does not. This class supports only the functionality - * needed by ZFSD; it does not implement the iostream API. - */ -class Reader -{ -public: - /** - * \brief Return the number of bytes immediately available for reading - */ - virtual ssize_t in_avail() const = 0; - - /** - * \brief Reads up to count bytes - * - * Whether this call blocks depends on the underlying input source. - * On error, -1 is returned, and errno will be set by the underlying - * source. - * - * \param buf Destination for the data - * \param count Maximum amount of data to read - * \returns Amount of data that was actually read - */ - virtual ssize_t read(char* buf, size_t count) = 0; - - virtual ~Reader() = 0; -}; - -inline Reader::~Reader() {} - - -/*--------------------------------- FDReader ---------------------------------*/ -/** - * \brief Specialization of Reader that uses a file descriptor - */ -class FDReader : public Reader -{ -public: - /** - * \brief Constructor - * - * \param fd An open file descriptor. It will not be garbage - * collected by the destructor. - */ - FDReader(int fd); - - virtual ssize_t in_avail() const; - - virtual ssize_t read(char* buf, size_t count); - -protected: - /** Copy of the underlying file descriptor */ - int m_fd; -}; - -/*-------------------------------- IstreamReader------------------------------*/ -/** - * \brief Specialization of Reader that uses a std::istream - */ -class IstreamReader : public Reader -{ -public: - /** - * Constructor - * - * \param stream Pointer to an open istream. It will not be - * garbage collected by the destructor. - */ - IstreamReader(std::istream* stream); - - virtual ssize_t in_avail() const; - - virtual ssize_t read(char* buf, size_t count); - -protected: - /** Copy of the underlying stream */ - std::istream *m_stream; -}; - -} // namespace DevCtl -#endif /* _DEVCTL_READER_H_ */ Index: projects/zfsd/head/lib/libdevctl/guid.cc =================================================================== --- projects/zfsd/head/lib/libdevctl/guid.cc (revision 289683) +++ projects/zfsd/head/lib/libdevctl/guid.cc (nonexistent) @@ -1,82 +0,0 @@ -/*- - * Copyright (c) 2012, 2013 Spectra Logic Corporation - * All rights reserved. - * - * 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, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * - * NO WARRANTY - * 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 MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. - * - * Authors: Alan Somers (Spectra Logic Corporation) - * - * $FreeBSD$ - */ - -/** - * \file guid.cc - * - * Implementation of the Guid class. - */ -#include - -#include -#include -#include - -#include -#include - -#include "guid.h" - -__FBSDID("$FreeBSD$"); -/*============================ Namespace Control =============================*/ -using std::string; -namespace DevCtl -{ - -/*=========================== Class Implementations ==========================*/ -/*----------------------------------- Guid -----------------------------------*/ -Guid::Guid(const string &guidString) -{ - if (guidString.empty()) { - m_GUID = INVALID_GUID; - } else { - /* - * strtoumax() returns zero on conversion failure - * which nicely matches our choice for INVALID_GUID. - */ - m_GUID = (uint64_t)strtoumax(guidString.c_str(), NULL, 0); - } -} - -std::ostream& -operator<< (std::ostream& out, Guid g) -{ - if (g.IsValid()) - out << (uint64_t)g; - else - out << "None"; - return (out); -} - -} // namespace DevCtl Index: projects/zfsd/head/lib/Makefile =================================================================== --- projects/zfsd/head/lib/Makefile (revision 289683) +++ projects/zfsd/head/lib/Makefile (revision 289684) @@ -1,320 +1,320 @@ # @(#)Makefile 8.1 (Berkeley) 6/4/93 # $FreeBSD$ .include # The SUBDIR_ORDERED list is a small set of libraries which are used by many # of the other libraries. These are built first with a .WAIT between them # and the main list to avoid needing a SUBDIR_DEPEND line on every library # naming just these few items. SUBDIR_ORDERED= ${_csu} \ .WAIT \ libc \ libc_nonshared \ libcompiler_rt \ ${_libclang_rt} \ ${_libcplusplus} \ ${_libcxxrt} \ libelf \ msun # The main list; please keep these sorted alphabetically. SUBDIR= ${SUBDIR_ORDERED} \ .WAIT \ libalias \ libarchive \ ${_libatm} \ libauditd \ libbegemot \ libblocksruntime \ ${_libbluetooth} \ ${_libbsnmp} \ libbsdstat \ libbsm \ libbz2 \ libcalendar \ libcam \ ${_libcapsicum} \ ${_libcasper} \ ${_libcom_err} \ libcompat \ libcrypt \ - libdevctl \ + libdevdctl \ libdevinfo \ libdevstat \ libdpv \ libdwarf \ libedit \ ${_libelftc} \ ${_libevent} \ libexecinfo \ libexpat \ libfetch \ libfigpar \ libgeom \ libgpio \ ${_libgssapi} \ ${_librpcsec_gss} \ ${_libiconv_modules} \ libipsec \ libjail \ libkiconv \ libkvm \ ${_libldns} \ liblzma \ libmagic \ libmandoc \ libmemstat \ libmd \ ${_libmilter} \ ${_libmp} \ ${_libnandfs} \ libnetbsd \ ${_libnetgraph} \ ${_libngatm} \ libnv \ libohash \ libopie \ libpam \ libpcap \ libpjdlog \ ${_libpmc} \ ${_libproc} \ libprocstat \ libradius \ librpcsvc \ librt \ ${_librtld_db} \ libsbuf \ ${_libsdp} \ ${_libsm} \ ${_libsmb} \ ${_libsmdb} \ ${_libsmutil} \ libsqlite3 \ libstand \ libstdbuf \ libstdthreads \ libtacplus \ ${_libtelnet} \ ${_libthr} \ libthread_db \ libucl \ libufs \ libugidfw \ libulog \ ${_libunbound} \ ${_libusbhid} \ ${_libusb} \ libutil \ ${_libvgl} \ ${_libvmmapi} \ libwrap \ libxo \ liby \ ${_libypclnt} \ libz \ ncurses \ ${_atf} \ ${_clang} \ ${_cuse} \ ${_tests} # Inter-library dependencies. When the makefile for a library contains LDADD # libraries, those libraries should be listed as build order dependencies here. SUBDIR_DEPEND_libarchive= libz libbz2 libexpat liblzma libmd SUBDIR_DEPEND_libatm= libmd SUBDIR_DEPEND_libauditdm= libbsm SUBDIR_DEPEND_libbsnmp= ${_libnetgraph} SUBDIR_DEPEND_libc++= libcxxrt SUBDIR_DEPEND_libc= libcompiler_rt SUBDIR_DEPEND_libcam= libsbuf SUBDIR_DEPEND_libcapsicum= libnv SUBDIR_DEPEND_libcasper= libcapsicum libnv libpjdlog SUBDIR_DEPEND_libdevstat= libkvm SUBDIR_DEPEND_libdpv= libfigpar ncurses libutil SUBDIR_DEPEND_libedit= ncurses SUBDIR_DEPEND_libg++= msun SUBDIR_DEPEND_libgeom= libexpat libsbuf SUBDIR_DEPEND_liblibrpcsec_gss= libgssapi SUBDIR_DEPEND_libmagic= libz SUBDIR_DEPEND_libmemstat= libkvm SUBDIR_DEPEND_libopie= libmd SUBDIR_DEPEND_libpam= libcrypt libopie libradius librpcsvc libtacplus libutil ${_libypclnt} ${_libcom_err} SUBDIR_DEPEND_libpjdlog= libutil SUBDIR_DEPEND_libprocstat= libkvm libutil SUBDIR_DEPEND_libradius= libmd SUBDIR_DEPEND_libreadline= ncurses SUBDIR_DEPEND_libsmb= libkiconv SUBDIR_DEPEND_libstdc++= msun SUBDIR_DEPEND_libtacplus= libmd SUBDIR_DEPEND_libulog= libmd SUBDIR_DEPEND_libunbound= ${_libldns} .if exists(${.CURDIR}/csu/${MACHINE_ARCH}-elf) _csu=csu/${MACHINE_ARCH}-elf .elif exists(${.CURDIR}/csu/${MACHINE_ARCH}) _csu=csu/${MACHINE_ARCH} .elif exists(${.CURDIR}/csu/${MACHINE_CPUARCH}/Makefile) _csu=csu/${MACHINE_CPUARCH} .else _csu=csu .endif # NB: keep these sorted by MK_* knobs .if ${MK_ATM} != "no" _libngatm= libngatm .endif .if ${MK_BLUETOOTH} != "no" _libbluetooth= libbluetooth _libsdp= libsdp .endif .if ${MK_BSNMP} != "no" _libbsnmp= libbsnmp .endif .if ${MK_CASPER} != "no" _libcapsicum= libcapsicum _libcasper= libcasper .endif .if ${MK_CLANG} != "no" && !defined(COMPAT_32BIT) _clang= clang .endif .if ${MK_CUSE} != "no" _cuse= libcuse .endif .if ${MK_ELFTOOLCHAIN_TOOLS} != "no" _libelftc= libelftc .endif .if ${MK_GSSAPI} != "no" _libgssapi= libgssapi _librpcsec_gss= librpcsec_gss .endif .if ${MK_ICONV} != "no" _libiconv_modules= libiconv_modules .endif .if ${MK_KERBEROS_SUPPORT} != "no" _libcom_err= libcom_err .endif .if ${MK_LDNS} != "no" _libldns= libldns .endif # The libraries under libclang_rt can only be built by clang, and only make # sense to build when clang is enabled at all. Furthermore, they can only be # built for certain architectures. .if ${MK_CLANG} != "no" && ${COMPILER_TYPE} == "clang" && \ (${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64" || \ (${MACHINE_CPUARCH} == "arm" && ${MACHINE_ARCH} != "armeb")) _libclang_rt= libclang_rt .endif .if ${MK_LIBCPLUSPLUS} != "no" _libcxxrt= libcxxrt _libcplusplus= libc++ .endif .if ${MK_LIBTHR} != "no" _libthr= libthr .endif .if ${MK_NAND} != "no" _libnandfs= libnandfs .endif .if ${MK_NETGRAPH} != "no" _libnetgraph= libnetgraph .endif .if ${MK_NIS} != "no" _libypclnt= libypclnt .endif .if ${MK_PF} != "no" _libevent= libevent .endif .if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64" _libsmb= libsmb _libvgl= libvgl _libproc= libproc _librtld_db= librtld_db .endif .if ${MACHINE_CPUARCH} == "amd64" _libvmmapi= libvmmapi .endif .if ${MACHINE_CPUARCH} == "mips" _libproc= libproc _librtld_db= librtld_db .endif .if ${MACHINE_CPUARCH} == "powerpc" _libproc= libproc _librtld_db= librtld_db _libsmb= libsmb .endif .if ${MACHINE_CPUARCH} == "sparc64" _libsmb= libsmb .endif .if ${MK_OPENSSL} != "no" _libmp= libmp .endif .if ${MK_PMC} != "no" _libpmc= libpmc .endif .if ${MK_SENDMAIL} != "no" _libmilter= libmilter _libsm= libsm _libsmdb= libsmdb _libsmutil= libsmutil .endif .if ${MK_TELNET} != "no" _libtelnet= libtelnet .endif .if ${MK_TESTS_SUPPORT} != "no" _atf= atf .endif .if ${MK_TESTS} != "no" _tests= tests .endif .if ${MK_UNBOUND} != "no" _libunbound= libunbound .endif .if ${MK_USB} != "no" _libusbhid= libusbhid _libusb= libusb .endif .if !defined(LIBRARIES_ONLY) afterinstall: ${INSTALL_SYMLINK} ../include ${DESTDIR}/usr/lib/include .endif .if !make(install) SUBDIR_PARALLEL= .endif .include Index: projects/zfsd/head/lib/libdevdctl/Makefile =================================================================== --- projects/zfsd/head/lib/libdevdctl/Makefile (nonexistent) +++ projects/zfsd/head/lib/libdevdctl/Makefile (revision 289684) @@ -0,0 +1,19 @@ +# $FreeBSD: stable/9/lib/libdevinfo/Makefile 201381 2010-01-02 09:58:07Z ed $ + +LIB= devdctl +INCS= consumer.h \ + event.h \ + event_factory.h \ + exception.h \ + guid.h +SRCS= consumer.cc \ + event.cc \ + event_factory.cc \ + exception.cc \ + guid.cc + +INCSDIR= ${INCLUDEDIR}/devctl + +WARNS?= 3 + +.include Index: projects/zfsd/head/lib/libdevdctl/consumer.cc =================================================================== --- projects/zfsd/head/lib/libdevdctl/consumer.cc (nonexistent) +++ projects/zfsd/head/lib/libdevdctl/consumer.cc (revision 289684) @@ -0,0 +1,258 @@ +/*- + * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation + * All rights reserved. + * + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * 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 MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * Authors: Justin T. Gibbs (Spectra Logic Corporation) + */ + +/** + * \file consumer.cc + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "guid.h" +#include "event.h" +#include "event_factory.h" +#include "exception.h" + +#include "consumer.h" + +__FBSDID("$FreeBSD$"); + +/*================================== Macros ==================================*/ +#define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*x)) + +/*============================ Namespace Control =============================*/ +using std::string; +namespace DevCtl +{ + +/*============================= Class Definitions ============================*/ +/*----------------------------- DevCtl::Consumer -----------------------------*/ +//- Consumer Static Private Data ----------------------------------------------- +const char Consumer::s_devdSockPath[] = "/var/run/devd.seqpacket.pipe"; + +//- Consumer Public Methods ---------------------------------------------------- +Consumer::Consumer(Event::BuildMethod *defBuilder, + EventFactory::Record *regEntries, + size_t numEntries) + : m_devdSockFD(-1), + m_eventFactory(defBuilder), + m_replayingEvents(false) +{ + m_eventFactory.UpdateRegistry(regEntries, numEntries); +} + +Consumer::~Consumer() +{ + DisconnectFromDevd(); +} + +bool +Consumer::ConnectToDevd() +{ + struct sockaddr_un devdAddr; + int sLen; + int result; + + if (m_devdSockFD != -1) { + /* Already connected. */ + syslog(LOG_DEBUG, "%s: Already connected.", __func__); + return (true); + } + syslog(LOG_INFO, "%s: Connecting to devd.", __func__); + + memset(&devdAddr, 0, sizeof(devdAddr)); + devdAddr.sun_family= AF_UNIX; + strlcpy(devdAddr.sun_path, s_devdSockPath, sizeof(devdAddr.sun_path)); + sLen = SUN_LEN(&devdAddr); + + m_devdSockFD = socket(AF_UNIX, SOCK_SEQPACKET, 0); + if (m_devdSockFD == -1) + err(1, "Unable to create socket"); + if (fcntl(m_devdSockFD, F_SETFL, O_NONBLOCK) < 0) + err(1, "fcntl"); + result = connect(m_devdSockFD, + reinterpret_cast(&devdAddr), + sLen); + if (result == -1) { + syslog(LOG_INFO, "Unable to connect to devd"); + DisconnectFromDevd(); + return (false); + } + + syslog(LOG_INFO, "Connection to devd successful"); + return (true); +} + +void +Consumer::DisconnectFromDevd() +{ + if (m_devdSockFD != -1) + syslog(LOG_INFO, "Disconnecting from devd."); + + close(m_devdSockFD); + m_devdSockFD = -1; +} + +std::string +Consumer::ReadEvent() +{ + char buf[MAX_EVENT_SIZE + 1]; + ssize_t len; + + len = ::recv(m_devdSockFD, buf, MAX_EVENT_SIZE, MSG_WAITALL); + if (len == -1) + return (std::string("")); + else { + /* NULL-terminate the result */ + buf[len] = '\0'; + return (std::string(buf)); + } +} + +void +Consumer::ReplayUnconsumedEvents(bool discardUnconsumed) +{ + EventList::iterator event(m_unconsumedEvents.begin()); + bool replayed_any = (event != m_unconsumedEvents.end()); + + m_replayingEvents = true; + if (replayed_any) + syslog(LOG_INFO, "Started replaying unconsumed events"); + while (event != m_unconsumedEvents.end()) { + bool consumed((*event)->Process()); + if (consumed || discardUnconsumed) { + delete *event; + event = m_unconsumedEvents.erase(event); + } else { + event++; + } + } + if (replayed_any) + syslog(LOG_INFO, "Finished replaying unconsumed events"); + m_replayingEvents = false; +} + +bool +Consumer::SaveEvent(const Event &event) +{ + if (m_replayingEvents) + return (false); + m_unconsumedEvents.push_back(event.DeepCopy()); + return (true); +} + +Event * +Consumer::NextEvent() +{ + if (!Connected()) + return(NULL); + + Event *event(NULL); + try { + string evString; + + evString = ReadEvent(); + if (! evString.empty()) { + Event::TimestampEventString(evString); + event = Event::CreateEvent(m_eventFactory, evString); + } + } catch (const Exception &exp) { + exp.Log(); + DisconnectFromDevd(); + } + return (event); +} + +/* Capture and process buffered events. */ +void +Consumer::ProcessEvents() +{ + Event *event; + while ((event = NextEvent()) != NULL) { + if (event->Process()) + SaveEvent(*event); + delete event; + } +} + +void +Consumer::FlushEvents() +{ + std::string s; + + do + s = ReadEvent(); + while (! s.empty()) ; +} + +bool +Consumer::EventsPending() +{ + struct pollfd fds[1]; + int result; + + do { + fds->fd = m_devdSockFD; + fds->events = POLLIN; + fds->revents = 0; + result = poll(fds, NUM_ELEMENTS(fds), /*timeout*/0); + } while (result == -1 && errno == EINTR); + + if (result == -1) + err(1, "Polling for devd events failed"); + + if ((fds->revents & POLLERR) != 0) + throw Exception("Consumer::EventsPending(): " + "POLLERR detected on devd socket."); + + if ((fds->revents & POLLHUP) != 0) + throw Exception("Consumer::EventsPending(): " + "POLLHUP detected on devd socket."); + + return ((fds->revents & POLLIN) != 0); +} + +} // namespace DevCtl Index: projects/zfsd/head/lib/libdevdctl/consumer.h =================================================================== --- projects/zfsd/head/lib/libdevdctl/consumer.h (nonexistent) +++ projects/zfsd/head/lib/libdevdctl/consumer.h (revision 289684) @@ -0,0 +1,186 @@ +/*- + * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation + * All rights reserved. + * + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * 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 MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * Authors: Justin T. Gibbs (Spectra Logic Corporation) + * + * $FreeBSD$ + */ + +/** + * \file devctl_consumer.h + */ +#ifndef _DEVCTL_CONSUMER_H_ +#define _DEVCTL_CONSUMER_H_ + +/*============================ Namespace Control =============================*/ +namespace DevCtl +{ + +/*=========================== Forward Declarations ===========================*/ +class Event; +class EventBuffer; +class FDReader; + +/*============================ Class Declarations ============================*/ +/*----------------------------- DevCtl::Consumer -----------------------------*/ + +/** + */ +class Consumer +{ +public: + Consumer(Event::BuildMethod *defBuilder = NULL, + EventFactory::Record *regEntries = NULL, + size_t numEntries = 0); + virtual ~Consumer(); + + bool Connected() const; + + /** + * Return file descriptor useful for client's wishing to poll(2) + * for new events. + */ + int GetPollFd(); + + /** + * Queue an event for deferred processing or replay. + */ + bool SaveEvent(const Event &event); + + /** + * Reprocess any events saved via the SaveEvent() facility. + * + * \param discardUnconsumed If true, events that are not conumed + * during replay are discarded. + */ + void ReplayUnconsumedEvents(bool discardUnconsumed); + + /** Return an event, if one is available. */ + Event *NextEvent(); + + /** + * Extract events and invoke each event's Process method. + */ + void ProcessEvents(); + + /** Discard all data pending in m_devdSockFD. */ + void FlushEvents(); + + /** + * Test for data pending in m_devdSockFD + * + * \return True if data is pending. Otherwise false. + */ + bool EventsPending(); + + /** + * Open a connection to devd's unix domain socket. + * + * \return True if the connection attempt is successsful. Otherwise + * false. + */ + bool ConnectToDevd(); + + /** + * Close a connection (if any) to devd's unix domain socket. + */ + void DisconnectFromDevd(); + + EventFactory GetFactory(); + +protected: + /** + * \brief Reads the most recent record + * + * On error, "" is returned, and errno will be set by the OS + * + * \returns A string containing the record + */ + std::string ReadEvent(); + + enum { + /* + * The maximum event size supported by libdevctl. + */ + MAX_EVENT_SIZE = 8192, + }; + + static const char s_devdSockPath[]; + + /** + * File descriptor representing the unix domain socket + * connection with devd. + */ + int m_devdSockFD; + + /** + * Reader tied to the devd socket. + */ + FDReader *m_reader; + + /** + * Default EventBuffer connected to m_reader. + */ + EventBuffer *m_eventBuffer; + + EventFactory m_eventFactory; + + /** Queued events for replay. */ + EventList m_unconsumedEvents; + + /** + * Flag controlling whether events can be queued. This boolean + * is set during event replay to ensure that previosuly deferred + * events are not requeued and thus retained forever. + */ + bool m_replayingEvents; +}; + +//- Consumer Const Public Inline Methods --------------------------------------- +inline bool +Consumer::Connected() const +{ + return (m_devdSockFD != -1); +} + +//- Consumer Public Inline Methods --------------------------------------------- +inline int +Consumer::GetPollFd() +{ + return (m_devdSockFD); +} + +inline EventFactory +Consumer::GetFactory() +{ + return (m_eventFactory); +} + +} // namespace DevCtl +#endif /* _DEVCTL_CONSUMER_H_ */ Index: projects/zfsd/head/lib/libdevdctl/event.cc =================================================================== --- projects/zfsd/head/lib/libdevdctl/event.cc (nonexistent) +++ projects/zfsd/head/lib/libdevdctl/event.cc (revision 289684) @@ -0,0 +1,557 @@ +/*- + * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation + * All rights reserved. + * + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * 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 MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * Authors: Justin T. Gibbs (Spectra Logic Corporation) + */ + +/** + * \file event.cc + * + * Implementation of the class hierarchy used to express events + * received via the devctl API. + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "guid.h" +#include "event.h" +#include "event_factory.h" +#include "exception.h" + +__FBSDID("$FreeBSD$"); + +/*================================== Macros ==================================*/ +#define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*x)) + +/*============================ Namespace Control =============================*/ +using std::cout; +using std::endl; +using std::string; +using std::stringstream; + +namespace DevCtl +{ + +/*=========================== Class Implementations ==========================*/ +/*----------------------------------- Event ----------------------------------*/ +//- Event Static Protected Data ------------------------------------------------ +const string Event::s_theEmptyString; + +Event::EventTypeRecord Event::s_typeTable[] = +{ + { Event::NOTIFY, "Notify" }, + { Event::NOMATCH, "No Driver Match" }, + { Event::ATTACH, "Attach" }, + { Event::DETACH, "Detach" } +}; + +//- Event Static Public Methods ------------------------------------------------ +Event * +Event::Builder(Event::Type type, NVPairMap &nvPairs, + const string &eventString) +{ + return (new Event(type, nvPairs, eventString)); +} + +Event * +Event::CreateEvent(const EventFactory &factory, const string &eventString) +{ + NVPairMap &nvpairs(*new NVPairMap); + Type type(static_cast(eventString[0])); + + try { + ParseEventString(type, eventString, nvpairs); + } catch (const ParseException &exp) { + if (exp.GetType() == ParseException::INVALID_FORMAT) + exp.Log(); + return (NULL); + } + + /* + * Allow entries in our table for events with no system specified. + * These entries should specify the string "none". + */ + NVPairMap::iterator system_item(nvpairs.find("system")); + if (system_item == nvpairs.end()) + nvpairs["system"] = "none"; + + return (factory.Build(type, nvpairs, eventString)); +} + +const char * +Event::TypeToString(Event::Type type) +{ + EventTypeRecord *rec(s_typeTable); + EventTypeRecord *lastRec(s_typeTable + NUM_ELEMENTS(s_typeTable) - 1); + + for (; rec <= lastRec; rec++) { + if (rec->m_type == type) + return (rec->m_typeName); + } + return ("Unknown"); +} + +//- Event Public Methods ------------------------------------------------------- +const string & +Event::Value(const string &varName) const +{ + NVPairMap::const_iterator item(m_nvPairs.find(varName)); + if (item == m_nvPairs.end()) + return (s_theEmptyString); + + return (item->second); +} + +bool +Event::Contains(const string &varName) const +{ + return (m_nvPairs.find(varName) != m_nvPairs.end()); +} + +string +Event::ToString() const +{ + stringstream result; + + NVPairMap::const_iterator devName(m_nvPairs.find("device-name")); + if (devName != m_nvPairs.end()) + result << devName->second << ": "; + + NVPairMap::const_iterator systemName(m_nvPairs.find("system")); + if (systemName != m_nvPairs.end() + && systemName->second != "none") + result << systemName->second << ": "; + + result << TypeToString(GetType()) << ' '; + + for (NVPairMap::const_iterator curVar = m_nvPairs.begin(); + curVar != m_nvPairs.end(); curVar++) { + if (curVar == devName || curVar == systemName) + continue; + + result << ' ' + << curVar->first << "=" << curVar->second; + } + result << endl; + + return (result.str()); +} + +void +Event::Print() const +{ + cout << ToString() << std::flush; +} + +void +Event::Log(int priority) const +{ + syslog(priority, "%s", ToString().c_str()); +} + +//- Event Virtual Public Methods ----------------------------------------------- +Event::~Event() +{ + delete &m_nvPairs; +} + +Event * +Event::DeepCopy() const +{ + return (new Event(*this)); +} + +bool +Event::Process() const +{ + return (false); +} + +timeval +Event::GetTimestamp() const +{ + timeval tv_timestamp; + struct tm tm_timestamp; + + if (!Contains("timestamp")) { + throw Exception("Event contains no timestamp: %s", + m_eventString.c_str()); + } + strptime(Value(string("timestamp")).c_str(), "%s", &tm_timestamp); + tv_timestamp.tv_sec = mktime(&tm_timestamp); + tv_timestamp.tv_usec = 0; + return (tv_timestamp); +} + + +//- Event Protected Methods ---------------------------------------------------- +Event::Event(Type type, NVPairMap &map, const string &eventString) + : m_type(type), + m_nvPairs(map), + m_eventString(eventString) +{ +} + +Event::Event(const Event &src) + : m_type(src.m_type), + m_nvPairs(*new NVPairMap(src.m_nvPairs)), + m_eventString(src.m_eventString) +{ +} + +void +Event::ParseEventString(Event::Type type, + const string &eventString, + NVPairMap& nvpairs) +{ + size_t start; + size_t end; + + switch (type) { + case ATTACH: + case DETACH: + + /* + * \ + * at \ + * on + * + * Handle all data that doesn't conform to the + * "name=value" format, and let the generic parser + * below handle the rest. + * + * Type is a single char. Skip it. + */ + start = 1; + end = eventString.find_first_of(" \t\n", start); + if (end == string::npos) + throw ParseException(ParseException::INVALID_FORMAT, + eventString, start); + + nvpairs["device-name"] = eventString.substr(start, end - start); + + start = eventString.find(" on ", end); + if (end == string::npos) + throw ParseException(ParseException::INVALID_FORMAT, + eventString, start); + start += 4; + end = eventString.find_first_of(" \t\n", start); + nvpairs["parent"] = eventString.substr(start, end); + break; + case NOTIFY: + break; + case NOMATCH: + throw ParseException(ParseException::DISCARDED_EVENT_TYPE, + eventString); + default: + throw ParseException(ParseException::UNKNOWN_EVENT_TYPE, + eventString); + } + + /* Process common "key=value" format. */ + for (start = 1; start < eventString.length(); start = end + 1) { + + /* Find the '=' in the middle of the key/value pair. */ + end = eventString.find('=', start); + if (end == string::npos) + break; + + /* + * Find the start of the key by backing up until + * we hit whitespace or '!' (event type "notice"). + * Due to the devctl format, all key/value pair must + * start with one of these two characters. + */ + start = eventString.find_last_of("! \t\n", end); + if (start == string::npos) + throw ParseException(ParseException::INVALID_FORMAT, + eventString, end); + start++; + string key(eventString.substr(start, end - start)); + + /* + * Walk forward from the '=' until either we exhaust + * the buffer or we hit whitespace. + */ + start = end + 1; + if (start >= eventString.length()) + throw ParseException(ParseException::INVALID_FORMAT, + eventString, end); + end = eventString.find_first_of(" \t\n", start); + if (end == string::npos) + end = eventString.length() - 1; + string value(eventString.substr(start, end - start)); + + nvpairs[key] = value; + } +} + +void +Event::TimestampEventString(std::string &eventString) +{ + if (eventString.size() > 0) { + /* + * Add a timestamp as the final field of the event if it is + * not already present. + */ + if (eventString.find("timestamp=") == string::npos) { + const size_t bufsize = 32; // Long enough for a 64-bit int + timeval now; + struct tm* time_s; + char timebuf[bufsize]; + + size_t eventEnd(eventString.find_last_not_of('\n') + 1); + if (gettimeofday(&now, NULL) != 0) + err(1, "gettimeofday"); + time_s = gmtime(&now.tv_sec); + strftime(timebuf, bufsize, " timestamp=%s", time_s); + eventString.insert(eventEnd, timebuf); + } + } +} + +/*-------------------------------- DevfsEvent --------------------------------*/ +//- DevfsEvent Static Public Methods ------------------------------------------- +Event * +DevfsEvent::Builder(Event::Type type, NVPairMap &nvPairs, + const string &eventString) +{ + return (new DevfsEvent(type, nvPairs, eventString)); +} + +//- DevfsEvent Static Protected Methods ---------------------------------------- +bool +DevfsEvent::IsDiskDev(const string &devName) +{ + static const char *diskDevNames[] = + { + "da", + "ada" + }; + + const char **diskName(diskDevNames); + const char **lastDiskName(diskDevNames + + NUM_ELEMENTS(diskDevNames) - 1); + size_t find_start = devName.rfind('/'); + if (find_start == string::npos) { + find_start = 0; + } else { + /* Just after the last '/'. */ + find_start++; + } + + for (; diskName <= lastDiskName; diskName++) { + + size_t loc(devName.find(*diskName, find_start)); + if (loc == find_start) { + size_t prefixLen(strlen(*diskName)); + + if (devName.length() - find_start >= prefixLen + && isdigit(devName[find_start + prefixLen])) + return (true); + } + } + + return (false); +} + +bool +DevfsEvent::IsWholeDev(const string &devName) +{ + string::const_iterator i(devName.begin()); + + size_t start = devName.rfind('/'); + if (start == string::npos) { + start = 0; + } else { + /* Just after the last '/'. */ + start++; + } + i += start; + + /* alpha prefix followed only by digits. */ + for (; i < devName.end() && !isdigit(*i); i++) + ; + + if (i == devName.end()) + return (false); + + for (; i < devName.end() && isdigit(*i); i++) + ; + + return (i == devName.end()); +} + +//- DevfsEvent Virtual Public Methods ------------------------------------------ +Event * +DevfsEvent::DeepCopy() const +{ + return (new DevfsEvent(*this)); +} + +bool +DevfsEvent::Process() const +{ + return (true); +} + +//- DevfsEvent Public Methods -------------------------------------------------- +bool +DevfsEvent::IsDiskDev() const +{ + string devName; + + return (DevName(devName) && IsDiskDev(devName)); +} + +bool +DevfsEvent::IsWholeDev() const +{ + string devName; + + return (DevName(devName) && IsDiskDev() && IsWholeDev(devName)); +} + +bool +DevfsEvent::DevName(std::string &name) const +{ + if (Value("subsystem") != "CDEV") + return (false); + + name = Value("cdev"); + return (!name.empty()); +} + +bool +DevfsEvent::DevPath(std::string &path) const +{ + string devName; + + if (!DevName(devName)) + return (false); + + string devPath(_PATH_DEV + devName); + int devFd(open(devPath.c_str(), O_RDONLY)); + if (devFd == -1) + return (false); + + /* Normalize the device name in case the DEVFS event is for a link. */ + devName = fdevname(devFd); + path = _PATH_DEV + devName; + + close(devFd); + + return (true); +} + +bool +DevfsEvent::PhysicalPath(std::string &path) const +{ + string devPath; + + if (!DevPath(devPath)) + return (false); + + int devFd(open(devPath.c_str(), O_RDONLY)); + if (devFd == -1) + return (false); + + char physPath[MAXPATHLEN]; + physPath[0] = '\0'; + bool result(ioctl(devFd, DIOCGPHYSPATH, physPath) == 0); + close(devFd); + if (result) + path = physPath; + return (result); +} + +//- DevfsEvent Protected Methods ----------------------------------------------- +DevfsEvent::DevfsEvent(Event::Type type, NVPairMap &nvpairs, + const string &eventString) + : Event(type, nvpairs, eventString) +{ +} + +DevfsEvent::DevfsEvent(const DevfsEvent &src) + : Event(src) +{ +} + +/*--------------------------------- ZfsEvent ---------------------------------*/ +//- ZfsEvent Static Public Methods --------------------------------------------- +Event * +ZfsEvent::Builder(Event::Type type, NVPairMap &nvpairs, + const string &eventString) +{ + return (new ZfsEvent(type, nvpairs, eventString)); +} + +//- ZfsEvent Virtual Public Methods -------------------------------------------- +Event * +ZfsEvent::DeepCopy() const +{ + return (new ZfsEvent(*this)); +} + +//- ZfsEvent Protected Methods ------------------------------------------------- +ZfsEvent::ZfsEvent(Event::Type type, NVPairMap &nvpairs, + const string &eventString) + : Event(type, nvpairs, eventString), + m_poolGUID(Guid(Value("pool_guid"))), + m_vdevGUID(Guid(Value("vdev_guid"))) +{ +} + +ZfsEvent::ZfsEvent(const ZfsEvent &src) + : Event(src), + m_poolGUID(src.m_poolGUID), + m_vdevGUID(src.m_vdevGUID) +{ +} + +} // namespace DevCtl Index: projects/zfsd/head/lib/libdevdctl/event.h =================================================================== --- projects/zfsd/head/lib/libdevdctl/event.h (nonexistent) +++ projects/zfsd/head/lib/libdevdctl/event.h (revision 289684) @@ -0,0 +1,379 @@ +/*- + * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation + * All rights reserved. + * + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * 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 MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * Authors: Justin T. Gibbs (Spectra Logic Corporation) + * + * $FreeBSD$ + */ + +/** + * \file devctl_event.h + * + * \brief Class hierarchy used to express events received via + * the devctl API. + */ + +#ifndef _DEVCTL_EVENT_H_ +#define _DEVCTL_EVENT_H_ + +/*============================ Namespace Control =============================*/ +namespace DevCtl +{ + +/*=========================== Forward Declarations ===========================*/ +class EventFactory; + +/*============================= Class Definitions ============================*/ +/*-------------------------------- NVPairMap ---------------------------------*/ +/** + * NVPairMap is a specialization of the standard map STL container. + */ +typedef std::map NVPairMap; + +/*----------------------------------- Event ----------------------------------*/ +/** + * \brief Container for the name => value pairs that comprise the content of + * a device control event. + * + * All name => value data for events can be accessed via the Contains() + * and Value() methods. name => value pairs for data not explicitly + * received as a name => value pair are synthesized during parsing. For + * example, ATTACH and DETACH events have "device-name" and "parent" + * name => value pairs added. + */ +class Event +{ + friend class EventFactory; + +public: + /** Event type */ + enum Type { + /** Generic event notification. */ + NOTIFY = '!', + + /** A driver was not found for this device. */ + NOMATCH = '?', + + /** A bus device instance has been added. */ + ATTACH = '+', + + /** A bus device instance has been removed. */ + DETACH = '-' + }; + + /** + * Factory method type to construct an Event given + * the type of event and an NVPairMap populated from + * the event string received from devd. + */ + typedef Event* (BuildMethod)(Type, NVPairMap &, const std::string &); + + /** Generic Event object factory. */ + static BuildMethod Builder; + + static Event *CreateEvent(const EventFactory &factory, + const std::string &eventString); + + /** + * Provide a user friendly string representation of an + * event type. + * + * \param type The type of event to map to a string. + * + * \return A user friendly string representing the input type. + */ + static const char *TypeToString(Type type); + + /** + * Determine the availability of a name => value pair by name. + * + * \param name The key name to search for in this event instance. + * + * \return true if the specified key is available in this + * event, otherwise false. + */ + bool Contains(const std::string &name) const; + + /** + * \param key The name of the key for which to retrieve its + * associated value. + * + * \return A const reference to the string representing the + * value associated with key. + * + * \note For key's with no registered value, the empty string + * is returned. + */ + const std::string &Value(const std::string &key) const; + + /** + * Get the type of this event instance. + * + * \return The type of this event instance. + */ + Type GetType() const; + + /** + * Get the orginal DevCtl event string for this event. + * + * \return The DevCtl event string. + */ + const std::string &GetEventString() const; + + /** + * Convert the event instance into a string suitable for + * printing to the console or emitting to syslog. + * + * \return A string of formatted event data. + */ + std::string ToString() const; + + /** + * Pretty-print this event instance to cout. + */ + void Print() const; + + /** + * Pretty-print this event instance to syslog. + * + * \param priority The logging priority/facility. + * See syslog(3). + */ + void Log(int priority) const; + + /** + * Create and return a fully independent clone + * of this event. + */ + virtual Event *DeepCopy() const; + + /** Destructor */ + virtual ~Event(); + + /** + * Interpret and perform any actions necessary to + * consume the event. + * + * \return True if this event should be queued for later reevaluation + */ + virtual bool Process() const; + + /** + * Get the time that the event was created + */ + timeval GetTimestamp() const; + + /** + * Add a timestamp to the event string, if one does not already exist + * TODO: make this an instance method that operates on the std::map + * instead of the string. We must fix zfsd's CaseFile serialization + * routines first, so that they don't need the raw event string. + * + * \param[in,out] eventString The devd event string to modify + */ + static void TimestampEventString(std::string &eventString); + + /** + * Access all parsed key => value pairs. + */ + const NVPairMap &GetMap() const; + +protected: + /** Table entries used to map a type to a user friendly string. */ + struct EventTypeRecord + { + Type m_type; + const char *m_typeName; + }; + + /** + * Constructor + * + * \param type The type of event to create. + */ + Event(Type type, NVPairMap &map, const std::string &eventString); + + /** Deep copy constructor. */ + Event(const Event &src); + + /** Always empty string returned when NVPairMap lookups fail. */ + static const std::string s_theEmptyString; + + /** Unsorted table of event types. */ + static EventTypeRecord s_typeTable[]; + + /** The type of this event. */ + const Type m_type; + + /** + * Event attribute storage. + * + * \note Although stored by reference (since m_nvPairs can + * never be NULL), the NVPairMap referenced by this field + * is dynamically allocated and owned by this event object. + * m_nvPairs must be deleted at event desctruction. + */ + NVPairMap &m_nvPairs; + + /** + * The unaltered event string, as received from devd, used to + * create this event object. + */ + std::string m_eventString; + +private: + /** + * Ingest event data from the supplied string. + * + * \param[in] eventString The string of devd event data to parse. + * \param[out] nvpairs Returns the parsed data + */ + static void ParseEventString(Type type, const std::string &eventString, + NVPairMap &nvpairs); +}; + +inline Event::Type +Event::GetType() const +{ + return (m_type); +} + +inline const std::string & +Event::GetEventString() const +{ + return (m_eventString); +} + +inline const NVPairMap & +Event::GetMap() const +{ + return (m_nvPairs); +} + +/*--------------------------------- EventList --------------------------------*/ +/** + * EventList is a specialization of the standard list STL container. + */ +typedef std::list EventList; + +/*-------------------------------- DevfsEvent --------------------------------*/ +class DevfsEvent : public Event +{ +public: + /** Specialized Event object factory for Devfs events. */ + static BuildMethod Builder; + + virtual Event *DeepCopy() const; + + /** + * Interpret and perform any actions necessary to + * consume the event. + * \return True if this event should be queued for later reevaluation + */ + virtual bool Process() const; + + bool IsDiskDev() const; + bool IsWholeDev() const; + bool DevName(std::string &name) const; + bool DevPath(std::string &path) const; + bool PhysicalPath(std::string &path) const; + +protected: + /** + * Determine if the given device name references a potential + * disk device. + * + * \param devName The device name to test. + */ + static bool IsDiskDev(const std::string &devName); + + /** + * Given the device name of a disk, determine if the device + * represents the whole device, not just a partition. + * + * \param devName Device name of disk device to test. + * + * \return True if the device name represents the whole device. + * Otherwise false. + */ + static bool IsWholeDev(const std::string &devName); + + /** DeepCopy Constructor. */ + DevfsEvent(const DevfsEvent &src); + + /** Constructor */ + DevfsEvent(Type, NVPairMap &, const std::string &); +}; + +/*--------------------------------- ZfsEvent ---------------------------------*/ +class ZfsEvent : public Event +{ +public: + /** Specialized Event object factory for ZFS events. */ + static BuildMethod Builder; + + virtual Event *DeepCopy() const; + + const std::string &PoolName() const; + Guid PoolGUID() const; + Guid VdevGUID() const; + +protected: + /** Constructor */ + ZfsEvent(Type, NVPairMap &, const std::string &); + + /** Deep copy constructor. */ + ZfsEvent(const ZfsEvent &src); + + Guid m_poolGUID; + Guid m_vdevGUID; +}; + +//- ZfsEvent Inline Public Methods -------------------------------------------- +inline const std::string& +ZfsEvent::PoolName() const +{ + /* The pool name is reported as the subsystem of ZFS events. */ + return (Value("subsystem")); +} + +inline Guid +ZfsEvent::PoolGUID() const +{ + return (m_poolGUID); +} + +inline Guid +ZfsEvent::VdevGUID() const +{ + return (m_vdevGUID); +} + +} // namespace DevCtl +#endif /*_DEVCTL_EVENT_H_ */ Index: projects/zfsd/head/lib/libdevdctl/event_factory.cc =================================================================== --- projects/zfsd/head/lib/libdevdctl/event_factory.cc (nonexistent) +++ projects/zfsd/head/lib/libdevdctl/event_factory.cc (revision 289684) @@ -0,0 +1,99 @@ +/*- + * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation + * All rights reserved. + * + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * 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 MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * Authors: Justin T. Gibbs (Spectra Logic Corporation) + */ + +/** + * \file event_factory.cc + */ +#include +#include + +#include +#include +#include + +#include "guid.h" +#include "event.h" +#include "event_factory.h" + +__FBSDID("$FreeBSD$"); + +/*================================== Macros ==================================*/ +#define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*x)) + +/*============================ Namespace Control =============================*/ +namespace DevCtl +{ + +/*=========================== Class Implementations ==========================*/ +/*------------------------------- EventFactory -------------------------------*/ +//- Event Public Methods ------------------------------------------------------- +EventFactory::EventFactory(Event::BuildMethod *defaultBuildMethod) + : m_defaultBuildMethod(defaultBuildMethod) +{ +} + +void +EventFactory::UpdateRegistry(Record regEntries[], size_t numEntries) +{ + EventFactory::Record *rec(regEntries); + EventFactory::Record *lastRec(rec + numEntries - 1); + + for (; rec <= lastRec; rec++) { + Key key(rec->m_type, rec->m_subsystem); + + if (rec->m_buildMethod == NULL) + m_registry.erase(key); + else + m_registry[key] = rec->m_buildMethod; + } +} + +Event * +EventFactory::Build(Event::Type type, NVPairMap &nvpairs, + const std::string eventString) const +{ + Key key(type, nvpairs["system"]); + Event::BuildMethod *buildMethod(m_defaultBuildMethod); + + Registry::const_iterator foundMethod(m_registry.find(key)); + if (foundMethod != m_registry.end()) + buildMethod = foundMethod->second; + + if (buildMethod == NULL) { + delete &nvpairs; + return (NULL); + } + + return (buildMethod(type, nvpairs, eventString)); +} + +} // namespace DevCtl Index: projects/zfsd/head/lib/libdevdctl/exception.cc =================================================================== --- projects/zfsd/head/lib/libdevdctl/exception.cc (nonexistent) +++ projects/zfsd/head/lib/libdevdctl/exception.cc (revision 289684) @@ -0,0 +1,125 @@ +/*- + * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation + * All rights reserved. + * + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * 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 MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * Authors: Justin T. Gibbs (Spectra Logic Corporation) + */ + +/** + * \file exception.cc + */ +#include + +#include + +#include +#include +#include +#include + +#include "exception.h" + +__FBSDID("$FreeBSD$"); + +/*============================ Namespace Control =============================*/ +using std::string; +using std::stringstream; +using std::endl; +namespace DevCtl +{ + +/*=========================== Class Implementations ==========================*/ +/*--------------------------------- Exception --------------------------------*/ +void +Exception::FormatLog(const char *fmt, va_list ap) +{ + char buf[256]; + + vsnprintf(buf, sizeof(buf), fmt, ap); + m_log = buf; +} + +Exception::Exception(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + FormatLog(fmt, ap); + va_end(ap); +} + +Exception::Exception() +{ +} + +void +Exception::Log() const +{ + syslog(LOG_ERR, "%s", m_log.c_str()); +} + +/*------------------------------ ParseException ------------------------------*/ +//- ParseException Inline Public Methods --------------------------------------- +ParseException::ParseException(Type type, const std::string &parsedBuffer, + size_t offset) + : Exception(), + m_type(type), + m_parsedBuffer(parsedBuffer), + m_offset(offset) +{ + stringstream logstream; + + logstream << "Parsing "; + + switch (Type()) { + case INVALID_FORMAT: + logstream << "invalid format "; + break; + case DISCARDED_EVENT_TYPE: + logstream << "discarded event "; + break; + case UNKNOWN_EVENT_TYPE: + logstream << "unknown event "; + break; + default: + break; + } + logstream << "exception on buffer: \'"; + if (GetOffset() == 0) { + logstream << m_parsedBuffer << '\'' << endl; + } else { + string markedBuffer(m_parsedBuffer); + + markedBuffer.insert(GetOffset(), ""); + logstream << markedBuffer << '\'' << endl; + } + + GetString() = logstream.str(); +} + +} // namespace DevCtl Index: projects/zfsd/head/lib/libdevdctl/event_buffer.cc =================================================================== --- projects/zfsd/head/lib/libdevdctl/event_buffer.cc (nonexistent) +++ projects/zfsd/head/lib/libdevdctl/event_buffer.cc (revision 289684) @@ -0,0 +1,216 @@ +/*- + * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation + * All rights reserved. + * + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * 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 MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * Authors: Justin T. Gibbs (Spectra Logic Corporation) + */ + +/** + * \file event_buffer.cc + */ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "event_buffer.h" +#include "exception.h" +#include "reader.h" + +__FBSDID("$FreeBSD$"); + +/*============================ Namespace Control =============================*/ +using std::string; +using std::stringstream; +namespace DevCtl +{ + +/*============================= Class Definitions ============================*/ +/*-------------------------------- EventBuffer -------------------------------*/ +//- EventBuffer Static Data ---------------------------------------------------- +/** + * NOTIFY, NOMATCH, ATTACH, DETACH. See DevCtlEvent::Type. + */ +const char EventBuffer::s_eventStartTokens[] = "!?+-"; + +/** + * Events are terminated by a newline. + */ +const char EventBuffer::s_eventEndTokens[] = "\n"; + +/** + * Key=Value pairs are terminated by whitespace. + */ +const char EventBuffer::s_keyPairSepTokens[] = " \t\n"; + +//- EventBuffer Public Methods ------------------------------------------------- +EventBuffer::EventBuffer(Reader& reader) + : m_reader(reader), + m_validLen(0), + m_parsedLen(0), + m_nextEventOffset(0), + m_synchronized(true) +{ +} + +bool +EventBuffer::ExtractEvent(string &eventString) +{ + stringstream tsField; + timeval now; + + gettimeofday(&now, NULL); + tsField << " timestamp=" << now.tv_sec; + + while (UnParsed() > 0 || Fill()) { + + /* + * If the valid data in the buffer isn't enough to hold + * a full event, try reading more. + */ + if (NextEventMaxLen() < MIN_EVENT_SIZE) { + m_parsedLen += UnParsed(); + continue; + } + + char *nextEvent(m_buf + m_nextEventOffset); + bool truncated(true); + size_t eventLen(strcspn(nextEvent, s_eventEndTokens)); + + if (!m_synchronized) { + /* Discard data until an end token is read. */ + if (nextEvent[eventLen] != '\0') + m_synchronized = true; + m_nextEventOffset += eventLen; + m_parsedLen = m_nextEventOffset; + continue; + } else if (nextEvent[eventLen] == '\0') { + + m_parsedLen += eventLen; + if (m_parsedLen < MAX_EVENT_SIZE) { + /* + * Ran out of buffer before hitting + * a full event. Fill() and try again. + */ + continue; + } + syslog(LOG_WARNING, "Overran event buffer\n\tm_nextEventOffset" + "=%zd\n\tm_parsedLen=%zd\n\tm_validLen=%zd", + m_nextEventOffset, m_parsedLen, m_validLen); + } else { + /* + * Include the normal terminator in the extracted + * event data. + */ + eventLen += 1; + truncated = false; + } + + m_nextEventOffset += eventLen; + m_parsedLen = m_nextEventOffset; + eventString.assign(nextEvent, eventLen); + + if (truncated) { + size_t fieldEnd; + + /* Break cleanly at the end of a key<=>value pair. */ + fieldEnd = eventString.find_last_of(s_keyPairSepTokens); + if (fieldEnd != string::npos) + eventString.erase(fieldEnd); + eventString += '\n'; + + m_synchronized = false; + syslog(LOG_WARNING, + "Truncated %zd characters from event.", + eventLen - fieldEnd); + } + + /* + * Add a timestamp as the final field of the event if it is + * not already present. + */ + if (eventString.find("timestamp=") == string::npos) { + size_t eventEnd(eventString.find_last_not_of('\n') + 1); + + eventString.insert(eventEnd, tsField.str()); + } + + return (true); + } + return (false); +} + +//- EventBuffer Private Methods ------------------------------------------------ +bool +EventBuffer::Fill() +{ + ssize_t avail; + ssize_t consumed(0); + + /* Compact the buffer. */ + if (m_nextEventOffset != 0) { + memmove(m_buf, m_buf + m_nextEventOffset, + m_validLen - m_nextEventOffset); + m_validLen -= m_nextEventOffset; + m_parsedLen -= m_nextEventOffset; + m_nextEventOffset = 0; + } + + /* Fill any empty space. */ + avail = m_reader.in_avail(); + if (avail > 0) { + size_t want; + + want = std::min((size_t)avail, MAX_READ_SIZE - m_validLen); + consumed = m_reader.read(m_buf + m_validLen, want); + if (consumed == -1) { + if (errno == EINTR) + return (false); + else + err(1, "EventBuffer::Fill(): Read failed"); + } + } else if (avail == -1) { + throw Exception("EventBuffer::Fill(): Reader disconnected"); + } + + m_validLen += consumed; + /* Guarantee our buffer is always NUL terminated. */ + m_buf[m_validLen] = '\0'; + + return (consumed > 0); +} + +} // namespace DevCtl Index: projects/zfsd/head/lib/libdevdctl/event_buffer.h =================================================================== --- projects/zfsd/head/lib/libdevdctl/event_buffer.h (nonexistent) +++ projects/zfsd/head/lib/libdevdctl/event_buffer.h (revision 289684) @@ -0,0 +1,188 @@ +/*- + * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation + * All rights reserved. + * + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * 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 MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * Authors: Justin T. Gibbs (Spectra Logic Corporation) + * + * $FreeBSD$ + */ + +/** + * \file devctl_event_buffer.h + */ +#ifndef _DEVCTL_EVENT_BUFFER_H_ +#define _DEVCTL_EVENT_BUFFER_H_ + +/*============================ Namespace Control =============================*/ +namespace DevCtl +{ + +/*=========================== Forward Declarations ===========================*/ +class Reader; + +/*============================= Class Definitions ============================*/ +/*-------------------------------- EventBuffer -------------------------------*/ +/** + * \brief Class buffering event data from Devd or a similar source and + * splitting it into individual event strings. + * + * Users of this class initialize it with a Reader associated with the unix + * domain socket connection with devd or a compatible source. The lifetime of + * an EventBuffer instance should match that of the Reader passed to it. This + * is required as data from partially received events is retained in the + * EventBuffer in order to allow reconstruction of these events across multiple + * reads of the stream. + * + * Once the program determines that the Reader is ready for reading, the + * EventBuffer::ExtractEvent() should be called in a loop until the method + * returns false. + */ +class EventBuffer +{ +public: + /** + * Constructor + * + * \param reader The data source on which to buffer/parse event data. + */ + EventBuffer(Reader& reader); + + /** + * Pull a single event string out of the event buffer. + * + * \param eventString The extracted event data (if available). + * + * \return true if event data is available and eventString has + * been populated. Otherwise false. + */ + bool ExtractEvent(std::string &eventString); + +private: + enum { + /** + * Size of an empty event (start and end token with + * no data. The EventBuffer parsing needs at least + * this much data in the buffer for safe event extraction. + */ + MIN_EVENT_SIZE = 2, + + /* + * The maximum event size supported by ZFSD. + * Events larger than this size (minus 1) are + * truncated at the end of the last fully received + * key/value pair. + */ + MAX_EVENT_SIZE = 8192, + + /** + * The maximum amount of buffer data to read at + * a single time from the Devd file descriptor. + */ + MAX_READ_SIZE = MAX_EVENT_SIZE, + + /** + * The size of EventBuffer's buffer of Devd event data. + * This is one larger than the maximum supported event + * size, which alows us to always include a terminating + * NUL without overwriting any received data. + */ + EVENT_BUFSIZE = MAX_EVENT_SIZE + /*NUL*/1 + }; + + /** The amount of data in m_buf we have yet to look at. */ + size_t UnParsed() const; + + /** The amount of data in m_buf available for the next event. */ + size_t NextEventMaxLen() const; + + /** Fill the event buffer with event data from Devd. */ + bool Fill(); + + /** Characters we treat as beginning an event string. */ + static const char s_eventStartTokens[]; + + /** Characters we treat as ending an event string. */ + static const char s_eventEndTokens[]; + + /** Characters found between successive "key=value" strings. */ + static const char s_keyPairSepTokens[]; + + /** Temporary space for event data during our parsing. Laid out like + * this: + * <---------------------------------------------------------> + * | | | | | + * m_buf---| | | | | + * m_nextEventOffset-- | | | + * m_parsedLen------------- | | + * m_validLen-------------------------- | + * EVENT_BUFSIZE------------------------------------------------------ + * + * Data before m_nextEventOffset has already been processed. + * + * Data between m_nextEvenOffset and m_parsedLen has been parsed, but + * not processed as a single event. + * + * Data between m_parsedLen and m_validLen has been read from the + * source, but not yet parsed. + * + * Between m_validLen and EVENT_BUFSIZE is empty space. + * + * */ + char m_buf[EVENT_BUFSIZE]; + + /** Reference to the reader linked to devd's domain socket. */ + Reader& m_reader; + + /** Offset within m_buf to the beginning of free space. */ + size_t m_validLen; + + /** Offset within m_buf to the beginning of data not yet parsed */ + size_t m_parsedLen; + + /** Offset within m_buf to the start token of the next event. */ + size_t m_nextEventOffset; + + /** The EventBuffer is aligned and tracking event records. */ + bool m_synchronized; +}; + +//- EventBuffer Inline Private Methods ----------------------------------------- +inline size_t +EventBuffer::UnParsed() const +{ + return (m_validLen - m_parsedLen); +} + +inline size_t +EventBuffer::NextEventMaxLen() const +{ + return (m_validLen - m_nextEventOffset); +} + +} // namespace DevCtl +#endif /* _DEVCTL_EVENT_BUFFER_H_ */ Index: projects/zfsd/head/lib/libdevdctl/event_factory.h =================================================================== --- projects/zfsd/head/lib/libdevdctl/event_factory.h (nonexistent) +++ projects/zfsd/head/lib/libdevdctl/event_factory.h (revision 289684) @@ -0,0 +1,94 @@ +/*- + * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation + * All rights reserved. + * + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * 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 MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * Authors: Justin T. Gibbs (Spectra Logic Corporation) + * + * $FreeBSD$ + */ + +/** + * \file devctl_event_factory.h + */ + +#ifndef _DEVCTL_EVENT_FACTORY_H_ +#define _DEVCTL_EVENT_FACTORY_H_ + +/*============================ Namespace Control =============================*/ +namespace DevCtl +{ + +/*============================= Class Definitions ============================*/ +/*------------------------------- EventFactory -------------------------------*/ +/** + * \brief Container for "event type" => "event object" creaction methods. + */ +class EventFactory +{ +public: + /** + * Event creation handlers are matched by event type and a + * string representing the system emitting the event. + */ + typedef std::pair Key; + + /** Map type for Factory method lookups. */ + typedef std::map Registry; + + /** Table record of factory methods to add to our registry. */ + struct Record + { + Event::Type m_type; + const char *m_subsystem; + Event::BuildMethod *m_buildMethod; + }; + + const Registry &GetRegistry() const; + Event *Build(Event::Type type, NVPairMap &nvpairs, + const std::string eventString) const; + + EventFactory(Event::BuildMethod *defaultBuildMethod = NULL); + + void UpdateRegistry(Record regEntries[], size_t numEntries); + + +protected: + /** Registry of event factory methods providing O(log(n)) lookup. */ + Registry m_registry; + + Event::BuildMethod *m_defaultBuildMethod; +}; + +inline const EventFactory::Registry & +EventFactory::GetRegistry() const +{ + return (m_registry); +} + +} // namespace DevCtl +#endif /*_DEVCTL_EVENT_FACTORY_H_ */ Index: projects/zfsd/head/lib/libdevdctl/exception.h =================================================================== --- projects/zfsd/head/lib/libdevdctl/exception.h (nonexistent) +++ projects/zfsd/head/lib/libdevdctl/exception.h (revision 289684) @@ -0,0 +1,166 @@ +/*- + * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation + * All rights reserved. + * + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * 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 MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * Authors: Justin T. Gibbs (Spectra Logic Corporation) + */ + +/** + * \file zfsd_exception.h + * + * Definition of the ZfsdException class hierarchy. All exceptions + * explicitly thrown by Zfsd are defined here. + */ +#ifndef _DEVCTL_EXCEPTION_H_ +#define _DEVCTL_EXCEPTION_H_ + +/*============================ Namespace Control =============================*/ +namespace DevCtl +{ + +/*============================= Class Definitions ============================*/ + +/*--------------------------------- Exception --------------------------------*/ +/** + * \brief Class allowing unified reporting/logging of exceptional events. + */ +class Exception +{ +public: + /** + * \brief Exception constructor allowing arbitrary string + * data to be reported. + * + * \param fmt Printf-like string format specifier. + */ + Exception(const char *fmt, ...); + + /** + * \brief Augment/Modify a Exception's string data. + */ + std::string& GetString(); + + /** + * \brief Emit exception data to syslog(3). + */ + virtual void Log() const; + +protected: + Exception(); + + /** + * \brief Convert exception string format and arguments provided + * in event constructors into a linear string. + */ + void FormatLog(const char *fmt, va_list ap); + + std::string m_log; +}; + +inline std::string & +Exception::GetString() +{ + return (m_log); +} + +/*------------------------------ ParseException ------------------------------*/ +/** + * Exception thrown when an event string is not converted to an actionable + * Event object. + */ +class ParseException : public Exception +{ +public: + enum Type + { + /** Improperly formatted event string encounterd. */ + INVALID_FORMAT, + + /** No handlers for this event type. */ + DISCARDED_EVENT_TYPE, + + /** Unhandled event type. */ + UNKNOWN_EVENT_TYPE + }; + + /** + * Constructor + * + * \param type The type of this exception. + * \param parsedBuffer The parsing buffer active at the time of + * the exception. + * \param offset The location in the parse buffer where this + * exception occurred. + */ + ParseException(Type type, const std::string &parsedBuffer, + size_t offset = 0); + + /** + * Accessor + * + * \return The classification for this exception. + */ + Type GetType() const; + + /** + * Accessor + * + * \return The offset into the event string where this exception + * occurred. + */ + size_t GetOffset() const; + +private: + /** The type of this exception. */ + Type m_type; + + /** The parsing buffer that was active at the time of the exception. */ + const std::string m_parsedBuffer; + + /** + * The offset into the event string buffer from where this + * exception was triggered. + */ + size_t m_offset; +}; + +//- ParseException Inline Const Public Methods --------------------------------- +inline ParseException::Type +ParseException::GetType() const +{ + return (m_type); +} + +inline size_t +ParseException::GetOffset() const +{ + return (m_offset); +} + +} // namespace DevCtl +#endif /* _DEVCTL_EXCEPTION_H_ */ Index: projects/zfsd/head/lib/libdevdctl/guid.cc =================================================================== --- projects/zfsd/head/lib/libdevdctl/guid.cc (nonexistent) +++ projects/zfsd/head/lib/libdevdctl/guid.cc (revision 289684) @@ -0,0 +1,82 @@ +/*- + * Copyright (c) 2012, 2013 Spectra Logic Corporation + * All rights reserved. + * + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * 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 MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * Authors: Alan Somers (Spectra Logic Corporation) + * + * $FreeBSD$ + */ + +/** + * \file guid.cc + * + * Implementation of the Guid class. + */ +#include + +#include +#include +#include + +#include +#include + +#include "guid.h" + +__FBSDID("$FreeBSD$"); +/*============================ Namespace Control =============================*/ +using std::string; +namespace DevCtl +{ + +/*=========================== Class Implementations ==========================*/ +/*----------------------------------- Guid -----------------------------------*/ +Guid::Guid(const string &guidString) +{ + if (guidString.empty()) { + m_GUID = INVALID_GUID; + } else { + /* + * strtoumax() returns zero on conversion failure + * which nicely matches our choice for INVALID_GUID. + */ + m_GUID = (uint64_t)strtoumax(guidString.c_str(), NULL, 0); + } +} + +std::ostream& +operator<< (std::ostream& out, Guid g) +{ + if (g.IsValid()) + out << (uint64_t)g; + else + out << "None"; + return (out); +} + +} // namespace DevCtl Index: projects/zfsd/head/lib/libdevdctl/guid.h =================================================================== --- projects/zfsd/head/lib/libdevdctl/guid.h (nonexistent) +++ projects/zfsd/head/lib/libdevdctl/guid.h (revision 289684) @@ -0,0 +1,143 @@ +/*- + * Copyright (c) 2012, 2013 Spectra Logic Corporation + * All rights reserved. + * + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * 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 MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * Authors: Alan Somers (Spectra Logic Corporation) + * + * $FreeBSD$ + */ + +/** + * \file devctl_guid.h + * + * Definition of the Guid class. + */ +#ifndef _DEVCTL_GUID_H_ +#define _DEVCTL_GUID_H_ + +/*============================ Namespace Control =============================*/ +namespace DevCtl +{ + +/*============================= Class Definitions ============================*/ +/*----------------------------------- Guid -----------------------------------*/ +/** + * \brief Object that represents guids. + * + * It can generally be manipulated as a uint64_t, but with a special + * value INVALID_GUID that does not equal any valid guid. + * + * As of this writing, this class is only used to to represent ZFS + * guids in events and spa_generate_guid() in spa_misc.c explicitly + * refuses to return a guid of 0. So this class uses 0 as the value + * for INVALID_GUID. In the future, if 0 is allowed to be a valid + * guid, the implementation of this class must change. + */ +class Guid +{ +public: + /* Constructors */ + Guid(); + Guid(uint64_t guid); + Guid(const std::string &guid); + + /* Assignment */ + Guid& operator=(const Guid& rhs); + + /* Test the validity of this guid. */ + bool IsValid() const; + + /* Comparison to other Guid operators */ + bool operator==(const Guid& rhs) const; + bool operator!=(const Guid& rhs) const; + + /* Integer conversion operators */ + operator uint64_t() const; + operator bool() const; + + static const uint64_t INVALID_GUID = 0; +protected: + /* The integer value of the GUID. */ + uint64_t m_GUID; +}; + +//- Guid Inline Public Methods ------------------------------------------------ +inline +Guid::Guid() + : m_GUID(INVALID_GUID) +{ +} + +inline +Guid::Guid(uint64_t guid) + : m_GUID(guid) +{ +} + +inline Guid& +Guid::operator=(const Guid &rhs) +{ + m_GUID = rhs.m_GUID; + return (*this); +} + +inline bool +Guid::IsValid() const +{ + return (m_GUID != INVALID_GUID); +} + +inline bool +Guid::operator==(const Guid& rhs) const +{ + return (m_GUID == rhs.m_GUID); +} + +inline bool +Guid::operator!=(const Guid& rhs) const +{ + return (m_GUID != rhs.m_GUID); +} + +inline +Guid::operator uint64_t() const +{ + return (m_GUID); +} + +inline +Guid::operator bool() const +{ + return (m_GUID != INVALID_GUID); +} + +/** Convert the GUID into its string representation */ +std::ostream& operator<< (std::ostream& out, Guid g); + +} // namespace DevCtl +#endif /* _DEVCTL_GUID_H_ */ Index: projects/zfsd/head/lib/libdevdctl/reader.cc =================================================================== --- projects/zfsd/head/lib/libdevdctl/reader.cc (nonexistent) +++ projects/zfsd/head/lib/libdevdctl/reader.cc (revision 289684) @@ -0,0 +1,99 @@ +/*- + * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation + * All rights reserved. + * + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * 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 MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * Authors: Alan Somers (Spectra Logic Corporation) + */ + +/** + * \file reader.cc + */ + +#include +#include + +#include +#include +#include +#include + +#include + +#include "reader.h" + +__FBSDID("$FreeBSD$"); + +/*============================ Namespace Control =============================*/ +namespace DevCtl +{ + +//- FDReader Public Methods --------------------------------------------------- +FDReader::FDReader(int fd) + : m_fd(fd) +{ +} + +ssize_t +FDReader::read(char* buf, size_t count) +{ + return (::read(m_fd, buf, count)); +} + +ssize_t +FDReader::in_avail() const +{ + int bytes; + if (ioctl(m_fd, FIONREAD, &bytes)) { + syslog(LOG_ERR, "ioctl FIONREAD: %s", strerror(errno)); + return (-1); + } + return (bytes); +} + +//- IstreamReader Inline Public Methods ---------------------------------------- +IstreamReader::IstreamReader(std::istream* stream) + : m_stream(stream) +{ +} + +ssize_t +IstreamReader::read(char* buf, size_t count) +{ + m_stream->read(buf, count); + if (m_stream->fail()) + return (-1); + return (m_stream->gcount()); +} + +ssize_t +IstreamReader::in_avail() const +{ + return (m_stream->rdbuf()->in_avail()); +} + +} // namespace DevCtl Index: projects/zfsd/head/lib/libdevdctl/reader.h =================================================================== --- projects/zfsd/head/lib/libdevdctl/reader.h (nonexistent) +++ projects/zfsd/head/lib/libdevdctl/reader.h (revision 289684) @@ -0,0 +1,136 @@ +/*- + * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation + * All rights reserved. + * + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * 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 MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * Authors: Justin T. Gibbs (Spectra Logic Corporation) + * + * $FreeBSD$ + */ + +/** + * \file devctl_reader.h + */ +#ifndef _DEVCTL_READER_H_ +#define _DEVCTL_READER_H_ + +/*=========================== Forward Declarations ===========================*/ + +/*============================ Namespace Control =============================*/ +namespace DevCtl +{ + +/*============================= Class Definitions ============================*/ + +/*-------------------------------- Reader -------------------------------*/ +/** + * \brief A class that presents a common interface to both file descriptors + * and istreams. + * + * Standard C++ provides no way to create an iostream from a file descriptor or + * a FILE. The GNU, Apache, HPUX, and Solaris C++ libraries all provide + * non-standard ways to construct such a stream using similar semantics, but + * FreeBSD's C++ library does not. This class supports only the functionality + * needed by ZFSD; it does not implement the iostream API. + */ +class Reader +{ +public: + /** + * \brief Return the number of bytes immediately available for reading + */ + virtual ssize_t in_avail() const = 0; + + /** + * \brief Reads up to count bytes + * + * Whether this call blocks depends on the underlying input source. + * On error, -1 is returned, and errno will be set by the underlying + * source. + * + * \param buf Destination for the data + * \param count Maximum amount of data to read + * \returns Amount of data that was actually read + */ + virtual ssize_t read(char* buf, size_t count) = 0; + + virtual ~Reader() = 0; +}; + +inline Reader::~Reader() {} + + +/*--------------------------------- FDReader ---------------------------------*/ +/** + * \brief Specialization of Reader that uses a file descriptor + */ +class FDReader : public Reader +{ +public: + /** + * \brief Constructor + * + * \param fd An open file descriptor. It will not be garbage + * collected by the destructor. + */ + FDReader(int fd); + + virtual ssize_t in_avail() const; + + virtual ssize_t read(char* buf, size_t count); + +protected: + /** Copy of the underlying file descriptor */ + int m_fd; +}; + +/*-------------------------------- IstreamReader------------------------------*/ +/** + * \brief Specialization of Reader that uses a std::istream + */ +class IstreamReader : public Reader +{ +public: + /** + * Constructor + * + * \param stream Pointer to an open istream. It will not be + * garbage collected by the destructor. + */ + IstreamReader(std::istream* stream); + + virtual ssize_t in_avail() const; + + virtual ssize_t read(char* buf, size_t count); + +protected: + /** Copy of the underlying stream */ + std::istream *m_stream; +}; + +} // namespace DevCtl +#endif /* _DEVCTL_READER_H_ */ Index: projects/zfsd/head/share/mk/bsd.libnames.mk =================================================================== --- projects/zfsd/head/share/mk/bsd.libnames.mk (revision 289683) +++ projects/zfsd/head/share/mk/bsd.libnames.mk (revision 289684) @@ -1,149 +1,149 @@ # $FreeBSD$ # The include file define library names. # Other include files (e.g. bsd.prog.mk, bsd.lib.mk) include this # file where necessary. .if !target(____) .error bsd.libnames.mk cannot be included directly. .endif .sinclude LIBCRT0?= ${DESTDIR}${LIBDIR}/crt0.o LIBALIAS?= ${DESTDIR}${LIBDIR}/libalias.a LIBARCHIVE?= ${DESTDIR}${LIBDIR}/libarchive.a LIBASN1?= ${DESTDIR}${LIBDIR}/libasn1.a LIBATM?= ${DESTDIR}${LIBDIR}/libatm.a LIBAUDITD?= ${DESTDIR}${LIBDIR}/libauditd.a LIBAVL?= ${DESTDIR}${LIBDIR}/libavl.a LIBBEGEMOT?= ${DESTDIR}${LIBDIR}/libbegemot.a LIBBLUETOOTH?= ${DESTDIR}${LIBDIR}/libbluetooth.a LIBBSDXML?= ${DESTDIR}${LIBDIR}/libbsdxml.a LIBBSM?= ${DESTDIR}${LIBDIR}/libbsm.a LIBBSNMP?= ${DESTDIR}${LIBDIR}/libbsnmp.a LIBBZ2?= ${DESTDIR}${LIBDIR}/libbz2.a LIBCXXRT?= ${DESTDIR}${LIBDIR}/libcxxrt.a LIBCPLUSPLUS?= ${DESTDIR}${LIBDIR}/libc++.a LIBC?= ${DESTDIR}${LIBDIR}/libc.a LIBC_PIC?= ${DESTDIR}${LIBDIR}/libc_pic.a LIBCALENDAR?= ${DESTDIR}${LIBDIR}/libcalendar.a LIBCAM?= ${DESTDIR}${LIBDIR}/libcam.a LIBCAPSICUM?= ${DESTDIR}${LIBDIR}/libcapsicum.a LIBCASPER?= ${DESTDIR}${LIBDIR}/libcasper.a LIBCOM_ERR?= ${DESTDIR}${LIBDIR}/libcom_err.a LIBCOMPAT?= ${DESTDIR}${LIBDIR}/libcompat.a LIBCOMPILER_RT?=${DESTDIR}${LIBDIR}/libcompiler_rt.a LIBCRYPT?= ${DESTDIR}${LIBDIR}/libcrypt.a LIBCRYPTO?= ${DESTDIR}${LIBDIR}/libcrypto.a LIBCTF?= ${DESTDIR}${LIBDIR}/libctf.a LIBCURSES?= ${DESTDIR}${LIBDIR}/libcurses.a -LIBDEVCLT?= ${DESTDIR}${LIBDIR}/libdevctl.a +LIBDEVDCTL?= ${DESTDIR}${LIBDIR}/libdevdctl.a LIBDEVINFO?= ${DESTDIR}${LIBDIR}/libdevinfo.a LIBDEVSTAT?= ${DESTDIR}${LIBDIR}/libdevstat.a LIBDIALOG?= ${DESTDIR}${LIBDIR}/libdialog.a LIBDNS?= ${DESTDIR}${LIBDIR}/libdns.a LIBDPV?= ${DESTDIR}${LIBDIR}/libdpv.a LIBDTRACE?= ${DESTDIR}${LIBDIR}/libdtrace.a LIBDWARF?= ${DESTDIR}${LIBDIR}/libdwarf.a LIBEDIT?= ${DESTDIR}${LIBDIR}/libedit.a LIBELF?= ${DESTDIR}${LIBDIR}/libelf.a LIBEXECINFO?= ${DESTDIR}${LIBDIR}/libexecinfo.a LIBFETCH?= ${DESTDIR}${LIBDIR}/libfetch.a LIBFIGPAR?= ${DESTDIR}${LIBDIR}/libfigpar.a LIBFL?= "don't use LIBFL, use LIBL" LIBFORM?= ${DESTDIR}${LIBDIR}/libform.a LIBG2C?= ${DESTDIR}${LIBDIR}/libg2c.a LIBGPIO?= ${DESTDIR}${LIBDIR}/libgpio.a LIBGEOM?= ${DESTDIR}${LIBDIR}/libgeom.a LIBGNUREGEX?= ${DESTDIR}${LIBDIR}/libgnuregex.a LIBGSSAPI?= ${DESTDIR}${LIBDIR}/libgssapi.a LIBGSSAPI_KRB5?= ${DESTDIR}${LIBDIR}/libgssapi_krb5.a LIBHDB?= ${DESTDIR}${LIBDIR}/libhdb.a LIBHEIMBASE?= ${DESTDIR}${LIBDIR}/libheimbase.a LIBHEIMNTLM?= ${DESTDIR}${LIBDIR}/libheimntlm.a LIBHEIMSQLITE?= ${DESTDIR}${LIBDIR}/libheimsqlite.a LIBHX509?= ${DESTDIR}${LIBDIR}/libhx509.a LIBIPSEC?= ${DESTDIR}${LIBDIR}/libipsec.a LIBJAIL?= ${DESTDIR}${LIBDIR}/libjail.a LIBKADM5CLNT?= ${DESTDIR}${LIBDIR}/libkadm5clnt.a LIBKADM5SRV?= ${DESTDIR}${LIBDIR}/libkadm5srv.a LIBKAFS5?= ${DESTDIR}${LIBDIR}/libkafs5.a LIBKDC?= ${DESTDIR}${LIBDIR}/libkdc.a LIBKEYCAP?= ${DESTDIR}${LIBDIR}/libkeycap.a LIBKICONV?= ${DESTDIR}${LIBDIR}/libkiconv.a LIBKRB5?= ${DESTDIR}${LIBDIR}/libkrb5.a LIBKVM?= ${DESTDIR}${LIBDIR}/libkvm.a LIBL?= ${DESTDIR}${LIBDIR}/libl.a LIBLN?= "don't use LIBLN, use LIBL" LIBLZMA?= ${DESTDIR}${LIBDIR}/liblzma.a LIBM?= ${DESTDIR}${LIBDIR}/libm.a LIBMAGIC?= ${DESTDIR}${LIBDIR}/libmagic.a LIBMD?= ${DESTDIR}${LIBDIR}/libmd.a LIBMEMSTAT?= ${DESTDIR}${LIBDIR}/libmemstat.a LIBMENU?= ${DESTDIR}${LIBDIR}/libmenu.a LIBMILTER?= ${DESTDIR}${LIBDIR}/libmilter.a LIBMP?= ${DESTDIR}${LIBDIR}/libmp.a LIBNCURSES?= ${DESTDIR}${LIBDIR}/libncurses.a LIBNCURSESW?= ${DESTDIR}${LIBDIR}/libncursesw.a LIBNETGRAPH?= ${DESTDIR}${LIBDIR}/libnetgraph.a LIBNGATM?= ${DESTDIR}${LIBDIR}/libngatm.a LIBNV?= ${DESTDIR}${LIBDIR}/libnv.a LIBNVPAIR?= ${DESTDIR}${LIBDIR}/libnvpair.a LIBOPIE?= ${DESTDIR}${LIBDIR}/libopie.a LIBPAM?= ${DESTDIR}${LIBDIR}/libpam.a LIBPANEL?= ${DESTDIR}${LIBDIR}/libpanel.a LIBPCAP?= ${DESTDIR}${LIBDIR}/libpcap.a LIBPJDLOG?= ${DESTDIR}${LIBDIR}/libpjdlog.a LIBPMC?= ${DESTDIR}${LIBDIR}/libpmc.a LIBPROC?= ${DESTDIR}${LIBDIR}/libproc.a LIBPROCSTAT?= ${DESTDIR}${LIBDIR}/libprocstat.a LIBPTHREAD?= ${DESTDIR}${LIBDIR}/libpthread.a LIBRADIUS?= ${DESTDIR}${LIBDIR}/libradius.a LIBROKEN?= ${DESTDIR}${LIBDIR}/libroken.a LIBRPCSVC?= ${DESTDIR}${LIBDIR}/librpcsvc.a LIBRPCSEC_GSS?= ${DESTDIR}${LIBDIR}/librpcsec_gss.a LIBRT?= ${DESTDIR}${LIBDIR}/librt.a LIBRTLD_DB?= ${DESTDIR}${LIBDIR}/librtld_db.a LIBSBUF?= ${DESTDIR}${LIBDIR}/libsbuf.a LIBSDP?= ${DESTDIR}${LIBDIR}/libsdp.a LIBSMB?= ${DESTDIR}${LIBDIR}/libsmb.a LIBSSL?= ${DESTDIR}${LIBDIR}/libssl.a LIBSSP_NONSHARED?= ${DESTDIR}${LIBDIR}/libssp_nonshared.a LIBSTAND?= ${DESTDIR}${LIBDIR}/libstand.a LIBSTDCPLUSPLUS?= ${DESTDIR}${LIBDIR}/libstdc++.a LIBTACPLUS?= ${DESTDIR}${LIBDIR}/libtacplus.a LIBTERMCAP?= ${DESTDIR}${LIBDIR}/libtermcap.a LIBTERMCAPW?= ${DESTDIR}${LIBDIR}/libtermcapw.a LIBTERMLIB?= "don't use LIBTERMLIB, use LIBTERMCAP" LIBTINFO?= "don't use LIBTINFO, use LIBNCURSES" LIBUFS?= ${DESTDIR}${LIBDIR}/libufs.a LIBUGIDFW?= ${DESTDIR}${LIBDIR}/libugidfw.a LIBUMEM?= ${DESTDIR}${LIBDIR}/libumem.a LIBUSBHID?= ${DESTDIR}${LIBDIR}/libusbhid.a LIBUSB?= ${DESTDIR}${LIBDIR}/libusb.a LIBULOG?= ${DESTDIR}${LIBDIR}/libulog.a LIBUTIL?= ${DESTDIR}${LIBDIR}/libutil.a LIBUUTIL?= ${DESTDIR}${LIBDIR}/libuutil.a LIBVGL?= ${DESTDIR}${LIBDIR}/libvgl.a LIBVMMAPI?= ${DESTDIR}${LIBDIR}/libvmmapi.a LIBWIND?= ${DESTDIR}${LIBDIR}/libwind.a LIBWRAP?= ${DESTDIR}${LIBDIR}/libwrap.a LIBXPG4?= ${DESTDIR}${LIBDIR}/libxpg4.a LIBY?= ${DESTDIR}${LIBDIR}/liby.a LIBYPCLNT?= ${DESTDIR}${LIBDIR}/libypclnt.a LIBZ?= ${DESTDIR}${LIBDIR}/libz.a LIBZFS?= ${DESTDIR}${LIBDIR}/libzfs.a LIBZFS_CORE?= ${DESTDIR}${LIBDIR}/libzfs_core.a LIBZPOOL?= ${DESTDIR}${LIBDIR}/libzpool.a # enforce the 2 -lpthread and -lc to always be the last in that exact order .if defined(LDADD) .if ${LDADD:M-lpthread} LDADD:= ${LDADD:N-lpthread} -lpthread .endif .if ${LDADD:M-lc} LDADD:= ${LDADD:N-lc} -lc .endif .endif