MFP4 zfsd-related changes
Convert libdevctl to use devd's new SEQPACKET socket. lib/libdevctl/consumer.cc lib/libdevctl/event_buffer.cc lib/libdevctl/event_buffer.h lib/libdevctl/reader.cc lib/libdevctl/reader.h Read from the new /var/run/devd.seqpacket.pipe instead of /var/run/devd.pipe. Since it preserves record boundaries, we can eliminate all the repacketization code in EventBuffer::ExtractEvent as well as much supporting code from the Reader class. lib/libdevctl/consumer.cc Make the pipe nonblocking. Previously, we avoided blocking by using the FIONREAD ioctl, but this is simpler. cddl/sbin/zfsd/case_file.cc cddl/sbin/zfsd/tests/zfsd_unittest.cc cddl/sbin/zfsd/vdev.cc cddl/sbin/zfsd/zfsd.cc cddl/sbin/zfsd/zfsd.h cddl/sbin/zfsd/zfsd_event.cc Update zfsd according to the libdevctl changes. The only nontrivial change is to CaseFile::DeSerialize, which elimintes the use of IStreamReader. cddl/sbin/zfsd/case_file.cc For an unknown reason, sometimes the std::ios::failbit will get set on caseStream. Instead of checking for !eof(), check for good(). That method checks the eofbit, errorbit, and failbit. livdevctl cleanup (from gibbs) lib/libdevctl/event.cc: lib/libdevctl/event.h: Remove the event class's name from its Builder method. It's perfectly clear that DevfsEvent::Builder() is the DevfsEvent class's Builder function. cddl/sbin/zfsd/zfsd.cc: cddl/sbin/zfsd/zfsd_event.cc: cddl/sbin/zfsd/zfsd_event.h: Conform to new libdevct Builder naming convention. Fix autoreplace by physical path when a hotspare is present cddl/sbin/zfsd/case_file.cc Fix logic error in CaseFile::Replace regarding whether the replacement device is a spare or not. Reviewed by: gibbs Sponsored by: Spectra Logic
This commit is contained in:
parent
9102691e9c
commit
6c96553e8a
@ -59,11 +59,9 @@
|
||||
|
||||
#include <devctl/guid.h>
|
||||
#include <devctl/event.h>
|
||||
#include <devctl/event_buffer.h>
|
||||
#include <devctl/event_factory.h>
|
||||
#include <devctl/exception.h>
|
||||
#include <devctl/consumer.h>
|
||||
#include <devctl/reader.h>
|
||||
|
||||
#include "callout.h"
|
||||
#include "vdev_iterator.h"
|
||||
@ -89,7 +87,6 @@ using DevCtl::EventBuffer;
|
||||
using DevCtl::EventFactory;
|
||||
using DevCtl::EventList;
|
||||
using DevCtl::Guid;
|
||||
using DevCtl::IstreamReader;
|
||||
using DevCtl::ParseException;
|
||||
|
||||
/*-------------------------- File-scoped classes ----------------------------*/
|
||||
@ -840,26 +837,28 @@ CaseFile::Serialize()
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX: This method assumes that events may not contain embedded newlines. If
|
||||
* ever events can contain embedded newlines, then CaseFile must switch
|
||||
* serialization formats
|
||||
*/
|
||||
void
|
||||
CaseFile::DeSerialize(ifstream &caseStream)
|
||||
{
|
||||
stringstream fakeDevdSocket(stringstream::in|stringstream::out);
|
||||
IstreamReader caseReader(&fakeDevdSocket);
|
||||
EventBuffer eventBuffer(caseReader);
|
||||
string evString;
|
||||
const EventFactory &factory(ZfsDaemon::Get().GetFactory());
|
||||
|
||||
caseStream >> std::noskipws >> std::ws;
|
||||
while (!caseStream.eof()) {
|
||||
while (caseStream.good()) {
|
||||
/*
|
||||
* Outline:
|
||||
* read the beginning of a line and check it for
|
||||
* "tentative". If found, discard "tentative".
|
||||
* Shove into fakeDevdSocket.
|
||||
* call ExtractEvent
|
||||
* Create a new event
|
||||
* continue
|
||||
*/
|
||||
EventList* destEvents;
|
||||
string tentFlag("tentative ");
|
||||
const string tentFlag("tentative ");
|
||||
string line;
|
||||
std::stringbuf lineBuf;
|
||||
|
||||
@ -867,20 +866,16 @@ CaseFile::DeSerialize(ifstream &caseStream)
|
||||
caseStream.ignore(); /*discard the newline character*/
|
||||
line = lineBuf.str();
|
||||
if (line.compare(0, tentFlag.size(), tentFlag) == 0) {
|
||||
/* Discard "tentative" */
|
||||
line.erase(0, tentFlag.size());
|
||||
destEvents = &m_tentativeEvents;
|
||||
} else {
|
||||
destEvents = &m_events;
|
||||
}
|
||||
fakeDevdSocket << line;
|
||||
fakeDevdSocket << '\n';
|
||||
const EventFactory &factory(ZfsDaemon::Get().GetFactory());
|
||||
while (eventBuffer.ExtractEvent(evString)) {
|
||||
Event *event(Event::CreateEvent(factory, evString));
|
||||
if (event != NULL) {
|
||||
destEvents->push_back(event);
|
||||
RegisterCallout(*event);
|
||||
}
|
||||
Event *event(Event::CreateEvent(factory, line));
|
||||
if (event != NULL) {
|
||||
destEvents->push_back(event);
|
||||
RegisterCallout(*event);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1032,7 +1027,7 @@ CaseFile::Replace(const char* vdev_type, const char* path, bool isspare) {
|
||||
Vdev vd(zhp, CaseVdev(zhp));
|
||||
Vdev replaced(BeingReplacedBy(zhp));
|
||||
|
||||
if (!vd.IsSpare() && !replaced.DoesNotExist()) {
|
||||
if (isspare && !vd.IsSpare() && !replaced.DoesNotExist()) {
|
||||
/* If we are already being replaced by a working spare, pass. */
|
||||
if (replaced.IsResilvering()
|
||||
|| replaced.State() == VDEV_STATE_HEALTHY) {
|
||||
@ -1044,12 +1039,10 @@ CaseFile::Replace(const char* vdev_type, const char* path, bool isspare) {
|
||||
* If we have already been replaced by a spare, but that spare
|
||||
* is broken, we must spare the spare, not the original device.
|
||||
*/
|
||||
if (isspare) {
|
||||
oldstr = replaced.GUIDString();
|
||||
syslog(LOG_INFO, "CaseFile::Replace(%s->%s): sparing "
|
||||
"broken spare %s instead", VdevGUIDString().c_str(),
|
||||
path, oldstr.c_str());
|
||||
}
|
||||
oldstr = replaced.GUIDString();
|
||||
syslog(LOG_INFO, "CaseFile::Replace(%s->%s): sparing "
|
||||
"broken spare %s instead", VdevGUIDString().c_str(),
|
||||
path, oldstr.c_str());
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -7,8 +7,6 @@ SRCDIR=${.CURDIR}/../../../..
|
||||
PROG_CXX= zfsd_unittest
|
||||
SRCS:= ${SRCS:Nzfsd_main.cc}
|
||||
SRCS+= libmocks.c zfsd_unittest.cc
|
||||
CLEANFILES+= *.gcno *.gcda *.info
|
||||
CLEANDIRS+= lcov-report
|
||||
|
||||
# Use #include <zfsd/xxx.h> in test programs.
|
||||
INCFLAGS+= -I ${.CURDIR}/../..
|
||||
@ -26,9 +24,6 @@ LIBRARY_PATH=
|
||||
.endif
|
||||
ZFSD_UNITTEST= env LD_LIBRARY_PATH=${LIBRARY_PATH} ./zfsd_unittest
|
||||
|
||||
# Extra tools
|
||||
LCOV= lcov
|
||||
|
||||
# Googletest options
|
||||
LOCALBASE?= /usr/local
|
||||
INCFLAGS+= -I ${LOCALBASE}/include -D_THREAD_SAFE -pthread
|
||||
@ -42,42 +37,12 @@ LDADD+= ${LOCALBASE}/lib/libgmock.a ${LOCALBASE}/lib/libgmock_main.a
|
||||
# https://groups.google.com/forum/#!msg/googletestframework/h8ixEPCFm0o/amwfu4xGJb0J
|
||||
CFLAGS+= -DGTEST_HAS_PTHREAD
|
||||
|
||||
# GCOV options
|
||||
CFLAGS+= -fprofile-arcs -ftest-coverage
|
||||
LDADD+= -lgcov
|
||||
|
||||
all: tests
|
||||
|
||||
# Install the tests
|
||||
TESTSBASE?= /usr/tests
|
||||
TESTSDIR= ${TESTSBASE}/zfsd
|
||||
TESTSDIR= ${TESTSBASE}/cddl/sbin/zfsd
|
||||
# TODO: Convert from an ATF SH test to a Kyua plain test
|
||||
# Long term TODO: Convert to a Kyua googletest test
|
||||
TESTS_SH+= zfsd_test
|
||||
ATF_TESTS_SH+= zfsd_test
|
||||
BINDIR= ${TESTSDIR}
|
||||
|
||||
# Install the gcov annotation files too
|
||||
FILESDIR= ${TESTSDIR}
|
||||
GCNOS= ${SRCS:C/.c+$/.gcno/}
|
||||
${GCNOS}: ${SRCS:C/.c+$/.o/}
|
||||
FILES= ${GCNOS}
|
||||
|
||||
|
||||
# Run the tests and produce the coverage report
|
||||
EXCLUDE_PATTERNS='/usr/include/*' '${LOCALBASE}/include/*'
|
||||
EXCLUDE_PATTERNS+= '*/cddl/compat/opensolaris/include/*'
|
||||
EXCLUDE_PATTERNS+= '*/tools/regression/zfsd/*'
|
||||
.PHONY: tests
|
||||
tests: zfsd_unittest
|
||||
${ZFSD_UNITTEST} --gmock_verbose=error
|
||||
|
||||
.PHONY: lcov
|
||||
lcov: zfsd_unittest
|
||||
${LCOV} -z -d . -f && \
|
||||
${ZFSD_UNITTEST} --gmock_verbose=error
|
||||
${LCOV} -f -d . -c -o default.info && \
|
||||
${LCOV} -r default.info $(EXCLUDE_PATTERNS) -o trimmed.info && \
|
||||
mkdir -p lcov-report && \
|
||||
genhtml -o lcov-report trimmed.info
|
||||
|
||||
.include <atf.test.mk>
|
||||
.include <bsd.test.mk>
|
||||
|
@ -43,7 +43,26 @@ zfsd_unittest_head()
|
||||
|
||||
zfsd_unittest_body()
|
||||
{
|
||||
atf_check -s exit:0 -o ignore -e ignore $(atf_get_srcdir)/zfsd_unittest
|
||||
TESTPROG=$(atf_get_srcdir)/zfsd_unittest
|
||||
if atf_config_has coverage_dir; then
|
||||
# If coverage_dir is defined, then we want to save the .gcda
|
||||
# and .gcno files for future analysis. Put them in a directory
|
||||
# tree that resembles /usr/src, but is anchored at
|
||||
# coverage_dir.
|
||||
export GCOV_PREFIX=`atf_config_get coverage_dir`
|
||||
# Examine zfsd_unittest to calculate the GCOV_PREFIX_STRIP
|
||||
# The outer echo command is needed to strip off whitespace
|
||||
# printed by wc
|
||||
OLDGCDADIR=`strings $TESTPROG | grep 'zfsd.gcda'`
|
||||
export GCOV_PREFIX_STRIP=$( echo $( echo $OLDGCDADIR | \
|
||||
sed -e 's:/cddl/sbin/zfsd.*::' -e 's:/: :g' | \
|
||||
wc -w ) )
|
||||
NEWGCDADIR=$GCOV_PREFIX/`dirname $OLDGCDADIR | \
|
||||
sed -e 's:.*\(cddl/sbin/zfsd\):\1:'`
|
||||
mkdir -p $NEWGCDADIR
|
||||
cp $(atf_get_srcdir)/*.gcno $NEWGCDADIR
|
||||
fi
|
||||
atf_check -s exit:0 -o ignore -e ignore $TESTPROG
|
||||
}
|
||||
|
||||
atf_init_test_cases()
|
||||
|
@ -47,11 +47,9 @@
|
||||
|
||||
#include <devctl/guid.h>
|
||||
#include <devctl/event.h>
|
||||
#include <devctl/event_buffer.h>
|
||||
#include <devctl/event_factory.h>
|
||||
#include <devctl/exception.h>
|
||||
#include <devctl/consumer.h>
|
||||
#include <devctl/reader.h>
|
||||
|
||||
#include <zfsd/callout.h>
|
||||
#include <zfsd/vdev_iterator.h>
|
||||
@ -365,17 +363,12 @@ TEST_F(VdevTest, AvailSpareState) {
|
||||
|
||||
/* Test the Vdev::IsSpare method */
|
||||
TEST_F(VdevTest, IsSpare) {
|
||||
Vdev* vdev;
|
||||
|
||||
vdev = new Vdev(m_poolConfig, m_vdevConfig);
|
||||
EXPECT_EQ(false, vdev->IsSpare());
|
||||
delete vdev;
|
||||
|
||||
Vdev notSpare(m_poolConfig, m_vdevConfig);
|
||||
EXPECT_EQ(false, notSpare.IsSpare());
|
||||
|
||||
ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig, ZPOOL_CONFIG_IS_SPARE, 1));
|
||||
vdev = new Vdev(m_poolConfig, m_vdevConfig);
|
||||
EXPECT_EQ(true, vdev->IsSpare());
|
||||
delete vdev;
|
||||
Vdev isSpare(m_poolConfig, m_vdevConfig);
|
||||
EXPECT_EQ(true, isSpare.IsSpare());
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -50,7 +50,6 @@
|
||||
|
||||
#include <devctl/guid.h>
|
||||
#include <devctl/event.h>
|
||||
#include <devctl/event_buffer.h>
|
||||
#include <devctl/event_factory.h>
|
||||
#include <devctl/exception.h>
|
||||
#include <devctl/consumer.h>
|
||||
|
@ -59,11 +59,9 @@
|
||||
|
||||
#include <devctl/guid.h>
|
||||
#include <devctl/event.h>
|
||||
#include <devctl/event_buffer.h>
|
||||
#include <devctl/event_factory.h>
|
||||
#include <devctl/exception.h>
|
||||
#include <devctl/consumer.h>
|
||||
#include <devctl/reader.h>
|
||||
|
||||
#include "callout.h"
|
||||
#include "vdev_iterator.h"
|
||||
@ -82,11 +80,8 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
/*============================ Namespace Control =============================*/
|
||||
using DevCtl::Event;
|
||||
using DevCtl::EventBuffer;
|
||||
using DevCtl::EventFactory;
|
||||
using DevCtl::EventList;
|
||||
using DevCtl::Guid;
|
||||
using DevCtl::NVPairMap;
|
||||
|
||||
/*================================ Global Data ===============================*/
|
||||
int g_debug = 0;
|
||||
@ -103,8 +98,8 @@ int ZfsDaemon::s_signalPipeFD[2];
|
||||
bool ZfsDaemon::s_systemRescanRequested(false);
|
||||
EventFactory::Record ZfsDaemon::s_registryEntries[] =
|
||||
{
|
||||
{ Event::NOTIFY, "DEVFS", &DevfsEvent::DevfsEventBuilder },
|
||||
{ Event::NOTIFY, "ZFS", &ZfsEvent::ZfsEventBuilder }
|
||||
{ Event::NOTIFY, "DEVFS", &DevfsEvent::Builder },
|
||||
{ Event::NOTIFY, "ZFS", &ZfsEvent::Builder }
|
||||
};
|
||||
|
||||
//- ZfsDaemon Static Public Methods --------------------------------------------
|
||||
|
@ -52,7 +52,6 @@
|
||||
* #include <devctl/event.h>
|
||||
* #include <devctl/event_factory.h>
|
||||
* #include <devctl/consumer.h>
|
||||
* #include <devctl/reader.h>
|
||||
*
|
||||
* #include "vdev_iterator.h"
|
||||
*/
|
||||
|
@ -51,7 +51,6 @@
|
||||
#include <devctl/event_factory.h>
|
||||
#include <devctl/exception.h>
|
||||
#include <devctl/consumer.h>
|
||||
#include <devctl/reader.h>
|
||||
|
||||
#include "callout.h"
|
||||
#include "vdev_iterator.h"
|
||||
@ -75,9 +74,9 @@ using std::stringstream;
|
||||
|
||||
//- DevfsEvent Static Public Methods -------------------------------------------
|
||||
Event *
|
||||
DevfsEvent::DevfsEventBuilder(Event::Type type,
|
||||
NVPairMap &nvPairs,
|
||||
const string &eventString)
|
||||
DevfsEvent::Builder(Event::Type type,
|
||||
NVPairMap &nvPairs,
|
||||
const string &eventString)
|
||||
{
|
||||
return (new DevfsEvent(type, nvPairs, eventString));
|
||||
}
|
||||
@ -230,8 +229,8 @@ DevfsEvent::DevfsEvent(const DevfsEvent &src)
|
||||
/*--------------------------------- ZfsEvent ---------------------------------*/
|
||||
//- ZfsEvent Static Public Methods ---------------------------------------------
|
||||
DevCtl::Event *
|
||||
ZfsEvent::ZfsEventBuilder(Event::Type type, NVPairMap &nvpairs,
|
||||
const string &eventString)
|
||||
ZfsEvent::Builder(Event::Type type, NVPairMap &nvpairs,
|
||||
const string &eventString)
|
||||
{
|
||||
return (new ZfsEvent(type, nvpairs, eventString));
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ class DevfsEvent : public DevCtl::DevfsEvent
|
||||
{
|
||||
public:
|
||||
/** Specialized DevCtlEvent object factory for Devfs events. */
|
||||
static BuildMethod DevfsEventBuilder;
|
||||
static BuildMethod Builder;
|
||||
|
||||
virtual DevCtl::Event *DeepCopy() const;
|
||||
|
||||
@ -122,7 +122,7 @@ class ZfsEvent : public DevCtl::ZfsEvent
|
||||
{
|
||||
public:
|
||||
/** Specialized DevCtlEvent object factory for ZFS events. */
|
||||
static BuildMethod ZfsEventBuilder;
|
||||
static BuildMethod Builder;
|
||||
|
||||
virtual DevCtl::Event *DeepCopy() const;
|
||||
|
||||
|
@ -54,6 +54,8 @@
|
||||
lib
|
||||
..
|
||||
sbin
|
||||
zfsd
|
||||
..
|
||||
..
|
||||
usr.bin
|
||||
..
|
||||
|
@ -3,18 +3,14 @@
|
||||
LIB= devctl
|
||||
INCS= consumer.h \
|
||||
event.h \
|
||||
event_buffer.h \
|
||||
event_factory.h \
|
||||
exception.h \
|
||||
guid.h \
|
||||
reader.h
|
||||
guid.h
|
||||
SRCS= consumer.cc \
|
||||
event.cc \
|
||||
event_buffer.cc \
|
||||
event_factory.cc \
|
||||
exception.cc \
|
||||
guid.cc \
|
||||
reader.cc
|
||||
guid.cc
|
||||
|
||||
INCSDIR= ${INCLUDEDIR}/devctl
|
||||
|
||||
|
@ -37,24 +37,24 @@
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cstdarg>
|
||||
#include <cstring>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "guid.h"
|
||||
#include "event.h"
|
||||
#include "event_buffer.h"
|
||||
#include "event_factory.h"
|
||||
#include "exception.h"
|
||||
#include "reader.h"
|
||||
|
||||
#include "consumer.h"
|
||||
|
||||
@ -71,15 +71,13 @@ namespace DevCtl
|
||||
/*============================= Class Definitions ============================*/
|
||||
/*----------------------------- DevCtl::Consumer -----------------------------*/
|
||||
//- Consumer Static Private Data -----------------------------------------------
|
||||
const char Consumer::s_devdSockPath[] = "/var/run/devd.pipe";
|
||||
const char Consumer::s_devdSockPath[] = "/var/run/devd.seqpacket.pipe";
|
||||
|
||||
//- Consumer Public Methods ----------------------------------------------------
|
||||
Consumer::Consumer(Event::BuildMethod *defBuilder,
|
||||
EventFactory::Record *regEntries,
|
||||
size_t numEntries)
|
||||
: m_devdSockFD(-1),
|
||||
m_reader(NULL),
|
||||
m_eventBuffer(NULL),
|
||||
m_eventFactory(defBuilder),
|
||||
m_replayingEvents(false)
|
||||
{
|
||||
@ -89,8 +87,6 @@ Consumer::Consumer(Event::BuildMethod *defBuilder,
|
||||
Consumer::~Consumer()
|
||||
{
|
||||
DisconnectFromDevd();
|
||||
delete m_reader;
|
||||
m_reader = NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -112,9 +108,11 @@ Consumer::ConnectToDevd()
|
||||
strlcpy(devdAddr.sun_path, s_devdSockPath, sizeof(devdAddr.sun_path));
|
||||
sLen = SUN_LEN(&devdAddr);
|
||||
|
||||
m_devdSockFD = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
m_devdSockFD = socket(AF_UNIX, SOCK_SEQPACKET, 0);
|
||||
if (m_devdSockFD == -1)
|
||||
err(1, "Unable to create socket");
|
||||
if (fcntl(m_devdSockFD, F_SETFL, O_NONBLOCK) < 0)
|
||||
err(1, "fcntl");
|
||||
result = connect(m_devdSockFD,
|
||||
reinterpret_cast<sockaddr *>(&devdAddr),
|
||||
sLen);
|
||||
@ -124,9 +122,6 @@ Consumer::ConnectToDevd()
|
||||
return (false);
|
||||
}
|
||||
|
||||
/* Connect the stream to the file descriptor */
|
||||
m_reader = new FDReader(m_devdSockFD);
|
||||
m_eventBuffer = new EventBuffer(*m_reader);
|
||||
syslog(LOG_INFO, "Connection to devd successful");
|
||||
return (true);
|
||||
}
|
||||
@ -137,14 +132,26 @@ Consumer::DisconnectFromDevd()
|
||||
if (m_devdSockFD != -1)
|
||||
syslog(LOG_INFO, "Disconnecting from devd.");
|
||||
|
||||
delete m_eventBuffer;
|
||||
m_eventBuffer = NULL;
|
||||
delete m_reader;
|
||||
m_reader = NULL;
|
||||
close(m_devdSockFD);
|
||||
m_devdSockFD = -1;
|
||||
}
|
||||
|
||||
std::string
|
||||
Consumer::ReadEvent()
|
||||
{
|
||||
char buf[MAX_EVENT_SIZE + 1];
|
||||
ssize_t len;
|
||||
|
||||
len = ::recv(m_devdSockFD, buf, MAX_EVENT_SIZE, MSG_WAITALL);
|
||||
if (len == -1)
|
||||
return (std::string(""));
|
||||
else {
|
||||
/* NULL-terminate the result */
|
||||
buf[len] = '\0';
|
||||
return (std::string(buf));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Consumer::ReplayUnconsumedEvents(bool discardUnconsumed)
|
||||
{
|
||||
@ -178,20 +185,20 @@ Consumer::SaveEvent(const Event &event)
|
||||
}
|
||||
|
||||
Event *
|
||||
Consumer::NextEvent(EventBuffer *eventBuffer)
|
||||
Consumer::NextEvent()
|
||||
{
|
||||
if (!Connected())
|
||||
return(NULL);
|
||||
|
||||
if (eventBuffer == NULL)
|
||||
eventBuffer = m_eventBuffer;
|
||||
|
||||
Event *event(NULL);
|
||||
try {
|
||||
string evString;
|
||||
|
||||
if (eventBuffer->ExtractEvent(evString))
|
||||
evString = ReadEvent();
|
||||
if (! evString.empty()) {
|
||||
Event::TimestampEventString(evString);
|
||||
event = Event::CreateEvent(m_eventFactory, evString);
|
||||
}
|
||||
} catch (const Exception &exp) {
|
||||
exp.Log();
|
||||
DisconnectFromDevd();
|
||||
@ -201,10 +208,10 @@ Consumer::NextEvent(EventBuffer *eventBuffer)
|
||||
|
||||
/* Capture and process buffered events. */
|
||||
void
|
||||
Consumer::ProcessEvents(EventBuffer *eventBuffer)
|
||||
Consumer::ProcessEvents()
|
||||
{
|
||||
Event *event;
|
||||
while ((event = NextEvent(eventBuffer)) != NULL) {
|
||||
while ((event = NextEvent()) != NULL) {
|
||||
if (event->Process())
|
||||
SaveEvent(*event);
|
||||
delete event;
|
||||
@ -214,10 +221,11 @@ Consumer::ProcessEvents(EventBuffer *eventBuffer)
|
||||
void
|
||||
Consumer::FlushEvents()
|
||||
{
|
||||
char discardBuf[256];
|
||||
std::string s;
|
||||
|
||||
while (m_reader->in_avail() > 0)
|
||||
m_reader->read(discardBuf, sizeof(discardBuf));
|
||||
do
|
||||
s = ReadEvent();
|
||||
while (! s.empty()) ;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -81,14 +81,13 @@ public:
|
||||
*/
|
||||
void ReplayUnconsumedEvents(bool discardUnconsumed);
|
||||
|
||||
/** Return an event, if available, from the provided EventBuffer. */
|
||||
Event *NextEvent(EventBuffer *eventBuffer = NULL);
|
||||
/** Return an event, if one is available. */
|
||||
Event *NextEvent();
|
||||
|
||||
/**
|
||||
* Extract events from the provided eventBuffer and invoke
|
||||
* each event's Process method.
|
||||
* Extract events and invoke each event's Process method.
|
||||
*/
|
||||
void ProcessEvents(EventBuffer *eventBuffer = NULL);
|
||||
void ProcessEvents();
|
||||
|
||||
/** Discard all data pending in m_devdSockFD. */
|
||||
void FlushEvents();
|
||||
@ -116,6 +115,22 @@ public:
|
||||
EventFactory GetFactory();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* \brief Reads the most recent record
|
||||
*
|
||||
* On error, "" is returned, and errno will be set by the OS
|
||||
*
|
||||
* \returns A string containing the record
|
||||
*/
|
||||
std::string ReadEvent();
|
||||
|
||||
enum {
|
||||
/*
|
||||
* The maximum event size supported by libdevctl.
|
||||
*/
|
||||
MAX_EVENT_SIZE = 8192,
|
||||
};
|
||||
|
||||
static const char s_devdSockPath[];
|
||||
|
||||
/**
|
||||
|
@ -40,12 +40,18 @@
|
||||
#include <sys/disk.h>
|
||||
#include <sys/filio.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <fcntl.h>
|
||||
#include <paths.h>
|
||||
#include <stdlib.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cstdarg>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <map>
|
||||
@ -86,8 +92,8 @@ Event::EventTypeRecord Event::s_typeTable[] =
|
||||
|
||||
//- Event Static Public Methods ------------------------------------------------
|
||||
Event *
|
||||
Event::EventBuilder(Event::Type type, NVPairMap &nvPairs,
|
||||
const string &eventString)
|
||||
Event::Builder(Event::Type type, NVPairMap &nvPairs,
|
||||
const string &eventString)
|
||||
{
|
||||
return (new Event(type, nvPairs, eventString));
|
||||
}
|
||||
@ -325,11 +331,35 @@ Event::ParseEventString(Event::Type type,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Event::TimestampEventString(std::string &eventString)
|
||||
{
|
||||
if (eventString.size() > 0) {
|
||||
/*
|
||||
* Add a timestamp as the final field of the event if it is
|
||||
* not already present.
|
||||
*/
|
||||
if (eventString.find("timestamp=") == string::npos) {
|
||||
const size_t bufsize = 32; // Long enough for a 64-bit int
|
||||
timeval now;
|
||||
struct tm* time_s;
|
||||
char timebuf[bufsize];
|
||||
|
||||
size_t eventEnd(eventString.find_last_not_of('\n') + 1);
|
||||
if (gettimeofday(&now, NULL) != 0)
|
||||
err(1, "gettimeofday");
|
||||
time_s = gmtime(&now.tv_sec);
|
||||
strftime(timebuf, bufsize, " timestamp=%s", time_s);
|
||||
eventString.insert(eventEnd, timebuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------- DevfsEvent --------------------------------*/
|
||||
//- DevfsEvent Static Public Methods -------------------------------------------
|
||||
Event *
|
||||
DevfsEvent::DevfsEventBuilder(Event::Type type, NVPairMap &nvPairs,
|
||||
const string &eventString)
|
||||
DevfsEvent::Builder(Event::Type type, NVPairMap &nvPairs,
|
||||
const string &eventString)
|
||||
{
|
||||
return (new DevfsEvent(type, nvPairs, eventString));
|
||||
}
|
||||
@ -495,8 +525,8 @@ DevfsEvent::DevfsEvent(const DevfsEvent &src)
|
||||
/*--------------------------------- ZfsEvent ---------------------------------*/
|
||||
//- ZfsEvent Static Public Methods ---------------------------------------------
|
||||
Event *
|
||||
ZfsEvent::ZfsEventBuilder(Event::Type type, NVPairMap &nvpairs,
|
||||
const string &eventString)
|
||||
ZfsEvent::Builder(Event::Type type, NVPairMap &nvpairs,
|
||||
const string &eventString)
|
||||
{
|
||||
return (new ZfsEvent(type, nvpairs, eventString));
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ public:
|
||||
typedef Event* (BuildMethod)(Type, NVPairMap &, const std::string &);
|
||||
|
||||
/** Generic Event object factory. */
|
||||
static BuildMethod EventBuilder;
|
||||
static BuildMethod Builder;
|
||||
|
||||
static Event *CreateEvent(const EventFactory &factory,
|
||||
const std::string &eventString);
|
||||
@ -189,6 +189,16 @@ public:
|
||||
*/
|
||||
timeval GetTimestamp() const;
|
||||
|
||||
/**
|
||||
* Add a timestamp to the event string, if one does not already exist
|
||||
* TODO: make this an instance method that operates on the std::map
|
||||
* instead of the string. We must fix zfsd's CaseFile serialization
|
||||
* routines first, so that they don't need the raw event string.
|
||||
*
|
||||
* \param[in,out] eventString The devd event string to modify
|
||||
*/
|
||||
static void TimestampEventString(std::string &eventString);
|
||||
|
||||
/**
|
||||
* Access all parsed key => value pairs.
|
||||
*/
|
||||
@ -277,7 +287,7 @@ class DevfsEvent : public Event
|
||||
{
|
||||
public:
|
||||
/** Specialized Event object factory for Devfs events. */
|
||||
static BuildMethod DevfsEventBuilder;
|
||||
static BuildMethod Builder;
|
||||
|
||||
virtual Event *DeepCopy() const;
|
||||
|
||||
@ -326,7 +336,7 @@ class ZfsEvent : public Event
|
||||
{
|
||||
public:
|
||||
/** Specialized Event object factory for ZFS events. */
|
||||
static BuildMethod ZfsEventBuilder;
|
||||
static BuildMethod Builder;
|
||||
|
||||
virtual Event *DeepCopy() const;
|
||||
|
||||
|
@ -88,8 +88,10 @@ EventFactory::Build(Event::Type type, NVPairMap &nvpairs,
|
||||
if (foundMethod != m_registry.end())
|
||||
buildMethod = foundMethod->second;
|
||||
|
||||
if (buildMethod == NULL)
|
||||
if (buildMethod == NULL) {
|
||||
delete &nvpairs;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (buildMethod(type, nvpairs, eventString));
|
||||
}
|
||||
|
@ -37,6 +37,8 @@
|
||||
|
||||
#include <syslog.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user