Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 23 May 2014 23:13:35 +0000 (UTC)
From:      Alan Somers <asomers@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r266602 - in projects/zfsd/head: cddl/sbin/zfsd cddl/sbin/zfsd/tests etc/mtree lib/libdevctl
Message-ID:  <201405232313.s4NNDZlu010781@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: asomers
Date: Fri May 23 23:13:34 2014
New Revision: 266602
URL: http://svnweb.freebsd.org/changeset/base/266602

Log:
  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

Modified:
  projects/zfsd/head/cddl/sbin/zfsd/case_file.cc
  projects/zfsd/head/cddl/sbin/zfsd/tests/Makefile
  projects/zfsd/head/cddl/sbin/zfsd/tests/zfsd_test.sh
  projects/zfsd/head/cddl/sbin/zfsd/tests/zfsd_unittest.cc
  projects/zfsd/head/cddl/sbin/zfsd/vdev.cc
  projects/zfsd/head/cddl/sbin/zfsd/zfsd.cc
  projects/zfsd/head/cddl/sbin/zfsd/zfsd.h
  projects/zfsd/head/cddl/sbin/zfsd/zfsd_event.cc
  projects/zfsd/head/cddl/sbin/zfsd/zfsd_event.h
  projects/zfsd/head/etc/mtree/BSD.tests.dist
  projects/zfsd/head/lib/libdevctl/Makefile
  projects/zfsd/head/lib/libdevctl/consumer.cc
  projects/zfsd/head/lib/libdevctl/consumer.h
  projects/zfsd/head/lib/libdevctl/event.cc
  projects/zfsd/head/lib/libdevctl/event.h
  projects/zfsd/head/lib/libdevctl/event_factory.cc
  projects/zfsd/head/lib/libdevctl/exception.cc

Modified: projects/zfsd/head/cddl/sbin/zfsd/case_file.cc
==============================================================================
--- projects/zfsd/head/cddl/sbin/zfsd/case_file.cc	Fri May 23 23:13:17 2014	(r266601)
+++ projects/zfsd/head/cddl/sbin/zfsd/case_file.cc	Fri May 23 23:13:34 2014	(r266602)
@@ -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 &caseStre
 		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,
 	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,
 		 * 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());
 	}
 
 	/*

Modified: projects/zfsd/head/cddl/sbin/zfsd/tests/Makefile
==============================================================================
--- projects/zfsd/head/cddl/sbin/zfsd/tests/Makefile	Fri May 23 23:13:17 2014	(r266601)
+++ projects/zfsd/head/cddl/sbin/zfsd/tests/Makefile	Fri May 23 23:13:34 2014	(r266602)
@@ -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 ${LO
 # 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>

Modified: projects/zfsd/head/cddl/sbin/zfsd/tests/zfsd_test.sh
==============================================================================
--- projects/zfsd/head/cddl/sbin/zfsd/tests/zfsd_test.sh	Fri May 23 23:13:17 2014	(r266601)
+++ projects/zfsd/head/cddl/sbin/zfsd/tests/zfsd_test.sh	Fri May 23 23:13:34 2014	(r266602)
@@ -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()

Modified: projects/zfsd/head/cddl/sbin/zfsd/tests/zfsd_unittest.cc
==============================================================================
--- projects/zfsd/head/cddl/sbin/zfsd/tests/zfsd_unittest.cc	Fri May 23 23:13:17 2014	(r266601)
+++ projects/zfsd/head/cddl/sbin/zfsd/tests/zfsd_unittest.cc	Fri May 23 23:13:34 2014	(r266602)
@@ -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());
 }
 
 /*

Modified: projects/zfsd/head/cddl/sbin/zfsd/vdev.cc
==============================================================================
--- projects/zfsd/head/cddl/sbin/zfsd/vdev.cc	Fri May 23 23:13:17 2014	(r266601)
+++ projects/zfsd/head/cddl/sbin/zfsd/vdev.cc	Fri May 23 23:13:34 2014	(r266602)
@@ -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>

Modified: projects/zfsd/head/cddl/sbin/zfsd/zfsd.cc
==============================================================================
--- projects/zfsd/head/cddl/sbin/zfsd/zfsd.cc	Fri May 23 23:13:17 2014	(r266601)
+++ projects/zfsd/head/cddl/sbin/zfsd/zfsd.cc	Fri May 23 23:13:34 2014	(r266602)
@@ -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 --------------------------------------------

Modified: projects/zfsd/head/cddl/sbin/zfsd/zfsd.h
==============================================================================
--- projects/zfsd/head/cddl/sbin/zfsd/zfsd.h	Fri May 23 23:13:17 2014	(r266601)
+++ projects/zfsd/head/cddl/sbin/zfsd/zfsd.h	Fri May 23 23:13:34 2014	(r266602)
@@ -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"
  */

Modified: projects/zfsd/head/cddl/sbin/zfsd/zfsd_event.cc
==============================================================================
--- projects/zfsd/head/cddl/sbin/zfsd/zfsd_event.cc	Fri May 23 23:13:17 2014	(r266601)
+++ projects/zfsd/head/cddl/sbin/zfsd/zfsd_event.cc	Fri May 23 23:13:34 2014	(r266602)
@@ -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 
 /*--------------------------------- 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));
 }

Modified: projects/zfsd/head/cddl/sbin/zfsd/zfsd_event.h
==============================================================================
--- projects/zfsd/head/cddl/sbin/zfsd/zfsd_event.h	Fri May 23 23:13:17 2014	(r266601)
+++ projects/zfsd/head/cddl/sbin/zfsd/zfsd_event.h	Fri May 23 23:13:34 2014	(r266602)
@@ -66,7 +66,7 @@ class DevfsEvent : public DevCtl::DevfsE
 {
 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;
 

Modified: projects/zfsd/head/etc/mtree/BSD.tests.dist
==============================================================================
--- projects/zfsd/head/etc/mtree/BSD.tests.dist	Fri May 23 23:13:17 2014	(r266601)
+++ projects/zfsd/head/etc/mtree/BSD.tests.dist	Fri May 23 23:13:34 2014	(r266602)
@@ -54,6 +54,8 @@
             lib
             ..
             sbin
+                zfsd
+                ..
             ..
             usr.bin
             ..

Modified: projects/zfsd/head/lib/libdevctl/Makefile
==============================================================================
--- projects/zfsd/head/lib/libdevctl/Makefile	Fri May 23 23:13:17 2014	(r266601)
+++ projects/zfsd/head/lib/libdevctl/Makefile	Fri May 23 23:13:34 2014	(r266602)
@@ -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
 

Modified: projects/zfsd/head/lib/libdevctl/consumer.cc
==============================================================================
--- projects/zfsd/head/lib/libdevctl/consumer.cc	Fri May 23 23:13:17 2014	(r266601)
+++ projects/zfsd/head/lib/libdevctl/consumer.cc	Fri May 23 23:13:34 2014	(r266602)
@@ -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 *d
 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 *eventBu
 
 /* 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 *eve
 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

Modified: projects/zfsd/head/lib/libdevctl/consumer.h
==============================================================================
--- projects/zfsd/head/lib/libdevctl/consumer.h	Fri May 23 23:13:17 2014	(r266601)
+++ projects/zfsd/head/lib/libdevctl/consumer.h	Fri May 23 23:13:34 2014	(r266602)
@@ -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[];
 
 	/**

Modified: projects/zfsd/head/lib/libdevctl/event.cc
==============================================================================
--- projects/zfsd/head/lib/libdevctl/event.cc	Fri May 23 23:13:17 2014	(r266601)
+++ projects/zfsd/head/lib/libdevctl/event.cc	Fri May 23 23:13:34 2014	(r266602)
@@ -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_typeTabl
 
 //- 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 
 /*--------------------------------- 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));
 }

Modified: projects/zfsd/head/lib/libdevctl/event.h
==============================================================================
--- projects/zfsd/head/lib/libdevctl/event.h	Fri May 23 23:13:17 2014	(r266601)
+++ projects/zfsd/head/lib/libdevctl/event.h	Fri May 23 23:13:34 2014	(r266602)
@@ -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);
@@ -190,6 +190,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.
 	 */
 	const NVPairMap &GetMap()			 const;
@@ -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;
 

Modified: projects/zfsd/head/lib/libdevctl/event_factory.cc
==============================================================================
--- projects/zfsd/head/lib/libdevctl/event_factory.cc	Fri May 23 23:13:17 2014	(r266601)
+++ projects/zfsd/head/lib/libdevctl/event_factory.cc	Fri May 23 23:13:34 2014	(r266602)
@@ -88,8 +88,10 @@ EventFactory::Build(Event::Type type, NV
 	if (foundMethod != m_registry.end())
 		buildMethod = foundMethod->second;
 	
-	if (buildMethod == NULL)
+	if (buildMethod == NULL) {
+		delete &nvpairs;
 		return (NULL);
+	}
 
 	return (buildMethod(type, nvpairs, eventString));
 }

Modified: projects/zfsd/head/lib/libdevctl/exception.cc
==============================================================================
--- projects/zfsd/head/lib/libdevctl/exception.cc	Fri May 23 23:13:17 2014	(r266601)
+++ projects/zfsd/head/lib/libdevctl/exception.cc	Fri May 23 23:13:34 2014	(r266602)
@@ -37,6 +37,8 @@
 
 #include <syslog.h>
 
+#include <cstdio>
+#include <cstdarg>
 #include <sstream>
 #include <string>
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201405232313.s4NNDZlu010781>