/*- * Copyright (c) 2011, 2012, 2013, 2016 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 devdctl_event.h * * \brief Class hierarchy used to express events received via * the devdctl API. */ #ifndef _DEVDCTL_EVENT_H_ #define _DEVDCTL_EVENT_H_ /*============================ Namespace Control =============================*/ namespace DevdCtl { /*=========================== 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); /** * Returns the devname, if any, associated with the event * * \param name Devname, returned by reference * \return True iff the event contained a devname */ virtual bool DevName(std::string &name) const; /** * Returns the absolute pathname of the device associated with this * event. * * \param name Devname, returned by reference * \return True iff the event contained a devname */ bool DevPath(std::string &path) const; /** * Returns true iff this event refers to a disk device */ bool IsDiskDev() const; /** Returns the physical path of the device, if any * * \param path Physical path, returned by reference * \return True iff the event contains a device with a physical * path */ bool PhysicalPath(std::string &path) const; /** * 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 original DevdCtl event string for this event. * * \return The DevdCtl 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 destruction. */ 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 IsWholeDev() const; virtual bool DevName(std::string &name) const; protected: /** * 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 &); }; /*--------------------------------- GeomEvent --------------------------------*/ class GeomEvent : public Event { public: /** Specialized Event object factory for GEOM events. */ static BuildMethod Builder; virtual Event *DeepCopy() const; virtual bool DevName(std::string &name) const; const std::string &DeviceName() const; protected: /** Constructor */ GeomEvent(Type, NVPairMap &, const std::string &); /** Deep copy constructor. */ GeomEvent(const GeomEvent &src); std::string m_devname; }; /*--------------------------------- ZfsEvent ---------------------------------*/ class ZfsEvent : public Event { public: /** Specialized Event object factory for ZFS events. */ static BuildMethod Builder; virtual Event *DeepCopy() const; virtual bool DevName(std::string &name) 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 DevdCtl #endif /*_DEVDCTL_EVENT_H_ */