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