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