/*-1* Copyright (c) 2011, 2012, 2013, 2016 Spectra Logic Corporation2* All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions, and the following disclaimer,9* without modification.10* 2. Redistributions in binary form must reproduce at minimum a disclaimer11* substantially similar to the "NO WARRANTY" disclaimer below12* ("Disclaimer") and any redistribution must be conditioned upon13* including a substantially similar Disclaimer requirement for further14* binary redistribution.15*16* NO WARRANTY17* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS18* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT19* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR20* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT21* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL22* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS23* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)24* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,25* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING26* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE27* POSSIBILITY OF SUCH DAMAGES.28*29* Authors: Justin T. Gibbs (Spectra Logic Corporation)30*/3132/**33* \file devdctl_event.h34*35* \brief Class hierarchy used to express events received via36* the devdctl API.37*/3839#ifndef _DEVDCTL_EVENT_H_40#define _DEVDCTL_EVENT_H_4142/*============================ Namespace Control =============================*/43namespace DevdCtl44{4546/*=========================== Forward Declarations ===========================*/47class EventFactory;4849/*============================= Class Definitions ============================*/50/*-------------------------------- NVPairMap ---------------------------------*/51/**52* NVPairMap is a specialization of the standard map STL container.53*/54typedef std::map<std::string, std::string> NVPairMap;5556/*----------------------------------- Event ----------------------------------*/57/**58* \brief Container for the name => value pairs that comprise the content of59* a device control event.60*61* All name => value data for events can be accessed via the Contains()62* and Value() methods. name => value pairs for data not explicitly63* received as a name => value pair are synthesized during parsing. For64* example, ATTACH and DETACH events have "device-name" and "parent"65* name => value pairs added.66*/67class Event68{69friend class EventFactory;7071public:72/** Event type */73enum Type {74/** Generic event notification. */75NOTIFY = '!',7677/** A driver was not found for this device. */78NOMATCH = '?',7980/** A bus device instance has been added. */81ATTACH = '+',8283/** A bus device instance has been removed. */84DETACH = '-'85};8687/**88* Factory method type to construct an Event given89* the type of event and an NVPairMap populated from90* the event string received from devd.91*/92typedef Event* (BuildMethod)(Type, NVPairMap &, const std::string &);9394/** Generic Event object factory. */95static BuildMethod Builder;9697static Event *CreateEvent(const EventFactory &factory,98const std::string &eventString);99100/**101* Returns the devname, if any, associated with the event102*103* \param name Devname, returned by reference104* \return True iff the event contained a devname105*/106virtual bool DevName(std::string &name) const;107108/**109* Returns the absolute pathname of the device associated with this110* event.111*112* \param name Devname, returned by reference113* \return True iff the event contained a devname114*/115bool DevPath(std::string &path) const;116117/**118* Returns true iff this event refers to a disk device119*/120bool IsDiskDev() const;121122/** Returns the physical path of the device, if any123*124* \param path Physical path, returned by reference125* \return True iff the event contains a device with a physical126* path127*/128bool PhysicalPath(std::string &path) const;129130/**131* Provide a user friendly string representation of an132* event type.133*134* \param type The type of event to map to a string.135*136* \return A user friendly string representing the input type.137*/138static const char *TypeToString(Type type);139140/**141* Determine the availability of a name => value pair by name.142*143* \param name The key name to search for in this event instance.144*145* \return true if the specified key is available in this146* event, otherwise false.147*/148bool Contains(const std::string &name) const;149150/**151* \param key The name of the key for which to retrieve its152* associated value.153*154* \return A const reference to the string representing the155* value associated with key.156*157* \note For key's with no registered value, the empty string158* is returned.159*/160const std::string &Value(const std::string &key) const;161162/**163* Get the type of this event instance.164*165* \return The type of this event instance.166*/167Type GetType() const;168169/**170* Get the original DevdCtl event string for this event.171*172* \return The DevdCtl event string.173*/174const std::string &GetEventString() const;175176/**177* Convert the event instance into a string suitable for178* printing to the console or emitting to syslog.179*180* \return A string of formatted event data.181*/182std::string ToString() const;183184/**185* Pretty-print this event instance to cout.186*/187void Print() const;188189/**190* Pretty-print this event instance to syslog.191*192* \param priority The logging priority/facility.193* See syslog(3).194*/195void Log(int priority) const;196197/**198* Create and return a fully independent clone199* of this event.200*/201virtual Event *DeepCopy() const;202203/** Destructor */204virtual ~Event();205206/**207* Interpret and perform any actions necessary to208* consume the event.209*210* \return True if this event should be queued for later reevaluation211*/212virtual bool Process() const;213214/**215* Get the time that the event was created216*/217timeval GetTimestamp() const;218219/**220* Add a timestamp to the event string, if one does not already exist221* TODO: make this an instance method that operates on the std::map222* instead of the string. We must fix zfsd's CaseFile serialization223* routines first, so that they don't need the raw event string.224*225* \param[in,out] eventString The devd event string to modify226*/227static void TimestampEventString(std::string &eventString);228229/**230* Access all parsed key => value pairs.231*/232const NVPairMap &GetMap() const;233234protected:235/** Table entries used to map a type to a user friendly string. */236struct EventTypeRecord237{238Type m_type;239const char *m_typeName;240};241242/**243* Constructor244*245* \param type The type of event to create.246*/247Event(Type type, NVPairMap &map, const std::string &eventString);248249/** Deep copy constructor. */250Event(const Event &src);251252/** Always empty string returned when NVPairMap lookups fail. */253static const std::string s_theEmptyString;254255/** Unsorted table of event types. */256static EventTypeRecord s_typeTable[];257258/** The type of this event. */259const Type m_type;260261/**262* Event attribute storage.263*264* \note Although stored by reference (since m_nvPairs can265* never be NULL), the NVPairMap referenced by this field266* is dynamically allocated and owned by this event object.267* m_nvPairs must be deleted at event destruction.268*/269NVPairMap &m_nvPairs;270271/**272* The unaltered event string, as received from devd, used to273* create this event object.274*/275std::string m_eventString;276277private:278/**279* Ingest event data from the supplied string.280*281* \param[in] eventString The string of devd event data to parse.282* \param[out] nvpairs Returns the parsed data283*/284static void ParseEventString(Type type, const std::string &eventString,285NVPairMap &nvpairs);286};287288inline Event::Type289Event::GetType() const290{291return (m_type);292}293294inline const std::string &295Event::GetEventString() const296{297return (m_eventString);298}299300inline const NVPairMap &301Event::GetMap() const302{303return (m_nvPairs);304}305306/*--------------------------------- EventList --------------------------------*/307/**308* EventList is a specialization of the standard list STL container.309*/310typedef std::list<Event *> EventList;311312/*-------------------------------- DevfsEvent --------------------------------*/313class DevfsEvent : public Event314{315public:316/** Specialized Event object factory for Devfs events. */317static BuildMethod Builder;318319virtual Event *DeepCopy() const;320321/**322* Interpret and perform any actions necessary to323* consume the event.324* \return True if this event should be queued for later reevaluation325*/326virtual bool Process() const;327328bool IsWholeDev() const;329virtual bool DevName(std::string &name) const;330331protected:332/**333* Given the device name of a disk, determine if the device334* represents the whole device, not just a partition.335*336* \param devName Device name of disk device to test.337*338* \return True if the device name represents the whole device.339* Otherwise false.340*/341static bool IsWholeDev(const std::string &devName);342343/** DeepCopy Constructor. */344DevfsEvent(const DevfsEvent &src);345346/** Constructor */347DevfsEvent(Type, NVPairMap &, const std::string &);348};349350/*--------------------------------- GeomEvent --------------------------------*/351class GeomEvent : public Event352{353public:354/** Specialized Event object factory for GEOM events. */355static BuildMethod Builder;356357virtual Event *DeepCopy() const;358359virtual bool DevName(std::string &name) const;360361const std::string &DeviceName() const;362363protected:364/** Constructor */365GeomEvent(Type, NVPairMap &, const std::string &);366367/** Deep copy constructor. */368GeomEvent(const GeomEvent &src);369370std::string m_devname;371};372373/*--------------------------------- ZfsEvent ---------------------------------*/374class ZfsEvent : public Event375{376public:377/** Specialized Event object factory for ZFS events. */378static BuildMethod Builder;379380virtual Event *DeepCopy() const;381382virtual bool DevName(std::string &name) const;383384const std::string &PoolName() const;385Guid PoolGUID() const;386Guid VdevGUID() const;387388protected:389/** Constructor */390ZfsEvent(Type, NVPairMap &, const std::string &);391392/** Deep copy constructor. */393ZfsEvent(const ZfsEvent &src);394395Guid m_poolGUID;396Guid m_vdevGUID;397};398399//- ZfsEvent Inline Public Methods --------------------------------------------400inline const std::string&401ZfsEvent::PoolName() const402{403/* The pool name is reported as the subsystem of ZFS events. */404return (Value("subsystem"));405}406407inline Guid408ZfsEvent::PoolGUID() const409{410return (m_poolGUID);411}412413inline Guid414ZfsEvent::VdevGUID() const415{416return (m_vdevGUID);417}418419} // namespace DevdCtl420#endif /*_DEVDCTL_EVENT_H_ */421422423