xref: /freebsd/lib/libdevdctl/event.h (revision edf8578117e8844e02c0121147f45e4609b30680)
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