Index: projects/zfsd/head/lib/libdevdctl/reader.cc =================================================================== --- projects/zfsd/head/lib/libdevdctl/reader.cc (revision 300526) +++ projects/zfsd/head/lib/libdevdctl/reader.cc (nonexistent) @@ -1,99 +0,0 @@ -/*- - * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * Authors: Alan Somers (Spectra Logic Corporation) - */ - -/** - * \file reader.cc - */ - -#include -#include - -#include -#include -#include -#include - -#include - -#include "reader.h" - -__FBSDID("$FreeBSD$"); - -/*============================ Namespace Control =============================*/ -namespace DevdCtl -{ - -//- FDReader Public Methods --------------------------------------------------- -FDReader::FDReader(int fd) - : m_fd(fd) -{ -} - -ssize_t -FDReader::read(char* buf, size_t count) -{ - return (::read(m_fd, buf, count)); -} - -ssize_t -FDReader::in_avail() const -{ - int bytes; - if (ioctl(m_fd, FIONREAD, &bytes)) { - syslog(LOG_ERR, "ioctl FIONREAD: %s", strerror(errno)); - return (-1); - } - return (bytes); -} - -//- IstreamReader Inline Public Methods ---------------------------------------- -IstreamReader::IstreamReader(std::istream* stream) - : m_stream(stream) -{ -} - -ssize_t -IstreamReader::read(char* buf, size_t count) -{ - m_stream->read(buf, count); - if (m_stream->fail()) - return (-1); - return (m_stream->gcount()); -} - -ssize_t -IstreamReader::in_avail() const -{ - return (m_stream->rdbuf()->in_avail()); -} - -} // namespace DevdCtl Index: projects/zfsd/head/lib/libdevdctl/event_buffer.cc =================================================================== --- projects/zfsd/head/lib/libdevdctl/event_buffer.cc (revision 300526) +++ projects/zfsd/head/lib/libdevdctl/event_buffer.cc (nonexistent) @@ -1,216 +0,0 @@ -/*- - * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * Authors: Justin T. Gibbs (Spectra Logic Corporation) - */ - -/** - * \file event_buffer.cc - */ - -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include "event_buffer.h" -#include "exception.h" -#include "reader.h" - -__FBSDID("$FreeBSD$"); - -/*============================ Namespace Control =============================*/ -using std::string; -using std::stringstream; -namespace DevdCtl -{ - -/*============================= Class Definitions ============================*/ -/*-------------------------------- EventBuffer -------------------------------*/ -//- EventBuffer Static Data ---------------------------------------------------- -/** - * NOTIFY, NOMATCH, ATTACH, DETACH. See DevdCtlEvent::Type. - */ -const char EventBuffer::s_eventStartTokens[] = "!?+-"; - -/** - * Events are terminated by a newline. - */ -const char EventBuffer::s_eventEndTokens[] = "\n"; - -/** - * Key=Value pairs are terminated by whitespace. - */ -const char EventBuffer::s_keyPairSepTokens[] = " \t\n"; - -//- EventBuffer Public Methods ------------------------------------------------- -EventBuffer::EventBuffer(Reader& reader) - : m_reader(reader), - m_validLen(0), - m_parsedLen(0), - m_nextEventOffset(0), - m_synchronized(true) -{ -} - -bool -EventBuffer::ExtractEvent(string &eventString) -{ - stringstream tsField; - timeval now; - - gettimeofday(&now, NULL); - tsField << " timestamp=" << now.tv_sec; - - while (UnParsed() > 0 || Fill()) { - - /* - * If the valid data in the buffer isn't enough to hold - * a full event, try reading more. - */ - if (NextEventMaxLen() < MIN_EVENT_SIZE) { - m_parsedLen += UnParsed(); - continue; - } - - char *nextEvent(m_buf + m_nextEventOffset); - bool truncated(true); - size_t eventLen(strcspn(nextEvent, s_eventEndTokens)); - - if (!m_synchronized) { - /* Discard data until an end token is read. */ - if (nextEvent[eventLen] != '\0') - m_synchronized = true; - m_nextEventOffset += eventLen; - m_parsedLen = m_nextEventOffset; - continue; - } else if (nextEvent[eventLen] == '\0') { - - m_parsedLen += eventLen; - if (m_parsedLen < MAX_EVENT_SIZE) { - /* - * Ran out of buffer before hitting - * a full event. Fill() and try again. - */ - continue; - } - syslog(LOG_WARNING, "Overran event buffer\n\tm_nextEventOffset" - "=%zd\n\tm_parsedLen=%zd\n\tm_validLen=%zd", - m_nextEventOffset, m_parsedLen, m_validLen); - } else { - /* - * Include the normal terminator in the extracted - * event data. - */ - eventLen += 1; - truncated = false; - } - - m_nextEventOffset += eventLen; - m_parsedLen = m_nextEventOffset; - eventString.assign(nextEvent, eventLen); - - if (truncated) { - size_t fieldEnd; - - /* Break cleanly at the end of a key<=>value pair. */ - fieldEnd = eventString.find_last_of(s_keyPairSepTokens); - if (fieldEnd != string::npos) - eventString.erase(fieldEnd); - eventString += '\n'; - - m_synchronized = false; - syslog(LOG_WARNING, - "Truncated %zd characters from event.", - eventLen - fieldEnd); - } - - /* - * Add a timestamp as the final field of the event if it is - * not already present. - */ - if (eventString.find("timestamp=") == string::npos) { - size_t eventEnd(eventString.find_last_not_of('\n') + 1); - - eventString.insert(eventEnd, tsField.str()); - } - - return (true); - } - return (false); -} - -//- EventBuffer Private Methods ------------------------------------------------ -bool -EventBuffer::Fill() -{ - ssize_t avail; - ssize_t consumed(0); - - /* Compact the buffer. */ - if (m_nextEventOffset != 0) { - memmove(m_buf, m_buf + m_nextEventOffset, - m_validLen - m_nextEventOffset); - m_validLen -= m_nextEventOffset; - m_parsedLen -= m_nextEventOffset; - m_nextEventOffset = 0; - } - - /* Fill any empty space. */ - avail = m_reader.in_avail(); - if (avail > 0) { - size_t want; - - want = std::min((size_t)avail, MAX_READ_SIZE - m_validLen); - consumed = m_reader.read(m_buf + m_validLen, want); - if (consumed == -1) { - if (errno == EINTR) - return (false); - else - err(1, "EventBuffer::Fill(): Read failed"); - } - } else if (avail == -1) { - throw Exception("EventBuffer::Fill(): Reader disconnected"); - } - - m_validLen += consumed; - /* Guarantee our buffer is always NUL terminated. */ - m_buf[m_validLen] = '\0'; - - return (consumed > 0); -} - -} // namespace DevdCtl Index: projects/zfsd/head/lib/libdevdctl/event_buffer.h =================================================================== --- projects/zfsd/head/lib/libdevdctl/event_buffer.h (revision 300526) +++ projects/zfsd/head/lib/libdevdctl/event_buffer.h (nonexistent) @@ -1,188 +0,0 @@ -/*- - * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * Authors: Justin T. Gibbs (Spectra Logic Corporation) - * - * $FreeBSD$ - */ - -/** - * \file devdctl_event_buffer.h - */ -#ifndef _DEVDCTL_EVENT_BUFFER_H_ -#define _DEVDCTL_EVENT_BUFFER_H_ - -/*============================ Namespace Control =============================*/ -namespace DevdCtl -{ - -/*=========================== Forward Declarations ===========================*/ -class Reader; - -/*============================= Class Definitions ============================*/ -/*-------------------------------- EventBuffer -------------------------------*/ -/** - * \brief Class buffering event data from Devd or a similar source and - * splitting it into individual event strings. - * - * Users of this class initialize it with a Reader associated with the unix - * domain socket connection with devd or a compatible source. The lifetime of - * an EventBuffer instance should match that of the Reader passed to it. This - * is required as data from partially received events is retained in the - * EventBuffer in order to allow reconstruction of these events across multiple - * reads of the stream. - * - * Once the program determines that the Reader is ready for reading, the - * EventBuffer::ExtractEvent() should be called in a loop until the method - * returns false. - */ -class EventBuffer -{ -public: - /** - * Constructor - * - * \param reader The data source on which to buffer/parse event data. - */ - EventBuffer(Reader& reader); - - /** - * Pull a single event string out of the event buffer. - * - * \param eventString The extracted event data (if available). - * - * \return true if event data is available and eventString has - * been populated. Otherwise false. - */ - bool ExtractEvent(std::string &eventString); - -private: - enum { - /** - * Size of an empty event (start and end token with - * no data. The EventBuffer parsing needs at least - * this much data in the buffer for safe event extraction. - */ - MIN_EVENT_SIZE = 2, - - /* - * The maximum event size supported by ZFSD. - * Events larger than this size (minus 1) are - * truncated at the end of the last fully received - * key/value pair. - */ - MAX_EVENT_SIZE = 8192, - - /** - * The maximum amount of buffer data to read at - * a single time from the Devd file descriptor. - */ - MAX_READ_SIZE = MAX_EVENT_SIZE, - - /** - * The size of EventBuffer's buffer of Devd event data. - * This is one larger than the maximum supported event - * size, which alows us to always include a terminating - * NUL without overwriting any received data. - */ - EVENT_BUFSIZE = MAX_EVENT_SIZE + /*NUL*/1 - }; - - /** The amount of data in m_buf we have yet to look at. */ - size_t UnParsed() const; - - /** The amount of data in m_buf available for the next event. */ - size_t NextEventMaxLen() const; - - /** Fill the event buffer with event data from Devd. */ - bool Fill(); - - /** Characters we treat as beginning an event string. */ - static const char s_eventStartTokens[]; - - /** Characters we treat as ending an event string. */ - static const char s_eventEndTokens[]; - - /** Characters found between successive "key=value" strings. */ - static const char s_keyPairSepTokens[]; - - /** Temporary space for event data during our parsing. Laid out like - * this: - * <---------------------------------------------------------> - * | | | | | - * m_buf---| | | | | - * m_nextEventOffset-- | | | - * m_parsedLen------------- | | - * m_validLen-------------------------- | - * EVENT_BUFSIZE------------------------------------------------------ - * - * Data before m_nextEventOffset has already been processed. - * - * Data between m_nextEvenOffset and m_parsedLen has been parsed, but - * not processed as a single event. - * - * Data between m_parsedLen and m_validLen has been read from the - * source, but not yet parsed. - * - * Between m_validLen and EVENT_BUFSIZE is empty space. - * - * */ - char m_buf[EVENT_BUFSIZE]; - - /** Reference to the reader linked to devd's domain socket. */ - Reader& m_reader; - - /** Offset within m_buf to the beginning of free space. */ - size_t m_validLen; - - /** Offset within m_buf to the beginning of data not yet parsed */ - size_t m_parsedLen; - - /** Offset within m_buf to the start token of the next event. */ - size_t m_nextEventOffset; - - /** The EventBuffer is aligned and tracking event records. */ - bool m_synchronized; -}; - -//- EventBuffer Inline Private Methods ----------------------------------------- -inline size_t -EventBuffer::UnParsed() const -{ - return (m_validLen - m_parsedLen); -} - -inline size_t -EventBuffer::NextEventMaxLen() const -{ - return (m_validLen - m_nextEventOffset); -} - -} // namespace DevdCtl -#endif /* _DEVDCTL_EVENT_BUFFER_H_ */ Index: projects/zfsd/head/lib/libdevdctl/reader.h =================================================================== --- projects/zfsd/head/lib/libdevdctl/reader.h (revision 300526) +++ projects/zfsd/head/lib/libdevdctl/reader.h (nonexistent) @@ -1,136 +0,0 @@ -/*- - * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * Authors: Justin T. Gibbs (Spectra Logic Corporation) - * - * $FreeBSD$ - */ - -/** - * \file devdctl_reader.h - */ -#ifndef _DEVDCTL_READER_H_ -#define _DEVDCTL_READER_H_ - -/*=========================== Forward Declarations ===========================*/ - -/*============================ Namespace Control =============================*/ -namespace DevdCtl -{ - -/*============================= Class Definitions ============================*/ - -/*-------------------------------- Reader -------------------------------*/ -/** - * \brief A class that presents a common interface to both file descriptors - * and istreams. - * - * Standard C++ provides no way to create an iostream from a file descriptor or - * a FILE. The GNU, Apache, HPUX, and Solaris C++ libraries all provide - * non-standard ways to construct such a stream using similar semantics, but - * FreeBSD's C++ library does not. This class supports only the functionality - * needed by ZFSD; it does not implement the iostream API. - */ -class Reader -{ -public: - /** - * \brief Return the number of bytes immediately available for reading - */ - virtual ssize_t in_avail() const = 0; - - /** - * \brief Reads up to count bytes - * - * Whether this call blocks depends on the underlying input source. - * On error, -1 is returned, and errno will be set by the underlying - * source. - * - * \param buf Destination for the data - * \param count Maximum amount of data to read - * \returns Amount of data that was actually read - */ - virtual ssize_t read(char* buf, size_t count) = 0; - - virtual ~Reader() = 0; -}; - -inline Reader::~Reader() {} - - -/*--------------------------------- FDReader ---------------------------------*/ -/** - * \brief Specialization of Reader that uses a file descriptor - */ -class FDReader : public Reader -{ -public: - /** - * \brief Constructor - * - * \param fd An open file descriptor. It will not be garbage - * collected by the destructor. - */ - FDReader(int fd); - - virtual ssize_t in_avail() const; - - virtual ssize_t read(char* buf, size_t count); - -protected: - /** Copy of the underlying file descriptor */ - int m_fd; -}; - -/*-------------------------------- IstreamReader------------------------------*/ -/** - * \brief Specialization of Reader that uses a std::istream - */ -class IstreamReader : public Reader -{ -public: - /** - * Constructor - * - * \param stream Pointer to an open istream. It will not be - * garbage collected by the destructor. - */ - IstreamReader(std::istream* stream); - - virtual ssize_t in_avail() const; - - virtual ssize_t read(char* buf, size_t count); - -protected: - /** Copy of the underlying stream */ - std::istream *m_stream; -}; - -} // namespace DevdCtl -#endif /* _DEVDCTL_READER_H_ */