17a0c41d5SAlan Somers /*-
27a0c41d5SAlan Somers * Copyright (c) 2011, 2012, 2013, 2016 Spectra Logic Corporation
37a0c41d5SAlan Somers * All rights reserved.
47a0c41d5SAlan Somers *
57a0c41d5SAlan Somers * Redistribution and use in source and binary forms, with or without
67a0c41d5SAlan Somers * modification, are permitted provided that the following conditions
77a0c41d5SAlan Somers * are met:
87a0c41d5SAlan Somers * 1. Redistributions of source code must retain the above copyright
97a0c41d5SAlan Somers * notice, this list of conditions, and the following disclaimer,
107a0c41d5SAlan Somers * without modification.
117a0c41d5SAlan Somers * 2. Redistributions in binary form must reproduce at minimum a disclaimer
127a0c41d5SAlan Somers * substantially similar to the "NO WARRANTY" disclaimer below
137a0c41d5SAlan Somers * ("Disclaimer") and any redistribution must be conditioned upon
147a0c41d5SAlan Somers * including a substantially similar Disclaimer requirement for further
157a0c41d5SAlan Somers * binary redistribution.
167a0c41d5SAlan Somers *
177a0c41d5SAlan Somers * NO WARRANTY
187a0c41d5SAlan Somers * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
197a0c41d5SAlan Somers * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
207a0c41d5SAlan Somers * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
217a0c41d5SAlan Somers * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
227a0c41d5SAlan Somers * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
237a0c41d5SAlan Somers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
247a0c41d5SAlan Somers * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
257a0c41d5SAlan Somers * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
267a0c41d5SAlan Somers * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
277a0c41d5SAlan Somers * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
287a0c41d5SAlan Somers * POSSIBILITY OF SUCH DAMAGES.
297a0c41d5SAlan Somers *
307a0c41d5SAlan Somers * Authors: Justin T. Gibbs (Spectra Logic Corporation)
317a0c41d5SAlan Somers */
327a0c41d5SAlan Somers
337a0c41d5SAlan Somers /**
347a0c41d5SAlan Somers * \file event.cc
357a0c41d5SAlan Somers *
367a0c41d5SAlan Somers * Implementation of the class hierarchy used to express events
377a0c41d5SAlan Somers * received via the devdctl API.
387a0c41d5SAlan Somers */
397a0c41d5SAlan Somers #include <sys/cdefs.h>
407a0c41d5SAlan Somers #include <sys/disk.h>
417a0c41d5SAlan Somers #include <sys/filio.h>
427a0c41d5SAlan Somers #include <sys/param.h>
437a0c41d5SAlan Somers #include <sys/stat.h>
447a0c41d5SAlan Somers
457a0c41d5SAlan Somers #include <err.h>
467a0c41d5SAlan Somers #include <fcntl.h>
477a0c41d5SAlan Somers #include <inttypes.h>
487a0c41d5SAlan Somers #include <paths.h>
497a0c41d5SAlan Somers #include <stdlib.h>
507a0c41d5SAlan Somers #include <syslog.h>
517a0c41d5SAlan Somers #include <unistd.h>
527a0c41d5SAlan Somers
537a0c41d5SAlan Somers #include <cstdarg>
547a0c41d5SAlan Somers #include <cstring>
557a0c41d5SAlan Somers #include <iostream>
567a0c41d5SAlan Somers #include <list>
577a0c41d5SAlan Somers #include <map>
587a0c41d5SAlan Somers #include <sstream>
597a0c41d5SAlan Somers #include <string>
607a0c41d5SAlan Somers
617a0c41d5SAlan Somers #include "guid.h"
627a0c41d5SAlan Somers #include "event.h"
637a0c41d5SAlan Somers #include "event_factory.h"
647a0c41d5SAlan Somers #include "exception.h"
657a0c41d5SAlan Somers /*================================== Macros ==================================*/
667a0c41d5SAlan Somers #define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*x))
677a0c41d5SAlan Somers
687a0c41d5SAlan Somers /*============================ Namespace Control =============================*/
697a0c41d5SAlan Somers using std::cout;
707a0c41d5SAlan Somers using std::endl;
717a0c41d5SAlan Somers using std::string;
727a0c41d5SAlan Somers using std::stringstream;
737a0c41d5SAlan Somers
747a0c41d5SAlan Somers namespace DevdCtl
757a0c41d5SAlan Somers {
767a0c41d5SAlan Somers
777a0c41d5SAlan Somers /*=========================== Class Implementations ==========================*/
787a0c41d5SAlan Somers /*----------------------------------- Event ----------------------------------*/
797a0c41d5SAlan Somers //- Event Static Protected Data ------------------------------------------------
807a0c41d5SAlan Somers const string Event::s_theEmptyString;
817a0c41d5SAlan Somers
827a0c41d5SAlan Somers Event::EventTypeRecord Event::s_typeTable[] =
837a0c41d5SAlan Somers {
847a0c41d5SAlan Somers { Event::NOTIFY, "Notify" },
857a0c41d5SAlan Somers { Event::NOMATCH, "No Driver Match" },
867a0c41d5SAlan Somers { Event::ATTACH, "Attach" },
877a0c41d5SAlan Somers { Event::DETACH, "Detach" }
887a0c41d5SAlan Somers };
897a0c41d5SAlan Somers
907a0c41d5SAlan Somers //- Event Static Public Methods ------------------------------------------------
917a0c41d5SAlan Somers Event *
Builder(Event::Type type,NVPairMap & nvPairs,const string & eventString)927a0c41d5SAlan Somers Event::Builder(Event::Type type, NVPairMap &nvPairs,
937a0c41d5SAlan Somers const string &eventString)
947a0c41d5SAlan Somers {
957a0c41d5SAlan Somers return (new Event(type, nvPairs, eventString));
967a0c41d5SAlan Somers }
977a0c41d5SAlan Somers
987a0c41d5SAlan Somers Event *
CreateEvent(const EventFactory & factory,const string & eventString)997a0c41d5SAlan Somers Event::CreateEvent(const EventFactory &factory, const string &eventString)
1007a0c41d5SAlan Somers {
1017a0c41d5SAlan Somers NVPairMap &nvpairs(*new NVPairMap);
1027a0c41d5SAlan Somers Type type(static_cast<Event::Type>(eventString[0]));
1037a0c41d5SAlan Somers
1047a0c41d5SAlan Somers try {
1057a0c41d5SAlan Somers ParseEventString(type, eventString, nvpairs);
1067a0c41d5SAlan Somers } catch (const ParseException &exp) {
1077a0c41d5SAlan Somers if (exp.GetType() == ParseException::INVALID_FORMAT)
1087a0c41d5SAlan Somers exp.Log();
1097a0c41d5SAlan Somers return (NULL);
1107a0c41d5SAlan Somers }
1117a0c41d5SAlan Somers
1127a0c41d5SAlan Somers /*
1137a0c41d5SAlan Somers * Allow entries in our table for events with no system specified.
1147a0c41d5SAlan Somers * These entries should specify the string "none".
1157a0c41d5SAlan Somers */
1167a0c41d5SAlan Somers NVPairMap::iterator system_item(nvpairs.find("system"));
1177a0c41d5SAlan Somers if (system_item == nvpairs.end())
1187a0c41d5SAlan Somers nvpairs["system"] = "none";
1197a0c41d5SAlan Somers
1207a0c41d5SAlan Somers return (factory.Build(type, nvpairs, eventString));
1217a0c41d5SAlan Somers }
1227a0c41d5SAlan Somers
1237a0c41d5SAlan Somers bool
DevName(std::string & name) const1247a0c41d5SAlan Somers Event::DevName(std::string &name) const
1257a0c41d5SAlan Somers {
1267a0c41d5SAlan Somers return (false);
1277a0c41d5SAlan Somers }
1287a0c41d5SAlan Somers
1297a0c41d5SAlan Somers /* TODO: simplify this function with C++-11 <regex> methods */
1307a0c41d5SAlan Somers bool
IsDiskDev() const1317a0c41d5SAlan Somers Event::IsDiskDev() const
1327a0c41d5SAlan Somers {
1337a0c41d5SAlan Somers const int numDrivers = 2;
1347a0c41d5SAlan Somers static const char *diskDevNames[numDrivers] =
1357a0c41d5SAlan Somers {
1367a0c41d5SAlan Somers "da",
1377a0c41d5SAlan Somers "ada"
1387a0c41d5SAlan Somers };
1397a0c41d5SAlan Somers const char **dName;
1407a0c41d5SAlan Somers string devName;
1417a0c41d5SAlan Somers
1427a0c41d5SAlan Somers if (! DevName(devName))
1437a0c41d5SAlan Somers return false;
1447a0c41d5SAlan Somers
1457a0c41d5SAlan Somers size_t find_start = devName.rfind('/');
1467a0c41d5SAlan Somers if (find_start == string::npos) {
1477a0c41d5SAlan Somers find_start = 0;
1487a0c41d5SAlan Somers } else {
1497a0c41d5SAlan Somers /* Just after the last '/'. */
1507a0c41d5SAlan Somers find_start++;
1517a0c41d5SAlan Somers }
1527a0c41d5SAlan Somers
1537a0c41d5SAlan Somers for (dName = &diskDevNames[0];
1547a0c41d5SAlan Somers dName <= &diskDevNames[numDrivers - 1]; dName++) {
1557a0c41d5SAlan Somers
1567a0c41d5SAlan Somers size_t loc(devName.find(*dName, find_start));
1577a0c41d5SAlan Somers if (loc == find_start) {
1587a0c41d5SAlan Somers size_t prefixLen(strlen(*dName));
1597a0c41d5SAlan Somers
1607a0c41d5SAlan Somers if (devName.length() - find_start >= prefixLen
1617a0c41d5SAlan Somers && isdigit(devName[find_start + prefixLen]))
1627a0c41d5SAlan Somers return (true);
1637a0c41d5SAlan Somers }
1647a0c41d5SAlan Somers }
1657a0c41d5SAlan Somers
1667a0c41d5SAlan Somers return (false);
1677a0c41d5SAlan Somers }
1687a0c41d5SAlan Somers
1697a0c41d5SAlan Somers const char *
TypeToString(Event::Type type)1707a0c41d5SAlan Somers Event::TypeToString(Event::Type type)
1717a0c41d5SAlan Somers {
1727a0c41d5SAlan Somers EventTypeRecord *rec(s_typeTable);
1737a0c41d5SAlan Somers EventTypeRecord *lastRec(s_typeTable + NUM_ELEMENTS(s_typeTable) - 1);
1747a0c41d5SAlan Somers
1757a0c41d5SAlan Somers for (; rec <= lastRec; rec++) {
1767a0c41d5SAlan Somers if (rec->m_type == type)
1777a0c41d5SAlan Somers return (rec->m_typeName);
1787a0c41d5SAlan Somers }
1797a0c41d5SAlan Somers return ("Unknown");
1807a0c41d5SAlan Somers }
1817a0c41d5SAlan Somers
1827a0c41d5SAlan Somers //- Event Public Methods -------------------------------------------------------
1837a0c41d5SAlan Somers const string &
Value(const string & varName) const1847a0c41d5SAlan Somers Event::Value(const string &varName) const
1857a0c41d5SAlan Somers {
1867a0c41d5SAlan Somers NVPairMap::const_iterator item(m_nvPairs.find(varName));
1877a0c41d5SAlan Somers if (item == m_nvPairs.end())
1887a0c41d5SAlan Somers return (s_theEmptyString);
1897a0c41d5SAlan Somers
1907a0c41d5SAlan Somers return (item->second);
1917a0c41d5SAlan Somers }
1927a0c41d5SAlan Somers
1937a0c41d5SAlan Somers bool
Contains(const string & varName) const1947a0c41d5SAlan Somers Event::Contains(const string &varName) const
1957a0c41d5SAlan Somers {
1967a0c41d5SAlan Somers return (m_nvPairs.find(varName) != m_nvPairs.end());
1977a0c41d5SAlan Somers }
1987a0c41d5SAlan Somers
1997a0c41d5SAlan Somers string
ToString() const2007a0c41d5SAlan Somers Event::ToString() const
2017a0c41d5SAlan Somers {
2027a0c41d5SAlan Somers stringstream result;
2037a0c41d5SAlan Somers
2047a0c41d5SAlan Somers NVPairMap::const_iterator devName(m_nvPairs.find("device-name"));
2057a0c41d5SAlan Somers if (devName != m_nvPairs.end())
2067a0c41d5SAlan Somers result << devName->second << ": ";
2077a0c41d5SAlan Somers
2087a0c41d5SAlan Somers NVPairMap::const_iterator systemName(m_nvPairs.find("system"));
2097a0c41d5SAlan Somers if (systemName != m_nvPairs.end()
2107a0c41d5SAlan Somers && systemName->second != "none")
2117a0c41d5SAlan Somers result << systemName->second << ": ";
2127a0c41d5SAlan Somers
2137a0c41d5SAlan Somers result << TypeToString(GetType()) << ' ';
2147a0c41d5SAlan Somers
2157a0c41d5SAlan Somers for (NVPairMap::const_iterator curVar = m_nvPairs.begin();
2167a0c41d5SAlan Somers curVar != m_nvPairs.end(); curVar++) {
2177a0c41d5SAlan Somers if (curVar == devName || curVar == systemName)
2187a0c41d5SAlan Somers continue;
2197a0c41d5SAlan Somers
2207a0c41d5SAlan Somers result << ' '
2217a0c41d5SAlan Somers << curVar->first << "=" << curVar->second;
2227a0c41d5SAlan Somers }
2237a0c41d5SAlan Somers result << endl;
2247a0c41d5SAlan Somers
2257a0c41d5SAlan Somers return (result.str());
2267a0c41d5SAlan Somers }
2277a0c41d5SAlan Somers
2287a0c41d5SAlan Somers void
Print() const2297a0c41d5SAlan Somers Event::Print() const
2307a0c41d5SAlan Somers {
2317a0c41d5SAlan Somers cout << ToString() << std::flush;
2327a0c41d5SAlan Somers }
2337a0c41d5SAlan Somers
2347a0c41d5SAlan Somers void
Log(int priority) const2357a0c41d5SAlan Somers Event::Log(int priority) const
2367a0c41d5SAlan Somers {
2377a0c41d5SAlan Somers syslog(priority, "%s", ToString().c_str());
2387a0c41d5SAlan Somers }
2397a0c41d5SAlan Somers
2407a0c41d5SAlan Somers //- Event Virtual Public Methods -----------------------------------------------
~Event()2417a0c41d5SAlan Somers Event::~Event()
2427a0c41d5SAlan Somers {
2437a0c41d5SAlan Somers delete &m_nvPairs;
2447a0c41d5SAlan Somers }
2457a0c41d5SAlan Somers
2467a0c41d5SAlan Somers Event *
DeepCopy() const2477a0c41d5SAlan Somers Event::DeepCopy() const
2487a0c41d5SAlan Somers {
2497a0c41d5SAlan Somers return (new Event(*this));
2507a0c41d5SAlan Somers }
2517a0c41d5SAlan Somers
2527a0c41d5SAlan Somers bool
Process() const2537a0c41d5SAlan Somers Event::Process() const
2547a0c41d5SAlan Somers {
2557a0c41d5SAlan Somers return (false);
2567a0c41d5SAlan Somers }
2577a0c41d5SAlan Somers
2587a0c41d5SAlan Somers timeval
GetTimestamp() const2597a0c41d5SAlan Somers Event::GetTimestamp() const
2607a0c41d5SAlan Somers {
2617a0c41d5SAlan Somers timeval tv_timestamp;
2627a0c41d5SAlan Somers struct tm tm_timestamp;
2637a0c41d5SAlan Somers
2647a0c41d5SAlan Somers if (!Contains("timestamp")) {
2657a0c41d5SAlan Somers throw Exception("Event contains no timestamp: %s",
2667a0c41d5SAlan Somers m_eventString.c_str());
2677a0c41d5SAlan Somers }
2687a0c41d5SAlan Somers strptime(Value(string("timestamp")).c_str(), "%s", &tm_timestamp);
2697a0c41d5SAlan Somers tv_timestamp.tv_sec = mktime(&tm_timestamp);
2707a0c41d5SAlan Somers tv_timestamp.tv_usec = 0;
2717a0c41d5SAlan Somers return (tv_timestamp);
2727a0c41d5SAlan Somers }
2737a0c41d5SAlan Somers
2747a0c41d5SAlan Somers bool
DevPath(std::string & path) const2757a0c41d5SAlan Somers Event::DevPath(std::string &path) const
2767a0c41d5SAlan Somers {
277*e49d3eb4SAlexander Motin char buf[SPECNAMELEN + 1];
2787a0c41d5SAlan Somers string devName;
2797a0c41d5SAlan Somers
2807a0c41d5SAlan Somers if (!DevName(devName))
2817a0c41d5SAlan Somers return (false);
2827a0c41d5SAlan Somers
2837a0c41d5SAlan Somers string devPath(_PATH_DEV + devName);
2847a0c41d5SAlan Somers int devFd(open(devPath.c_str(), O_RDONLY));
2857a0c41d5SAlan Somers if (devFd == -1)
2867a0c41d5SAlan Somers return (false);
2877a0c41d5SAlan Somers
2887a0c41d5SAlan Somers /* Normalize the device name in case the DEVFS event is for a link. */
289*e49d3eb4SAlexander Motin if (fdevname_r(devFd, buf, sizeof(buf)) == NULL) {
290*e49d3eb4SAlexander Motin close(devFd);
291*e49d3eb4SAlexander Motin return (false);
292*e49d3eb4SAlexander Motin }
293*e49d3eb4SAlexander Motin devName = buf;
2947a0c41d5SAlan Somers path = _PATH_DEV + devName;
2957a0c41d5SAlan Somers
2967a0c41d5SAlan Somers close(devFd);
2977a0c41d5SAlan Somers
2987a0c41d5SAlan Somers return (true);
2997a0c41d5SAlan Somers }
3007a0c41d5SAlan Somers
3017a0c41d5SAlan Somers bool
PhysicalPath(std::string & path) const3027a0c41d5SAlan Somers Event::PhysicalPath(std::string &path) const
3037a0c41d5SAlan Somers {
3047a0c41d5SAlan Somers string devPath;
3057a0c41d5SAlan Somers
3067a0c41d5SAlan Somers if (!DevPath(devPath))
3077a0c41d5SAlan Somers return (false);
3087a0c41d5SAlan Somers
3097a0c41d5SAlan Somers int devFd(open(devPath.c_str(), O_RDONLY));
3107a0c41d5SAlan Somers if (devFd == -1)
3117a0c41d5SAlan Somers return (false);
3127a0c41d5SAlan Somers
3137a0c41d5SAlan Somers char physPath[MAXPATHLEN];
3147a0c41d5SAlan Somers physPath[0] = '\0';
3157a0c41d5SAlan Somers bool result(ioctl(devFd, DIOCGPHYSPATH, physPath) == 0);
3167a0c41d5SAlan Somers close(devFd);
3177a0c41d5SAlan Somers if (result)
3187a0c41d5SAlan Somers path = physPath;
3197a0c41d5SAlan Somers return (result);
3207a0c41d5SAlan Somers }
3217a0c41d5SAlan Somers
3227a0c41d5SAlan Somers //- Event Protected Methods ----------------------------------------------------
Event(Type type,NVPairMap & map,const string & eventString)3237a0c41d5SAlan Somers Event::Event(Type type, NVPairMap &map, const string &eventString)
3247a0c41d5SAlan Somers : m_type(type),
3257a0c41d5SAlan Somers m_nvPairs(map),
3267a0c41d5SAlan Somers m_eventString(eventString)
3277a0c41d5SAlan Somers {
3287a0c41d5SAlan Somers }
3297a0c41d5SAlan Somers
Event(const Event & src)3307a0c41d5SAlan Somers Event::Event(const Event &src)
3317a0c41d5SAlan Somers : m_type(src.m_type),
3327a0c41d5SAlan Somers m_nvPairs(*new NVPairMap(src.m_nvPairs)),
3337a0c41d5SAlan Somers m_eventString(src.m_eventString)
3347a0c41d5SAlan Somers {
3357a0c41d5SAlan Somers }
3367a0c41d5SAlan Somers
3377a0c41d5SAlan Somers void
ParseEventString(Event::Type type,const string & eventString,NVPairMap & nvpairs)3387a0c41d5SAlan Somers Event::ParseEventString(Event::Type type,
3397a0c41d5SAlan Somers const string &eventString,
3407a0c41d5SAlan Somers NVPairMap& nvpairs)
3417a0c41d5SAlan Somers {
3427a0c41d5SAlan Somers size_t start;
3437a0c41d5SAlan Somers size_t end;
3447a0c41d5SAlan Somers
3457a0c41d5SAlan Somers switch (type) {
3467a0c41d5SAlan Somers case ATTACH:
3477a0c41d5SAlan Somers case DETACH:
3487a0c41d5SAlan Somers
3497a0c41d5SAlan Somers /*
3507a0c41d5SAlan Somers * <type><device-name><unit> <pnpvars> \
3517a0c41d5SAlan Somers * at <location vars> <pnpvars> \
3527a0c41d5SAlan Somers * on <parent>
3537a0c41d5SAlan Somers *
3547a0c41d5SAlan Somers * Handle all data that doesn't conform to the
3557a0c41d5SAlan Somers * "name=value" format, and let the generic parser
3567a0c41d5SAlan Somers * below handle the rest.
3577a0c41d5SAlan Somers *
3587a0c41d5SAlan Somers * Type is a single char. Skip it.
3597a0c41d5SAlan Somers */
3607a0c41d5SAlan Somers start = 1;
3617a0c41d5SAlan Somers end = eventString.find_first_of(" \t\n", start);
3627a0c41d5SAlan Somers if (end == string::npos)
3637a0c41d5SAlan Somers throw ParseException(ParseException::INVALID_FORMAT,
3647a0c41d5SAlan Somers eventString, start);
3657a0c41d5SAlan Somers
3667a0c41d5SAlan Somers nvpairs["device-name"] = eventString.substr(start, end - start);
3677a0c41d5SAlan Somers
3687a0c41d5SAlan Somers start = eventString.find(" on ", end);
3697a0c41d5SAlan Somers if (end == string::npos)
3707a0c41d5SAlan Somers throw ParseException(ParseException::INVALID_FORMAT,
3717a0c41d5SAlan Somers eventString, start);
3727a0c41d5SAlan Somers start += 4;
3737a0c41d5SAlan Somers end = eventString.find_first_of(" \t\n", start);
3747a0c41d5SAlan Somers nvpairs["parent"] = eventString.substr(start, end);
3757a0c41d5SAlan Somers break;
3767a0c41d5SAlan Somers case NOTIFY:
3777a0c41d5SAlan Somers break;
3787a0c41d5SAlan Somers case NOMATCH:
3797a0c41d5SAlan Somers throw ParseException(ParseException::DISCARDED_EVENT_TYPE,
3807a0c41d5SAlan Somers eventString);
3817a0c41d5SAlan Somers default:
3827a0c41d5SAlan Somers throw ParseException(ParseException::UNKNOWN_EVENT_TYPE,
3837a0c41d5SAlan Somers eventString);
3847a0c41d5SAlan Somers }
3857a0c41d5SAlan Somers
3867a0c41d5SAlan Somers /* Process common "key=value" format. */
3877a0c41d5SAlan Somers for (start = 1; start < eventString.length(); start = end + 1) {
3887a0c41d5SAlan Somers
3897a0c41d5SAlan Somers /* Find the '=' in the middle of the key/value pair. */
3907a0c41d5SAlan Somers end = eventString.find('=', start);
3917a0c41d5SAlan Somers if (end == string::npos)
3927a0c41d5SAlan Somers break;
3937a0c41d5SAlan Somers
3947a0c41d5SAlan Somers /*
3957a0c41d5SAlan Somers * Find the start of the key by backing up until
3967a0c41d5SAlan Somers * we hit whitespace or '!' (event type "notice").
3977a0c41d5SAlan Somers * Due to the devdctl format, all key/value pair must
3987a0c41d5SAlan Somers * start with one of these two characters.
3997a0c41d5SAlan Somers */
4007a0c41d5SAlan Somers start = eventString.find_last_of("! \t\n", end);
4017a0c41d5SAlan Somers if (start == string::npos)
4027a0c41d5SAlan Somers throw ParseException(ParseException::INVALID_FORMAT,
4037a0c41d5SAlan Somers eventString, end);
4047a0c41d5SAlan Somers start++;
4057a0c41d5SAlan Somers string key(eventString.substr(start, end - start));
4067a0c41d5SAlan Somers
4077a0c41d5SAlan Somers /*
4087a0c41d5SAlan Somers * Walk forward from the '=' until either we exhaust
4097a0c41d5SAlan Somers * the buffer or we hit whitespace.
4107a0c41d5SAlan Somers */
4117a0c41d5SAlan Somers start = end + 1;
4127a0c41d5SAlan Somers if (start >= eventString.length())
4137a0c41d5SAlan Somers throw ParseException(ParseException::INVALID_FORMAT,
4147a0c41d5SAlan Somers eventString, end);
4157a0c41d5SAlan Somers end = eventString.find_first_of(" \t\n", start);
4167a0c41d5SAlan Somers if (end == string::npos)
4177a0c41d5SAlan Somers end = eventString.length() - 1;
4187a0c41d5SAlan Somers string value(eventString.substr(start, end - start));
4197a0c41d5SAlan Somers
4207a0c41d5SAlan Somers nvpairs[key] = value;
4217a0c41d5SAlan Somers }
4227a0c41d5SAlan Somers }
4237a0c41d5SAlan Somers
4247a0c41d5SAlan Somers void
TimestampEventString(std::string & eventString)4257a0c41d5SAlan Somers Event::TimestampEventString(std::string &eventString)
4267a0c41d5SAlan Somers {
4277a0c41d5SAlan Somers if (eventString.size() > 0) {
4287a0c41d5SAlan Somers /*
4297a0c41d5SAlan Somers * Add a timestamp as the final field of the event if it is
4307a0c41d5SAlan Somers * not already present.
4317a0c41d5SAlan Somers */
4327a0c41d5SAlan Somers if (eventString.find(" timestamp=") == string::npos) {
4337a0c41d5SAlan Somers const size_t bufsize = 32; // Long enough for a 64-bit int
4347a0c41d5SAlan Somers timeval now;
4357a0c41d5SAlan Somers char timebuf[bufsize];
4367a0c41d5SAlan Somers
4377a0c41d5SAlan Somers size_t eventEnd(eventString.find_last_not_of('\n') + 1);
4387a0c41d5SAlan Somers if (gettimeofday(&now, NULL) != 0)
4397a0c41d5SAlan Somers err(1, "gettimeofday");
4407a0c41d5SAlan Somers snprintf(timebuf, bufsize, " timestamp=%" PRId64,
4417a0c41d5SAlan Somers (int64_t) now.tv_sec);
4427a0c41d5SAlan Somers eventString.insert(eventEnd, timebuf);
4437a0c41d5SAlan Somers }
4447a0c41d5SAlan Somers }
4457a0c41d5SAlan Somers }
4467a0c41d5SAlan Somers
4477a0c41d5SAlan Somers /*-------------------------------- DevfsEvent --------------------------------*/
4487a0c41d5SAlan Somers //- DevfsEvent Static Public Methods -------------------------------------------
4497a0c41d5SAlan Somers Event *
Builder(Event::Type type,NVPairMap & nvPairs,const string & eventString)4507a0c41d5SAlan Somers DevfsEvent::Builder(Event::Type type, NVPairMap &nvPairs,
4517a0c41d5SAlan Somers const string &eventString)
4527a0c41d5SAlan Somers {
4537a0c41d5SAlan Somers return (new DevfsEvent(type, nvPairs, eventString));
4547a0c41d5SAlan Somers }
4557a0c41d5SAlan Somers
4567a0c41d5SAlan Somers //- DevfsEvent Static Protected Methods ----------------------------------------
4577a0c41d5SAlan Somers bool
IsWholeDev(const string & devName)4587a0c41d5SAlan Somers DevfsEvent::IsWholeDev(const string &devName)
4597a0c41d5SAlan Somers {
4607a0c41d5SAlan Somers string::const_iterator i(devName.begin());
4617a0c41d5SAlan Somers
4627a0c41d5SAlan Somers size_t start = devName.rfind('/');
4637a0c41d5SAlan Somers if (start == string::npos) {
4647a0c41d5SAlan Somers start = 0;
4657a0c41d5SAlan Somers } else {
4667a0c41d5SAlan Somers /* Just after the last '/'. */
4677a0c41d5SAlan Somers start++;
4687a0c41d5SAlan Somers }
4697a0c41d5SAlan Somers i += start;
4707a0c41d5SAlan Somers
4717a0c41d5SAlan Somers /* alpha prefix followed only by digits. */
4727a0c41d5SAlan Somers for (; i < devName.end() && !isdigit(*i); i++)
4737a0c41d5SAlan Somers ;
4747a0c41d5SAlan Somers
4757a0c41d5SAlan Somers if (i == devName.end())
4767a0c41d5SAlan Somers return (false);
4777a0c41d5SAlan Somers
4787a0c41d5SAlan Somers for (; i < devName.end() && isdigit(*i); i++)
4797a0c41d5SAlan Somers ;
4807a0c41d5SAlan Somers
4817a0c41d5SAlan Somers return (i == devName.end());
4827a0c41d5SAlan Somers }
4837a0c41d5SAlan Somers
4847a0c41d5SAlan Somers //- DevfsEvent Virtual Public Methods ------------------------------------------
4857a0c41d5SAlan Somers Event *
DeepCopy() const4867a0c41d5SAlan Somers DevfsEvent::DeepCopy() const
4877a0c41d5SAlan Somers {
4887a0c41d5SAlan Somers return (new DevfsEvent(*this));
4897a0c41d5SAlan Somers }
4907a0c41d5SAlan Somers
4917a0c41d5SAlan Somers bool
Process() const4927a0c41d5SAlan Somers DevfsEvent::Process() const
4937a0c41d5SAlan Somers {
4947a0c41d5SAlan Somers return (true);
4957a0c41d5SAlan Somers }
4967a0c41d5SAlan Somers
4977a0c41d5SAlan Somers //- DevfsEvent Public Methods --------------------------------------------------
4987a0c41d5SAlan Somers bool
IsWholeDev() const4997a0c41d5SAlan Somers DevfsEvent::IsWholeDev() const
5007a0c41d5SAlan Somers {
5017a0c41d5SAlan Somers string devName;
5027a0c41d5SAlan Somers
5037a0c41d5SAlan Somers return (DevName(devName) && IsDiskDev() && IsWholeDev(devName));
5047a0c41d5SAlan Somers }
5057a0c41d5SAlan Somers
5067a0c41d5SAlan Somers bool
DevName(std::string & name) const5077a0c41d5SAlan Somers DevfsEvent::DevName(std::string &name) const
5087a0c41d5SAlan Somers {
5097a0c41d5SAlan Somers if (Value("subsystem") != "CDEV")
5107a0c41d5SAlan Somers return (false);
5117a0c41d5SAlan Somers
5127a0c41d5SAlan Somers name = Value("cdev");
5137a0c41d5SAlan Somers return (!name.empty());
5147a0c41d5SAlan Somers }
5157a0c41d5SAlan Somers
5167a0c41d5SAlan Somers //- DevfsEvent Protected Methods -----------------------------------------------
DevfsEvent(Event::Type type,NVPairMap & nvpairs,const string & eventString)5177a0c41d5SAlan Somers DevfsEvent::DevfsEvent(Event::Type type, NVPairMap &nvpairs,
5187a0c41d5SAlan Somers const string &eventString)
5197a0c41d5SAlan Somers : Event(type, nvpairs, eventString)
5207a0c41d5SAlan Somers {
5217a0c41d5SAlan Somers }
5227a0c41d5SAlan Somers
DevfsEvent(const DevfsEvent & src)5237a0c41d5SAlan Somers DevfsEvent::DevfsEvent(const DevfsEvent &src)
5247a0c41d5SAlan Somers : Event(src)
5257a0c41d5SAlan Somers {
5267a0c41d5SAlan Somers }
5277a0c41d5SAlan Somers
5287a0c41d5SAlan Somers /*--------------------------------- GeomEvent --------------------------------*/
5297a0c41d5SAlan Somers //- GeomEvent Static Public Methods --------------------------------------------
5307a0c41d5SAlan Somers Event *
Builder(Event::Type type,NVPairMap & nvpairs,const string & eventString)5317a0c41d5SAlan Somers GeomEvent::Builder(Event::Type type, NVPairMap &nvpairs,
5327a0c41d5SAlan Somers const string &eventString)
5337a0c41d5SAlan Somers {
5347a0c41d5SAlan Somers return (new GeomEvent(type, nvpairs, eventString));
5357a0c41d5SAlan Somers }
5367a0c41d5SAlan Somers
5377a0c41d5SAlan Somers //- GeomEvent Virtual Public Methods -------------------------------------------
5387a0c41d5SAlan Somers Event *
DeepCopy() const5397a0c41d5SAlan Somers GeomEvent::DeepCopy() const
5407a0c41d5SAlan Somers {
5417a0c41d5SAlan Somers return (new GeomEvent(*this));
5427a0c41d5SAlan Somers }
5437a0c41d5SAlan Somers
5447a0c41d5SAlan Somers bool
DevName(std::string & name) const5457a0c41d5SAlan Somers GeomEvent::DevName(std::string &name) const
5467a0c41d5SAlan Somers {
547a07d59d1SAlan Somers if (Value("subsystem") == "disk")
5487a0c41d5SAlan Somers name = Value("devname");
549a07d59d1SAlan Somers else
550a07d59d1SAlan Somers name = Value("cdev");
5517a0c41d5SAlan Somers return (!name.empty());
5527a0c41d5SAlan Somers }
5537a0c41d5SAlan Somers
5547a0c41d5SAlan Somers
5557a0c41d5SAlan Somers //- GeomEvent Protected Methods ------------------------------------------------
GeomEvent(Event::Type type,NVPairMap & nvpairs,const string & eventString)5567a0c41d5SAlan Somers GeomEvent::GeomEvent(Event::Type type, NVPairMap &nvpairs,
5577a0c41d5SAlan Somers const string &eventString)
5587a0c41d5SAlan Somers : Event(type, nvpairs, eventString),
5597a0c41d5SAlan Somers m_devname(Value("devname"))
5607a0c41d5SAlan Somers {
5617a0c41d5SAlan Somers }
5627a0c41d5SAlan Somers
GeomEvent(const GeomEvent & src)5637a0c41d5SAlan Somers GeomEvent::GeomEvent(const GeomEvent &src)
5647a0c41d5SAlan Somers : Event(src),
5657a0c41d5SAlan Somers m_devname(src.m_devname)
5667a0c41d5SAlan Somers {
5677a0c41d5SAlan Somers }
5687a0c41d5SAlan Somers
5697a0c41d5SAlan Somers /*--------------------------------- ZfsEvent ---------------------------------*/
5707a0c41d5SAlan Somers //- ZfsEvent Static Public Methods ---------------------------------------------
5717a0c41d5SAlan Somers Event *
Builder(Event::Type type,NVPairMap & nvpairs,const string & eventString)5727a0c41d5SAlan Somers ZfsEvent::Builder(Event::Type type, NVPairMap &nvpairs,
5737a0c41d5SAlan Somers const string &eventString)
5747a0c41d5SAlan Somers {
5757a0c41d5SAlan Somers return (new ZfsEvent(type, nvpairs, eventString));
5767a0c41d5SAlan Somers }
5777a0c41d5SAlan Somers
5787a0c41d5SAlan Somers //- ZfsEvent Virtual Public Methods --------------------------------------------
5797a0c41d5SAlan Somers Event *
DeepCopy() const5807a0c41d5SAlan Somers ZfsEvent::DeepCopy() const
5817a0c41d5SAlan Somers {
5827a0c41d5SAlan Somers return (new ZfsEvent(*this));
5837a0c41d5SAlan Somers }
5847a0c41d5SAlan Somers
5857a0c41d5SAlan Somers bool
DevName(std::string & name) const5867a0c41d5SAlan Somers ZfsEvent::DevName(std::string &name) const
5877a0c41d5SAlan Somers {
5887a0c41d5SAlan Somers return (false);
5897a0c41d5SAlan Somers }
5907a0c41d5SAlan Somers
5917a0c41d5SAlan Somers //- ZfsEvent Protected Methods -------------------------------------------------
ZfsEvent(Event::Type type,NVPairMap & nvpairs,const string & eventString)5927a0c41d5SAlan Somers ZfsEvent::ZfsEvent(Event::Type type, NVPairMap &nvpairs,
5937a0c41d5SAlan Somers const string &eventString)
5947a0c41d5SAlan Somers : Event(type, nvpairs, eventString),
5957a0c41d5SAlan Somers m_poolGUID(Guid(Value("pool_guid"))),
5967a0c41d5SAlan Somers m_vdevGUID(Guid(Value("vdev_guid")))
5977a0c41d5SAlan Somers {
5987a0c41d5SAlan Somers }
5997a0c41d5SAlan Somers
ZfsEvent(const ZfsEvent & src)6007a0c41d5SAlan Somers ZfsEvent::ZfsEvent(const ZfsEvent &src)
6017a0c41d5SAlan Somers : Event(src),
6027a0c41d5SAlan Somers m_poolGUID(src.m_poolGUID),
6037a0c41d5SAlan Somers m_vdevGUID(src.m_vdevGUID)
6047a0c41d5SAlan Somers {
6057a0c41d5SAlan Somers }
6067a0c41d5SAlan Somers
6077a0c41d5SAlan Somers } // namespace DevdCtl
608