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 667a0c41d5SAlan Somers __FBSDID("$FreeBSD$"); 677a0c41d5SAlan Somers 687a0c41d5SAlan Somers /*================================== Macros ==================================*/ 697a0c41d5SAlan Somers #define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*x)) 707a0c41d5SAlan Somers 717a0c41d5SAlan Somers /*============================ Namespace Control =============================*/ 727a0c41d5SAlan Somers using std::cout; 737a0c41d5SAlan Somers using std::endl; 747a0c41d5SAlan Somers using std::string; 757a0c41d5SAlan Somers using std::stringstream; 767a0c41d5SAlan Somers 777a0c41d5SAlan Somers namespace DevdCtl 787a0c41d5SAlan Somers { 797a0c41d5SAlan Somers 807a0c41d5SAlan Somers /*=========================== Class Implementations ==========================*/ 817a0c41d5SAlan Somers /*----------------------------------- Event ----------------------------------*/ 827a0c41d5SAlan Somers //- Event Static Protected Data ------------------------------------------------ 837a0c41d5SAlan Somers const string Event::s_theEmptyString; 847a0c41d5SAlan Somers 857a0c41d5SAlan Somers Event::EventTypeRecord Event::s_typeTable[] = 867a0c41d5SAlan Somers { 877a0c41d5SAlan Somers { Event::NOTIFY, "Notify" }, 887a0c41d5SAlan Somers { Event::NOMATCH, "No Driver Match" }, 897a0c41d5SAlan Somers { Event::ATTACH, "Attach" }, 907a0c41d5SAlan Somers { Event::DETACH, "Detach" } 917a0c41d5SAlan Somers }; 927a0c41d5SAlan Somers 937a0c41d5SAlan Somers //- Event Static Public Methods ------------------------------------------------ 947a0c41d5SAlan Somers Event * 957a0c41d5SAlan Somers Event::Builder(Event::Type type, NVPairMap &nvPairs, 967a0c41d5SAlan Somers const string &eventString) 977a0c41d5SAlan Somers { 987a0c41d5SAlan Somers return (new Event(type, nvPairs, eventString)); 997a0c41d5SAlan Somers } 1007a0c41d5SAlan Somers 1017a0c41d5SAlan Somers Event * 1027a0c41d5SAlan Somers Event::CreateEvent(const EventFactory &factory, const string &eventString) 1037a0c41d5SAlan Somers { 1047a0c41d5SAlan Somers NVPairMap &nvpairs(*new NVPairMap); 1057a0c41d5SAlan Somers Type type(static_cast<Event::Type>(eventString[0])); 1067a0c41d5SAlan Somers 1077a0c41d5SAlan Somers try { 1087a0c41d5SAlan Somers ParseEventString(type, eventString, nvpairs); 1097a0c41d5SAlan Somers } catch (const ParseException &exp) { 1107a0c41d5SAlan Somers if (exp.GetType() == ParseException::INVALID_FORMAT) 1117a0c41d5SAlan Somers exp.Log(); 1127a0c41d5SAlan Somers return (NULL); 1137a0c41d5SAlan Somers } 1147a0c41d5SAlan Somers 1157a0c41d5SAlan Somers /* 1167a0c41d5SAlan Somers * Allow entries in our table for events with no system specified. 1177a0c41d5SAlan Somers * These entries should specify the string "none". 1187a0c41d5SAlan Somers */ 1197a0c41d5SAlan Somers NVPairMap::iterator system_item(nvpairs.find("system")); 1207a0c41d5SAlan Somers if (system_item == nvpairs.end()) 1217a0c41d5SAlan Somers nvpairs["system"] = "none"; 1227a0c41d5SAlan Somers 1237a0c41d5SAlan Somers return (factory.Build(type, nvpairs, eventString)); 1247a0c41d5SAlan Somers } 1257a0c41d5SAlan Somers 1267a0c41d5SAlan Somers bool 1277a0c41d5SAlan Somers Event::DevName(std::string &name) const 1287a0c41d5SAlan Somers { 1297a0c41d5SAlan Somers return (false); 1307a0c41d5SAlan Somers } 1317a0c41d5SAlan Somers 1327a0c41d5SAlan Somers /* TODO: simplify this function with C++-11 <regex> methods */ 1337a0c41d5SAlan Somers bool 1347a0c41d5SAlan Somers Event::IsDiskDev() const 1357a0c41d5SAlan Somers { 1367a0c41d5SAlan Somers const int numDrivers = 2; 1377a0c41d5SAlan Somers static const char *diskDevNames[numDrivers] = 1387a0c41d5SAlan Somers { 1397a0c41d5SAlan Somers "da", 1407a0c41d5SAlan Somers "ada" 1417a0c41d5SAlan Somers }; 1427a0c41d5SAlan Somers const char **dName; 1437a0c41d5SAlan Somers string devName; 1447a0c41d5SAlan Somers 1457a0c41d5SAlan Somers if (! DevName(devName)) 1467a0c41d5SAlan Somers return false; 1477a0c41d5SAlan Somers 1487a0c41d5SAlan Somers size_t find_start = devName.rfind('/'); 1497a0c41d5SAlan Somers if (find_start == string::npos) { 1507a0c41d5SAlan Somers find_start = 0; 1517a0c41d5SAlan Somers } else { 1527a0c41d5SAlan Somers /* Just after the last '/'. */ 1537a0c41d5SAlan Somers find_start++; 1547a0c41d5SAlan Somers } 1557a0c41d5SAlan Somers 1567a0c41d5SAlan Somers for (dName = &diskDevNames[0]; 1577a0c41d5SAlan Somers dName <= &diskDevNames[numDrivers - 1]; dName++) { 1587a0c41d5SAlan Somers 1597a0c41d5SAlan Somers size_t loc(devName.find(*dName, find_start)); 1607a0c41d5SAlan Somers if (loc == find_start) { 1617a0c41d5SAlan Somers size_t prefixLen(strlen(*dName)); 1627a0c41d5SAlan Somers 1637a0c41d5SAlan Somers if (devName.length() - find_start >= prefixLen 1647a0c41d5SAlan Somers && isdigit(devName[find_start + prefixLen])) 1657a0c41d5SAlan Somers return (true); 1667a0c41d5SAlan Somers } 1677a0c41d5SAlan Somers } 1687a0c41d5SAlan Somers 1697a0c41d5SAlan Somers return (false); 1707a0c41d5SAlan Somers } 1717a0c41d5SAlan Somers 1727a0c41d5SAlan Somers const char * 1737a0c41d5SAlan Somers Event::TypeToString(Event::Type type) 1747a0c41d5SAlan Somers { 1757a0c41d5SAlan Somers EventTypeRecord *rec(s_typeTable); 1767a0c41d5SAlan Somers EventTypeRecord *lastRec(s_typeTable + NUM_ELEMENTS(s_typeTable) - 1); 1777a0c41d5SAlan Somers 1787a0c41d5SAlan Somers for (; rec <= lastRec; rec++) { 1797a0c41d5SAlan Somers if (rec->m_type == type) 1807a0c41d5SAlan Somers return (rec->m_typeName); 1817a0c41d5SAlan Somers } 1827a0c41d5SAlan Somers return ("Unknown"); 1837a0c41d5SAlan Somers } 1847a0c41d5SAlan Somers 1857a0c41d5SAlan Somers //- Event Public Methods ------------------------------------------------------- 1867a0c41d5SAlan Somers const string & 1877a0c41d5SAlan Somers Event::Value(const string &varName) const 1887a0c41d5SAlan Somers { 1897a0c41d5SAlan Somers NVPairMap::const_iterator item(m_nvPairs.find(varName)); 1907a0c41d5SAlan Somers if (item == m_nvPairs.end()) 1917a0c41d5SAlan Somers return (s_theEmptyString); 1927a0c41d5SAlan Somers 1937a0c41d5SAlan Somers return (item->second); 1947a0c41d5SAlan Somers } 1957a0c41d5SAlan Somers 1967a0c41d5SAlan Somers bool 1977a0c41d5SAlan Somers Event::Contains(const string &varName) const 1987a0c41d5SAlan Somers { 1997a0c41d5SAlan Somers return (m_nvPairs.find(varName) != m_nvPairs.end()); 2007a0c41d5SAlan Somers } 2017a0c41d5SAlan Somers 2027a0c41d5SAlan Somers string 2037a0c41d5SAlan Somers Event::ToString() const 2047a0c41d5SAlan Somers { 2057a0c41d5SAlan Somers stringstream result; 2067a0c41d5SAlan Somers 2077a0c41d5SAlan Somers NVPairMap::const_iterator devName(m_nvPairs.find("device-name")); 2087a0c41d5SAlan Somers if (devName != m_nvPairs.end()) 2097a0c41d5SAlan Somers result << devName->second << ": "; 2107a0c41d5SAlan Somers 2117a0c41d5SAlan Somers NVPairMap::const_iterator systemName(m_nvPairs.find("system")); 2127a0c41d5SAlan Somers if (systemName != m_nvPairs.end() 2137a0c41d5SAlan Somers && systemName->second != "none") 2147a0c41d5SAlan Somers result << systemName->second << ": "; 2157a0c41d5SAlan Somers 2167a0c41d5SAlan Somers result << TypeToString(GetType()) << ' '; 2177a0c41d5SAlan Somers 2187a0c41d5SAlan Somers for (NVPairMap::const_iterator curVar = m_nvPairs.begin(); 2197a0c41d5SAlan Somers curVar != m_nvPairs.end(); curVar++) { 2207a0c41d5SAlan Somers if (curVar == devName || curVar == systemName) 2217a0c41d5SAlan Somers continue; 2227a0c41d5SAlan Somers 2237a0c41d5SAlan Somers result << ' ' 2247a0c41d5SAlan Somers << curVar->first << "=" << curVar->second; 2257a0c41d5SAlan Somers } 2267a0c41d5SAlan Somers result << endl; 2277a0c41d5SAlan Somers 2287a0c41d5SAlan Somers return (result.str()); 2297a0c41d5SAlan Somers } 2307a0c41d5SAlan Somers 2317a0c41d5SAlan Somers void 2327a0c41d5SAlan Somers Event::Print() const 2337a0c41d5SAlan Somers { 2347a0c41d5SAlan Somers cout << ToString() << std::flush; 2357a0c41d5SAlan Somers } 2367a0c41d5SAlan Somers 2377a0c41d5SAlan Somers void 2387a0c41d5SAlan Somers Event::Log(int priority) const 2397a0c41d5SAlan Somers { 2407a0c41d5SAlan Somers syslog(priority, "%s", ToString().c_str()); 2417a0c41d5SAlan Somers } 2427a0c41d5SAlan Somers 2437a0c41d5SAlan Somers //- Event Virtual Public Methods ----------------------------------------------- 2447a0c41d5SAlan Somers Event::~Event() 2457a0c41d5SAlan Somers { 2467a0c41d5SAlan Somers delete &m_nvPairs; 2477a0c41d5SAlan Somers } 2487a0c41d5SAlan Somers 2497a0c41d5SAlan Somers Event * 2507a0c41d5SAlan Somers Event::DeepCopy() const 2517a0c41d5SAlan Somers { 2527a0c41d5SAlan Somers return (new Event(*this)); 2537a0c41d5SAlan Somers } 2547a0c41d5SAlan Somers 2557a0c41d5SAlan Somers bool 2567a0c41d5SAlan Somers Event::Process() const 2577a0c41d5SAlan Somers { 2587a0c41d5SAlan Somers return (false); 2597a0c41d5SAlan Somers } 2607a0c41d5SAlan Somers 2617a0c41d5SAlan Somers timeval 2627a0c41d5SAlan Somers Event::GetTimestamp() const 2637a0c41d5SAlan Somers { 2647a0c41d5SAlan Somers timeval tv_timestamp; 2657a0c41d5SAlan Somers struct tm tm_timestamp; 2667a0c41d5SAlan Somers 2677a0c41d5SAlan Somers if (!Contains("timestamp")) { 2687a0c41d5SAlan Somers throw Exception("Event contains no timestamp: %s", 2697a0c41d5SAlan Somers m_eventString.c_str()); 2707a0c41d5SAlan Somers } 2717a0c41d5SAlan Somers strptime(Value(string("timestamp")).c_str(), "%s", &tm_timestamp); 2727a0c41d5SAlan Somers tv_timestamp.tv_sec = mktime(&tm_timestamp); 2737a0c41d5SAlan Somers tv_timestamp.tv_usec = 0; 2747a0c41d5SAlan Somers return (tv_timestamp); 2757a0c41d5SAlan Somers } 2767a0c41d5SAlan Somers 2777a0c41d5SAlan Somers bool 2787a0c41d5SAlan Somers Event::DevPath(std::string &path) const 2797a0c41d5SAlan Somers { 280*e49d3eb4SAlexander Motin char buf[SPECNAMELEN + 1]; 2817a0c41d5SAlan Somers string devName; 2827a0c41d5SAlan Somers 2837a0c41d5SAlan Somers if (!DevName(devName)) 2847a0c41d5SAlan Somers return (false); 2857a0c41d5SAlan Somers 2867a0c41d5SAlan Somers string devPath(_PATH_DEV + devName); 2877a0c41d5SAlan Somers int devFd(open(devPath.c_str(), O_RDONLY)); 2887a0c41d5SAlan Somers if (devFd == -1) 2897a0c41d5SAlan Somers return (false); 2907a0c41d5SAlan Somers 2917a0c41d5SAlan Somers /* Normalize the device name in case the DEVFS event is for a link. */ 292*e49d3eb4SAlexander Motin if (fdevname_r(devFd, buf, sizeof(buf)) == NULL) { 293*e49d3eb4SAlexander Motin close(devFd); 294*e49d3eb4SAlexander Motin return (false); 295*e49d3eb4SAlexander Motin } 296*e49d3eb4SAlexander Motin devName = buf; 2977a0c41d5SAlan Somers path = _PATH_DEV + devName; 2987a0c41d5SAlan Somers 2997a0c41d5SAlan Somers close(devFd); 3007a0c41d5SAlan Somers 3017a0c41d5SAlan Somers return (true); 3027a0c41d5SAlan Somers } 3037a0c41d5SAlan Somers 3047a0c41d5SAlan Somers bool 3057a0c41d5SAlan Somers Event::PhysicalPath(std::string &path) const 3067a0c41d5SAlan Somers { 3077a0c41d5SAlan Somers string devPath; 3087a0c41d5SAlan Somers 3097a0c41d5SAlan Somers if (!DevPath(devPath)) 3107a0c41d5SAlan Somers return (false); 3117a0c41d5SAlan Somers 3127a0c41d5SAlan Somers int devFd(open(devPath.c_str(), O_RDONLY)); 3137a0c41d5SAlan Somers if (devFd == -1) 3147a0c41d5SAlan Somers return (false); 3157a0c41d5SAlan Somers 3167a0c41d5SAlan Somers char physPath[MAXPATHLEN]; 3177a0c41d5SAlan Somers physPath[0] = '\0'; 3187a0c41d5SAlan Somers bool result(ioctl(devFd, DIOCGPHYSPATH, physPath) == 0); 3197a0c41d5SAlan Somers close(devFd); 3207a0c41d5SAlan Somers if (result) 3217a0c41d5SAlan Somers path = physPath; 3227a0c41d5SAlan Somers return (result); 3237a0c41d5SAlan Somers } 3247a0c41d5SAlan Somers 3257a0c41d5SAlan Somers //- Event Protected Methods ---------------------------------------------------- 3267a0c41d5SAlan Somers Event::Event(Type type, NVPairMap &map, const string &eventString) 3277a0c41d5SAlan Somers : m_type(type), 3287a0c41d5SAlan Somers m_nvPairs(map), 3297a0c41d5SAlan Somers m_eventString(eventString) 3307a0c41d5SAlan Somers { 3317a0c41d5SAlan Somers } 3327a0c41d5SAlan Somers 3337a0c41d5SAlan Somers Event::Event(const Event &src) 3347a0c41d5SAlan Somers : m_type(src.m_type), 3357a0c41d5SAlan Somers m_nvPairs(*new NVPairMap(src.m_nvPairs)), 3367a0c41d5SAlan Somers m_eventString(src.m_eventString) 3377a0c41d5SAlan Somers { 3387a0c41d5SAlan Somers } 3397a0c41d5SAlan Somers 3407a0c41d5SAlan Somers void 3417a0c41d5SAlan Somers Event::ParseEventString(Event::Type type, 3427a0c41d5SAlan Somers const string &eventString, 3437a0c41d5SAlan Somers NVPairMap& nvpairs) 3447a0c41d5SAlan Somers { 3457a0c41d5SAlan Somers size_t start; 3467a0c41d5SAlan Somers size_t end; 3477a0c41d5SAlan Somers 3487a0c41d5SAlan Somers switch (type) { 3497a0c41d5SAlan Somers case ATTACH: 3507a0c41d5SAlan Somers case DETACH: 3517a0c41d5SAlan Somers 3527a0c41d5SAlan Somers /* 3537a0c41d5SAlan Somers * <type><device-name><unit> <pnpvars> \ 3547a0c41d5SAlan Somers * at <location vars> <pnpvars> \ 3557a0c41d5SAlan Somers * on <parent> 3567a0c41d5SAlan Somers * 3577a0c41d5SAlan Somers * Handle all data that doesn't conform to the 3587a0c41d5SAlan Somers * "name=value" format, and let the generic parser 3597a0c41d5SAlan Somers * below handle the rest. 3607a0c41d5SAlan Somers * 3617a0c41d5SAlan Somers * Type is a single char. Skip it. 3627a0c41d5SAlan Somers */ 3637a0c41d5SAlan Somers start = 1; 3647a0c41d5SAlan Somers end = eventString.find_first_of(" \t\n", start); 3657a0c41d5SAlan Somers if (end == string::npos) 3667a0c41d5SAlan Somers throw ParseException(ParseException::INVALID_FORMAT, 3677a0c41d5SAlan Somers eventString, start); 3687a0c41d5SAlan Somers 3697a0c41d5SAlan Somers nvpairs["device-name"] = eventString.substr(start, end - start); 3707a0c41d5SAlan Somers 3717a0c41d5SAlan Somers start = eventString.find(" on ", end); 3727a0c41d5SAlan Somers if (end == string::npos) 3737a0c41d5SAlan Somers throw ParseException(ParseException::INVALID_FORMAT, 3747a0c41d5SAlan Somers eventString, start); 3757a0c41d5SAlan Somers start += 4; 3767a0c41d5SAlan Somers end = eventString.find_first_of(" \t\n", start); 3777a0c41d5SAlan Somers nvpairs["parent"] = eventString.substr(start, end); 3787a0c41d5SAlan Somers break; 3797a0c41d5SAlan Somers case NOTIFY: 3807a0c41d5SAlan Somers break; 3817a0c41d5SAlan Somers case NOMATCH: 3827a0c41d5SAlan Somers throw ParseException(ParseException::DISCARDED_EVENT_TYPE, 3837a0c41d5SAlan Somers eventString); 3847a0c41d5SAlan Somers default: 3857a0c41d5SAlan Somers throw ParseException(ParseException::UNKNOWN_EVENT_TYPE, 3867a0c41d5SAlan Somers eventString); 3877a0c41d5SAlan Somers } 3887a0c41d5SAlan Somers 3897a0c41d5SAlan Somers /* Process common "key=value" format. */ 3907a0c41d5SAlan Somers for (start = 1; start < eventString.length(); start = end + 1) { 3917a0c41d5SAlan Somers 3927a0c41d5SAlan Somers /* Find the '=' in the middle of the key/value pair. */ 3937a0c41d5SAlan Somers end = eventString.find('=', start); 3947a0c41d5SAlan Somers if (end == string::npos) 3957a0c41d5SAlan Somers break; 3967a0c41d5SAlan Somers 3977a0c41d5SAlan Somers /* 3987a0c41d5SAlan Somers * Find the start of the key by backing up until 3997a0c41d5SAlan Somers * we hit whitespace or '!' (event type "notice"). 4007a0c41d5SAlan Somers * Due to the devdctl format, all key/value pair must 4017a0c41d5SAlan Somers * start with one of these two characters. 4027a0c41d5SAlan Somers */ 4037a0c41d5SAlan Somers start = eventString.find_last_of("! \t\n", end); 4047a0c41d5SAlan Somers if (start == string::npos) 4057a0c41d5SAlan Somers throw ParseException(ParseException::INVALID_FORMAT, 4067a0c41d5SAlan Somers eventString, end); 4077a0c41d5SAlan Somers start++; 4087a0c41d5SAlan Somers string key(eventString.substr(start, end - start)); 4097a0c41d5SAlan Somers 4107a0c41d5SAlan Somers /* 4117a0c41d5SAlan Somers * Walk forward from the '=' until either we exhaust 4127a0c41d5SAlan Somers * the buffer or we hit whitespace. 4137a0c41d5SAlan Somers */ 4147a0c41d5SAlan Somers start = end + 1; 4157a0c41d5SAlan Somers if (start >= eventString.length()) 4167a0c41d5SAlan Somers throw ParseException(ParseException::INVALID_FORMAT, 4177a0c41d5SAlan Somers eventString, end); 4187a0c41d5SAlan Somers end = eventString.find_first_of(" \t\n", start); 4197a0c41d5SAlan Somers if (end == string::npos) 4207a0c41d5SAlan Somers end = eventString.length() - 1; 4217a0c41d5SAlan Somers string value(eventString.substr(start, end - start)); 4227a0c41d5SAlan Somers 4237a0c41d5SAlan Somers nvpairs[key] = value; 4247a0c41d5SAlan Somers } 4257a0c41d5SAlan Somers } 4267a0c41d5SAlan Somers 4277a0c41d5SAlan Somers void 4287a0c41d5SAlan Somers Event::TimestampEventString(std::string &eventString) 4297a0c41d5SAlan Somers { 4307a0c41d5SAlan Somers if (eventString.size() > 0) { 4317a0c41d5SAlan Somers /* 4327a0c41d5SAlan Somers * Add a timestamp as the final field of the event if it is 4337a0c41d5SAlan Somers * not already present. 4347a0c41d5SAlan Somers */ 4357a0c41d5SAlan Somers if (eventString.find(" timestamp=") == string::npos) { 4367a0c41d5SAlan Somers const size_t bufsize = 32; // Long enough for a 64-bit int 4377a0c41d5SAlan Somers timeval now; 4387a0c41d5SAlan Somers char timebuf[bufsize]; 4397a0c41d5SAlan Somers 4407a0c41d5SAlan Somers size_t eventEnd(eventString.find_last_not_of('\n') + 1); 4417a0c41d5SAlan Somers if (gettimeofday(&now, NULL) != 0) 4427a0c41d5SAlan Somers err(1, "gettimeofday"); 4437a0c41d5SAlan Somers snprintf(timebuf, bufsize, " timestamp=%" PRId64, 4447a0c41d5SAlan Somers (int64_t) now.tv_sec); 4457a0c41d5SAlan Somers eventString.insert(eventEnd, timebuf); 4467a0c41d5SAlan Somers } 4477a0c41d5SAlan Somers } 4487a0c41d5SAlan Somers } 4497a0c41d5SAlan Somers 4507a0c41d5SAlan Somers /*-------------------------------- DevfsEvent --------------------------------*/ 4517a0c41d5SAlan Somers //- DevfsEvent Static Public Methods ------------------------------------------- 4527a0c41d5SAlan Somers Event * 4537a0c41d5SAlan Somers DevfsEvent::Builder(Event::Type type, NVPairMap &nvPairs, 4547a0c41d5SAlan Somers const string &eventString) 4557a0c41d5SAlan Somers { 4567a0c41d5SAlan Somers return (new DevfsEvent(type, nvPairs, eventString)); 4577a0c41d5SAlan Somers } 4587a0c41d5SAlan Somers 4597a0c41d5SAlan Somers //- DevfsEvent Static Protected Methods ---------------------------------------- 4607a0c41d5SAlan Somers bool 4617a0c41d5SAlan Somers DevfsEvent::IsWholeDev(const string &devName) 4627a0c41d5SAlan Somers { 4637a0c41d5SAlan Somers string::const_iterator i(devName.begin()); 4647a0c41d5SAlan Somers 4657a0c41d5SAlan Somers size_t start = devName.rfind('/'); 4667a0c41d5SAlan Somers if (start == string::npos) { 4677a0c41d5SAlan Somers start = 0; 4687a0c41d5SAlan Somers } else { 4697a0c41d5SAlan Somers /* Just after the last '/'. */ 4707a0c41d5SAlan Somers start++; 4717a0c41d5SAlan Somers } 4727a0c41d5SAlan Somers i += start; 4737a0c41d5SAlan Somers 4747a0c41d5SAlan Somers /* alpha prefix followed only by digits. */ 4757a0c41d5SAlan Somers for (; i < devName.end() && !isdigit(*i); i++) 4767a0c41d5SAlan Somers ; 4777a0c41d5SAlan Somers 4787a0c41d5SAlan Somers if (i == devName.end()) 4797a0c41d5SAlan Somers return (false); 4807a0c41d5SAlan Somers 4817a0c41d5SAlan Somers for (; i < devName.end() && isdigit(*i); i++) 4827a0c41d5SAlan Somers ; 4837a0c41d5SAlan Somers 4847a0c41d5SAlan Somers return (i == devName.end()); 4857a0c41d5SAlan Somers } 4867a0c41d5SAlan Somers 4877a0c41d5SAlan Somers //- DevfsEvent Virtual Public Methods ------------------------------------------ 4887a0c41d5SAlan Somers Event * 4897a0c41d5SAlan Somers DevfsEvent::DeepCopy() const 4907a0c41d5SAlan Somers { 4917a0c41d5SAlan Somers return (new DevfsEvent(*this)); 4927a0c41d5SAlan Somers } 4937a0c41d5SAlan Somers 4947a0c41d5SAlan Somers bool 4957a0c41d5SAlan Somers DevfsEvent::Process() const 4967a0c41d5SAlan Somers { 4977a0c41d5SAlan Somers return (true); 4987a0c41d5SAlan Somers } 4997a0c41d5SAlan Somers 5007a0c41d5SAlan Somers //- DevfsEvent Public Methods -------------------------------------------------- 5017a0c41d5SAlan Somers bool 5027a0c41d5SAlan Somers DevfsEvent::IsWholeDev() const 5037a0c41d5SAlan Somers { 5047a0c41d5SAlan Somers string devName; 5057a0c41d5SAlan Somers 5067a0c41d5SAlan Somers return (DevName(devName) && IsDiskDev() && IsWholeDev(devName)); 5077a0c41d5SAlan Somers } 5087a0c41d5SAlan Somers 5097a0c41d5SAlan Somers bool 5107a0c41d5SAlan Somers DevfsEvent::DevName(std::string &name) const 5117a0c41d5SAlan Somers { 5127a0c41d5SAlan Somers if (Value("subsystem") != "CDEV") 5137a0c41d5SAlan Somers return (false); 5147a0c41d5SAlan Somers 5157a0c41d5SAlan Somers name = Value("cdev"); 5167a0c41d5SAlan Somers return (!name.empty()); 5177a0c41d5SAlan Somers } 5187a0c41d5SAlan Somers 5197a0c41d5SAlan Somers //- DevfsEvent Protected Methods ----------------------------------------------- 5207a0c41d5SAlan Somers DevfsEvent::DevfsEvent(Event::Type type, NVPairMap &nvpairs, 5217a0c41d5SAlan Somers const string &eventString) 5227a0c41d5SAlan Somers : Event(type, nvpairs, eventString) 5237a0c41d5SAlan Somers { 5247a0c41d5SAlan Somers } 5257a0c41d5SAlan Somers 5267a0c41d5SAlan Somers DevfsEvent::DevfsEvent(const DevfsEvent &src) 5277a0c41d5SAlan Somers : Event(src) 5287a0c41d5SAlan Somers { 5297a0c41d5SAlan Somers } 5307a0c41d5SAlan Somers 5317a0c41d5SAlan Somers /*--------------------------------- GeomEvent --------------------------------*/ 5327a0c41d5SAlan Somers //- GeomEvent Static Public Methods -------------------------------------------- 5337a0c41d5SAlan Somers Event * 5347a0c41d5SAlan Somers GeomEvent::Builder(Event::Type type, NVPairMap &nvpairs, 5357a0c41d5SAlan Somers const string &eventString) 5367a0c41d5SAlan Somers { 5377a0c41d5SAlan Somers return (new GeomEvent(type, nvpairs, eventString)); 5387a0c41d5SAlan Somers } 5397a0c41d5SAlan Somers 5407a0c41d5SAlan Somers //- GeomEvent Virtual Public Methods ------------------------------------------- 5417a0c41d5SAlan Somers Event * 5427a0c41d5SAlan Somers GeomEvent::DeepCopy() const 5437a0c41d5SAlan Somers { 5447a0c41d5SAlan Somers return (new GeomEvent(*this)); 5457a0c41d5SAlan Somers } 5467a0c41d5SAlan Somers 5477a0c41d5SAlan Somers bool 5487a0c41d5SAlan Somers GeomEvent::DevName(std::string &name) const 5497a0c41d5SAlan Somers { 550a07d59d1SAlan Somers if (Value("subsystem") == "disk") 5517a0c41d5SAlan Somers name = Value("devname"); 552a07d59d1SAlan Somers else 553a07d59d1SAlan Somers name = Value("cdev"); 5547a0c41d5SAlan Somers return (!name.empty()); 5557a0c41d5SAlan Somers } 5567a0c41d5SAlan Somers 5577a0c41d5SAlan Somers 5587a0c41d5SAlan Somers //- GeomEvent Protected Methods ------------------------------------------------ 5597a0c41d5SAlan Somers GeomEvent::GeomEvent(Event::Type type, NVPairMap &nvpairs, 5607a0c41d5SAlan Somers const string &eventString) 5617a0c41d5SAlan Somers : Event(type, nvpairs, eventString), 5627a0c41d5SAlan Somers m_devname(Value("devname")) 5637a0c41d5SAlan Somers { 5647a0c41d5SAlan Somers } 5657a0c41d5SAlan Somers 5667a0c41d5SAlan Somers GeomEvent::GeomEvent(const GeomEvent &src) 5677a0c41d5SAlan Somers : Event(src), 5687a0c41d5SAlan Somers m_devname(src.m_devname) 5697a0c41d5SAlan Somers { 5707a0c41d5SAlan Somers } 5717a0c41d5SAlan Somers 5727a0c41d5SAlan Somers /*--------------------------------- ZfsEvent ---------------------------------*/ 5737a0c41d5SAlan Somers //- ZfsEvent Static Public Methods --------------------------------------------- 5747a0c41d5SAlan Somers Event * 5757a0c41d5SAlan Somers ZfsEvent::Builder(Event::Type type, NVPairMap &nvpairs, 5767a0c41d5SAlan Somers const string &eventString) 5777a0c41d5SAlan Somers { 5787a0c41d5SAlan Somers return (new ZfsEvent(type, nvpairs, eventString)); 5797a0c41d5SAlan Somers } 5807a0c41d5SAlan Somers 5817a0c41d5SAlan Somers //- ZfsEvent Virtual Public Methods -------------------------------------------- 5827a0c41d5SAlan Somers Event * 5837a0c41d5SAlan Somers ZfsEvent::DeepCopy() const 5847a0c41d5SAlan Somers { 5857a0c41d5SAlan Somers return (new ZfsEvent(*this)); 5867a0c41d5SAlan Somers } 5877a0c41d5SAlan Somers 5887a0c41d5SAlan Somers bool 5897a0c41d5SAlan Somers ZfsEvent::DevName(std::string &name) const 5907a0c41d5SAlan Somers { 5917a0c41d5SAlan Somers return (false); 5927a0c41d5SAlan Somers } 5937a0c41d5SAlan Somers 5947a0c41d5SAlan Somers //- ZfsEvent Protected Methods ------------------------------------------------- 5957a0c41d5SAlan Somers ZfsEvent::ZfsEvent(Event::Type type, NVPairMap &nvpairs, 5967a0c41d5SAlan Somers const string &eventString) 5977a0c41d5SAlan Somers : Event(type, nvpairs, eventString), 5987a0c41d5SAlan Somers m_poolGUID(Guid(Value("pool_guid"))), 5997a0c41d5SAlan Somers m_vdevGUID(Guid(Value("vdev_guid"))) 6007a0c41d5SAlan Somers { 6017a0c41d5SAlan Somers } 6027a0c41d5SAlan Somers 6037a0c41d5SAlan Somers ZfsEvent::ZfsEvent(const ZfsEvent &src) 6047a0c41d5SAlan Somers : Event(src), 6057a0c41d5SAlan Somers m_poolGUID(src.m_poolGUID), 6067a0c41d5SAlan Somers m_vdevGUID(src.m_vdevGUID) 6077a0c41d5SAlan Somers { 6087a0c41d5SAlan Somers } 6097a0c41d5SAlan Somers 6107a0c41d5SAlan Somers } // namespace DevdCtl 611