1 /*- 2 * Copyright (c) 2011, 2012, 2013, 2016 Spectra Logic Corporation 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions, and the following disclaimer, 10 * without modification. 11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12 * substantially similar to the "NO WARRANTY" disclaimer below 13 * ("Disclaimer") and any redistribution must be conditioned upon 14 * including a substantially similar Disclaimer requirement for further 15 * binary redistribution. 16 * 17 * NO WARRANTY 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGES. 29 * 30 * Authors: Justin T. Gibbs (Spectra Logic Corporation) 31 */ 32 33 /** 34 * \file devdctl_event.h 35 * 36 * \brief Class hierarchy used to express events received via 37 * the devdctl API. 38 */ 39 40 #ifndef _DEVDCTL_EVENT_H_ 41 #define _DEVDCTL_EVENT_H_ 42 43 /*============================ Namespace Control =============================*/ 44 namespace DevdCtl 45 { 46 47 /*=========================== Forward Declarations ===========================*/ 48 class EventFactory; 49 50 /*============================= Class Definitions ============================*/ 51 /*-------------------------------- NVPairMap ---------------------------------*/ 52 /** 53 * NVPairMap is a specialization of the standard map STL container. 54 */ 55 typedef std::map<std::string, std::string> NVPairMap; 56 57 /*----------------------------------- Event ----------------------------------*/ 58 /** 59 * \brief Container for the name => value pairs that comprise the content of 60 * a device control event. 61 * 62 * All name => value data for events can be accessed via the Contains() 63 * and Value() methods. name => value pairs for data not explicitly 64 * received as a name => value pair are synthesized during parsing. For 65 * example, ATTACH and DETACH events have "device-name" and "parent" 66 * name => value pairs added. 67 */ 68 class Event 69 { 70 friend class EventFactory; 71 72 public: 73 /** Event type */ 74 enum Type { 75 /** Generic event notification. */ 76 NOTIFY = '!', 77 78 /** A driver was not found for this device. */ 79 NOMATCH = '?', 80 81 /** A bus device instance has been added. */ 82 ATTACH = '+', 83 84 /** A bus device instance has been removed. */ 85 DETACH = '-' 86 }; 87 88 /** 89 * Factory method type to construct an Event given 90 * the type of event and an NVPairMap populated from 91 * the event string received from devd. 92 */ 93 typedef Event* (BuildMethod)(Type, NVPairMap &, const std::string &); 94 95 /** Generic Event object factory. */ 96 static BuildMethod Builder; 97 98 static Event *CreateEvent(const EventFactory &factory, 99 const std::string &eventString); 100 101 /** 102 * Returns the devname, if any, associated with the event 103 * 104 * \param name Devname, returned by reference 105 * \return True iff the event contained a devname 106 */ 107 virtual bool DevName(std::string &name) const; 108 109 /** 110 * Returns the absolute pathname of the device associated with this 111 * event. 112 * 113 * \param name Devname, returned by reference 114 * \return True iff the event contained a devname 115 */ 116 bool DevPath(std::string &path) const; 117 118 /** 119 * Returns true iff this event refers to a disk device 120 */ 121 bool IsDiskDev() const; 122 123 /** Returns the physical path of the device, if any 124 * 125 * \param path Physical path, returned by reference 126 * \return True iff the event contains a device with a physical 127 * path 128 */ 129 bool PhysicalPath(std::string &path) const; 130 131 /** 132 * Provide a user friendly string representation of an 133 * event type. 134 * 135 * \param type The type of event to map to a string. 136 * 137 * \return A user friendly string representing the input type. 138 */ 139 static const char *TypeToString(Type type); 140 141 /** 142 * Determine the availability of a name => value pair by name. 143 * 144 * \param name The key name to search for in this event instance. 145 * 146 * \return true if the specified key is available in this 147 * event, otherwise false. 148 */ 149 bool Contains(const std::string &name) const; 150 151 /** 152 * \param key The name of the key for which to retrieve its 153 * associated value. 154 * 155 * \return A const reference to the string representing the 156 * value associated with key. 157 * 158 * \note For key's with no registered value, the empty string 159 * is returned. 160 */ 161 const std::string &Value(const std::string &key) const; 162 163 /** 164 * Get the type of this event instance. 165 * 166 * \return The type of this event instance. 167 */ 168 Type GetType() const; 169 170 /** 171 * Get the original DevdCtl event string for this event. 172 * 173 * \return The DevdCtl event string. 174 */ 175 const std::string &GetEventString() const; 176 177 /** 178 * Convert the event instance into a string suitable for 179 * printing to the console or emitting to syslog. 180 * 181 * \return A string of formatted event data. 182 */ 183 std::string ToString() const; 184 185 /** 186 * Pretty-print this event instance to cout. 187 */ 188 void Print() const; 189 190 /** 191 * Pretty-print this event instance to syslog. 192 * 193 * \param priority The logging priority/facility. 194 * See syslog(3). 195 */ 196 void Log(int priority) const; 197 198 /** 199 * Create and return a fully independent clone 200 * of this event. 201 */ 202 virtual Event *DeepCopy() const; 203 204 /** Destructor */ 205 virtual ~Event(); 206 207 /** 208 * Interpret and perform any actions necessary to 209 * consume the event. 210 * 211 * \return True if this event should be queued for later reevaluation 212 */ 213 virtual bool Process() const; 214 215 /** 216 * Get the time that the event was created 217 */ 218 timeval GetTimestamp() const; 219 220 /** 221 * Add a timestamp to the event string, if one does not already exist 222 * TODO: make this an instance method that operates on the std::map 223 * instead of the string. We must fix zfsd's CaseFile serialization 224 * routines first, so that they don't need the raw event string. 225 * 226 * \param[in,out] eventString The devd event string to modify 227 */ 228 static void TimestampEventString(std::string &eventString); 229 230 /** 231 * Access all parsed key => value pairs. 232 */ 233 const NVPairMap &GetMap() const; 234 235 protected: 236 /** Table entries used to map a type to a user friendly string. */ 237 struct EventTypeRecord 238 { 239 Type m_type; 240 const char *m_typeName; 241 }; 242 243 /** 244 * Constructor 245 * 246 * \param type The type of event to create. 247 */ 248 Event(Type type, NVPairMap &map, const std::string &eventString); 249 250 /** Deep copy constructor. */ 251 Event(const Event &src); 252 253 /** Always empty string returned when NVPairMap lookups fail. */ 254 static const std::string s_theEmptyString; 255 256 /** Unsorted table of event types. */ 257 static EventTypeRecord s_typeTable[]; 258 259 /** The type of this event. */ 260 const Type m_type; 261 262 /** 263 * Event attribute storage. 264 * 265 * \note Although stored by reference (since m_nvPairs can 266 * never be NULL), the NVPairMap referenced by this field 267 * is dynamically allocated and owned by this event object. 268 * m_nvPairs must be deleted at event destruction. 269 */ 270 NVPairMap &m_nvPairs; 271 272 /** 273 * The unaltered event string, as received from devd, used to 274 * create this event object. 275 */ 276 std::string m_eventString; 277 278 private: 279 /** 280 * Ingest event data from the supplied string. 281 * 282 * \param[in] eventString The string of devd event data to parse. 283 * \param[out] nvpairs Returns the parsed data 284 */ 285 static void ParseEventString(Type type, const std::string &eventString, 286 NVPairMap &nvpairs); 287 }; 288 289 inline Event::Type 290 Event::GetType() const 291 { 292 return (m_type); 293 } 294 295 inline const std::string & 296 Event::GetEventString() const 297 { 298 return (m_eventString); 299 } 300 301 inline const NVPairMap & 302 Event::GetMap() const 303 { 304 return (m_nvPairs); 305 } 306 307 /*--------------------------------- EventList --------------------------------*/ 308 /** 309 * EventList is a specialization of the standard list STL container. 310 */ 311 typedef std::list<Event *> EventList; 312 313 /*-------------------------------- DevfsEvent --------------------------------*/ 314 class DevfsEvent : public Event 315 { 316 public: 317 /** Specialized Event object factory for Devfs events. */ 318 static BuildMethod Builder; 319 320 virtual Event *DeepCopy() const; 321 322 /** 323 * Interpret and perform any actions necessary to 324 * consume the event. 325 * \return True if this event should be queued for later reevaluation 326 */ 327 virtual bool Process() const; 328 329 bool IsWholeDev() const; 330 virtual bool DevName(std::string &name) const; 331 332 protected: 333 /** 334 * Given the device name of a disk, determine if the device 335 * represents the whole device, not just a partition. 336 * 337 * \param devName Device name of disk device to test. 338 * 339 * \return True if the device name represents the whole device. 340 * Otherwise false. 341 */ 342 static bool IsWholeDev(const std::string &devName); 343 344 /** DeepCopy Constructor. */ 345 DevfsEvent(const DevfsEvent &src); 346 347 /** Constructor */ 348 DevfsEvent(Type, NVPairMap &, const std::string &); 349 }; 350 351 /*--------------------------------- GeomEvent --------------------------------*/ 352 class GeomEvent : public Event 353 { 354 public: 355 /** Specialized Event object factory for GEOM events. */ 356 static BuildMethod Builder; 357 358 virtual Event *DeepCopy() const; 359 360 virtual bool DevName(std::string &name) const; 361 362 const std::string &DeviceName() const; 363 364 protected: 365 /** Constructor */ 366 GeomEvent(Type, NVPairMap &, const std::string &); 367 368 /** Deep copy constructor. */ 369 GeomEvent(const GeomEvent &src); 370 371 std::string m_devname; 372 }; 373 374 /*--------------------------------- ZfsEvent ---------------------------------*/ 375 class ZfsEvent : public Event 376 { 377 public: 378 /** Specialized Event object factory for ZFS events. */ 379 static BuildMethod Builder; 380 381 virtual Event *DeepCopy() const; 382 383 virtual bool DevName(std::string &name) const; 384 385 const std::string &PoolName() const; 386 Guid PoolGUID() const; 387 Guid VdevGUID() const; 388 389 protected: 390 /** Constructor */ 391 ZfsEvent(Type, NVPairMap &, const std::string &); 392 393 /** Deep copy constructor. */ 394 ZfsEvent(const ZfsEvent &src); 395 396 Guid m_poolGUID; 397 Guid m_vdevGUID; 398 }; 399 400 //- ZfsEvent Inline Public Methods -------------------------------------------- 401 inline const std::string& 402 ZfsEvent::PoolName() const 403 { 404 /* The pool name is reported as the subsystem of ZFS events. */ 405 return (Value("subsystem")); 406 } 407 408 inline Guid 409 ZfsEvent::PoolGUID() const 410 { 411 return (m_poolGUID); 412 } 413 414 inline Guid 415 ZfsEvent::VdevGUID() const 416 { 417 return (m_vdevGUID); 418 } 419 420 } // namespace DevdCtl 421 #endif /*_DEVDCTL_EVENT_H_ */ 422