zeek/src/input/ReaderBackend.h
Robin Sommer 87e10b5f97 Further threading and API restructuring for logging and input
frameworks.

There were a number of cases that weren't thread-safe. In particular,
we don't use std::string anymore for anything that's passed between
threads (but instead plain old const char*, with manual memmory
managmenet).

This is still a check-point commit, I'll do more testing.
2012-07-19 22:28:30 -07:00

338 lines
9.6 KiB
C++

// See the file "COPYING" in the main distribution directory for copyright.
#ifndef INPUT_READERBACKEND_H
#define INPUT_READERBACKEND_H
#include "BroString.h"
#include "threading/SerialTypes.h"
#include "threading/MsgThread.h"
namespace input {
/**
* The modes a reader can be in.
*/
enum ReaderMode {
/**
* Manual refresh reader mode. The reader will read the file once,
* and send all read data back to the manager. After that, no automatic
* refresh should happen. Manual refreshes can be triggered from the
* scripting layer using force_update.
*/
MODE_MANUAL,
/**
* Automatic rereading mode. The reader should monitor the
* data source for changes continually. When the data source changes,
* either the whole file has to be resent using the SendEntry/EndCurrentSend functions.
*/
MODE_REREAD,
/**
* Streaming reading mode. The reader should monitor the data source
* for new appended data. When new data is appended is has to be sent
* using the Put api functions.
*/
MODE_STREAM,
/** Internal dummy mode for initialization. */
MODE_NONE
};
class ReaderFrontend;
/**
* Base class for reader implementation. When the input:Manager creates a new
* input stream, it instantiates a ReaderFrontend. That then in turn creates
* a ReaderBackend of the right type. The frontend then forwards messages
* over the backend as its methods are called.
*
* All methods must be called only from the corresponding child thread (the
* constructor is the one exception.)
*/
class ReaderBackend : public threading::MsgThread {
public:
/**
* Constructor.
*
* @param frontend The frontend reader that created this backend. The
* *only* purpose of this value is to be passed back via messages as
* an argument to callbacks. One must not otherwise access the
* frontend, it's running in a different thread.
*/
ReaderBackend(ReaderFrontend* frontend);
/**
* Destructor.
*/
virtual ~ReaderBackend();
/**
* A struct passing information to the reader at initialization time.
*/
struct ReaderInfo
{
// Structure takes ownership of the strings.
typedef std::map<const char*, const char*> config_map;
/**
* A string left to the interpretation of the reader
* implementation; it corresponds to the value configured on
* the script-level for the logging filter.
*
* Structure takes ownership of the string.
*/
const char* source;
/**
* A map of key/value pairs corresponding to the relevant
* filter's "config" table.
*/
config_map config;
/**
* The opening mode for the input source.
*/
ReaderMode mode;
ReaderInfo()
{
source = 0;
mode = MODE_NONE;
}
ReaderInfo(const ReaderInfo& other)
{
source = other.source ? copy_string(other.source) : 0;
mode = other.mode;
for ( config_map::const_iterator i = other.config.begin(); i != other.config.end(); i++ )
config.insert(std::make_pair(copy_string(i->first), copy_string(i->second)));
}
~ReaderInfo()
{
delete [] source;
for ( config_map::iterator i = config.begin(); i != config.end(); i++ )
{
delete [] i->first;
delete [] i->second;
}
}
private:
const ReaderInfo& operator=(const ReaderInfo& other); // Disable.
};
/**
* One-time initialization of the reader to define the input source.
*
* @param @param info Meta information for the writer.
*
* @param num_fields Number of fields contained in \a fields.
*
* @param fields The types and names of the fields to be retrieved
* from the input source.
*
* @param config A string map containing additional configuration options
* for the reader.
*
* @return False if an error occured.
*/
bool Init(int num_fields, const threading::Field* const* fields);
/**
* Force trigger an update of the input stream. The action that will
* be taken depends on the current read mode and the individual input
* backend.
*
* An backend can choose to ignore this.
*
* @return False if an error occured.
*/
bool Update();
/**
* Disables the frontend that has instantiated this backend. Once
* disabled, the frontend will not send any further message over.
*/
void DisableFrontend();
/**
* Returns the log fields as passed into the constructor.
*/
const threading::Field* const * Fields() const { return fields; }
/**
* Returns the additional reader information into the constructor.
*/
const ReaderInfo& Info() const { return *info; }
/**
* Returns the number of log fields as passed into the constructor.
*/
int NumFields() const { return num_fields; }
// Overridden from MsgThread.
virtual bool OnHeartbeat(double network_time, double current_time);
virtual bool OnFinish(double network_time);
protected:
// Methods that have to be overwritten by the individual readers
/**
* Reader-specific intialization method. Note that data may only be
* read from the input source after the Init() function has been
* called.
*
* A reader implementation must override this method. If it returns
* false, it will be assumed that a fatal error has occured that
* prevents the reader from further operation; it will then be
* disabled and eventually deleted. When returning false, an
* implementation should also call Error() to indicate what happened.
*
* Arguments are the same as Init().
*
* Note that derived classes don't need to store the values passed in
* here if other methods need them to; the \a ReaderBackend class
* provides accessor methods to get them later, and they are passed
* in here only for convinience.
*/
virtual bool DoInit(const ReaderInfo& info, int arg_num_fields, const threading::Field* const* fields) = 0;
/**
* Reader-specific method implementing input finalization at
* termination.
*
* A reader implementation must override this method but it can just
* ignore calls if an input source can't actually be closed.
*
* After the method is called, the writer will be deleted. If an
* error occurs during shutdown, an implementation should also call
* Error() to indicate what happened.
*/
virtual void DoClose() = 0;
/**
* Reader-specific method implementing the forced update trigger.
*
* A reader implementation must override this method but it can just
* ignore calls if a forced update does not fit the input source or
* the current input reading mode.
*
* If it returns false, it will be assumed that a fatal error has
* occured that prevents the reader from further operation; it will
* then be disabled and eventually deleted. When returning false, an
* implementation should also call Error to indicate what happened.
*/
virtual bool DoUpdate() = 0;
/**
* Triggered by regular heartbeat messages from the main thread.
*/
virtual bool DoHeartbeat(double network_time, double current_time) = 0;
/**
* Method allowing a reader to send a specified Bro event. Vals must
* match the values expected by the bro event.
*
* @param name name of the bro event to send
*
* @param num_vals number of entries in \a vals
*
* @param vals the values to be given to the event
*/
void SendEvent(const char* name, const int num_vals, threading::Value* *vals);
// Content-sending-functions (simple mode). Include table-specific
// functionality that simply is not used if we have no table.
/**
* Method allowing a reader to send a list of values read from a
* specific stream back to the manager in simple mode.
*
* If the stream is a table stream, the values are inserted into the
* table; if it is an event stream, the event is raised.
*
* @param val Array of threading::Values expected by the stream. The
* array must have exactly NumEntries() elements.
*/
void Put(threading::Value** val);
/**
* Method allowing a reader to delete a specific value from a Bro
* table.
*
* If the receiving stream is an event stream, only a removed event
* is raised.
*
* @param val Array of threading::Values expected by the stream. The
* array must have exactly NumEntries() elements.
*/
void Delete(threading::Value** val);
/**
* Method allowing a reader to clear a Bro table.
*
* If the receiving stream is an event stream, this is ignored.
*
*/
void Clear();
// Content-sending-functions (tracking mode): Only changed lines are propagated.
/**
* Method allowing a reader to send a list of values read from
* specific stream back to the manager in tracking mode.
*
* If the stream is a table stream, the values are inserted into the
* table; if it is an event stream, the event is raised.
*
* @param val Array of threading::Values expected by the stream. The
* array must have exactly NumEntries() elements.
*/
void SendEntry(threading::Value** vals);
/**
* Method telling the manager, that the current list of entries sent
* by SendEntry is finished.
*
* For table streams, all entries that were not updated since the
* last EndCurrentSend will be deleted, because they are no longer
* present in the input source
*/
void EndCurrentSend();
/**
* Convert a string into a TransportProto. This is just a utility
* function for Readers.
*
* @param proto the transport protocol
*/
TransportProto StringToProto(const string &proto);
/**
* Convert a string into a Value::addr_t. This is just a utility
* function for Readers.
*
* @param addr containing an ipv4 or ipv6 address
*/
threading::Value::addr_t StringToAddr(const string &addr);
private:
// Frontend that instantiated us. This object must not be accessed
// from this class, it's running in a different thread!
ReaderFrontend* frontend;
ReaderInfo* info;
unsigned int num_fields;
const threading::Field* const * fields; // raw mapping
bool disabled;
};
}
#endif /* INPUT_READERBACKEND_H */