diff options
Diffstat (limited to 'lib/libdevdctl/event.h')
-rw-r--r-- | lib/libdevdctl/event.h | 421 |
1 files changed, 421 insertions, 0 deletions
diff --git a/lib/libdevdctl/event.h b/lib/libdevdctl/event.h new file mode 100644 index 000000000000..162878bd6a65 --- /dev/null +++ b/lib/libdevdctl/event.h @@ -0,0 +1,421 @@ +/*- + * 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) + */ + +/** + * \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<std::string, std::string> 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<Event *> 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_ */ |