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.
This commit is contained in:
Robin Sommer 2012-07-18 12:47:13 -07:00
parent 490859cfef
commit 87e10b5f97
31 changed files with 692 additions and 381 deletions

View file

@ -6,6 +6,7 @@
#include "../EventHandler.h"
#include "../NetVar.h"
#include "../Net.h"
#include "../Type.h"
#include "threading/Manager.h"
#include "threading/SerialTypes.h"
@ -75,7 +76,7 @@ struct Manager::WriterInfo {
double interval;
Func* postprocessor;
WriterFrontend* writer;
WriterBackend::WriterInfo info;
WriterBackend::WriterInfo* info;
};
struct Manager::Stream {
@ -118,6 +119,7 @@ Manager::Stream::~Stream()
Unref(winfo->type);
delete winfo->writer;
delete winfo->info;
delete winfo;
}
@ -193,7 +195,6 @@ WriterBackend* Manager::CreateBackend(WriterFrontend* frontend, bro_int_t type)
assert(ld->factory);
frontend->ty_name = ld->name;
WriterBackend* backend = (*ld->factory)(frontend);
assert(backend);
@ -476,18 +477,17 @@ bool Manager::TraverseRecord(Stream* stream, Filter* filter, RecordType* rt,
return false;
}
threading::Field* field = new threading::Field();
field->name = new_path;
field->type = t->Tag();
field->optional = rt->FieldDecl(i)->FindAttr(ATTR_OPTIONAL);
TypeTag st = TYPE_VOID;
if ( field->type == TYPE_TABLE )
field->subtype = t->AsSetType()->Indices()->PureType()->Tag();
if ( t->Tag() == TYPE_TABLE )
st = t->AsSetType()->Indices()->PureType()->Tag();
else if ( field->type == TYPE_VECTOR )
field->subtype = t->AsVectorType()->YieldType()->Tag();
else if ( t->Tag() == TYPE_VECTOR )
st = t->AsVectorType()->YieldType()->Tag();
filter->fields[filter->num_fields - 1] = field;
bool optional = rt->FieldDecl(i)->FindAttr(ATTR_OPTIONAL);
filter->fields[filter->num_fields - 1] = new threading::Field(new_path.c_str(), 0, t->Tag(), st, optional);
}
return true;
@ -594,7 +594,7 @@ bool Manager::AddFilter(EnumVal* id, RecordVal* fval)
{
threading::Field* field = filter->fields[i];
DBG_LOG(DBG_LOGGING, " field %10s: %s",
field->name.c_str(), type_name(field->type));
field->name, type_name(field->type));
}
#endif
@ -769,9 +769,9 @@ bool Manager::Write(EnumVal* id, RecordVal* columns)
for ( int j = 0; j < filter->num_fields; ++j )
arg_fields[j] = new threading::Field(*filter->fields[j]);
WriterBackend::WriterInfo info;
info.path = path;
info.network_time = network_time;
WriterBackend::WriterInfo* info = new WriterBackend::WriterInfo;
info->path = copy_string(path.c_str());
info->network_time = network_time;
HashKey* k;
IterCookie* c = filter->config->AsTable()->InitForIteration();
@ -782,7 +782,7 @@ bool Manager::Write(EnumVal* id, RecordVal* columns)
ListVal* index = filter->config->RecoverIndex(k);
string key = index->Index(0)->AsString()->CheckString();
string value = v->Value()->AsString()->CheckString();
info.config.insert(std::make_pair(key, value));
info->config.insert(std::make_pair(copy_string(key.c_str()), copy_string(value.c_str())));
Unref(index);
delete k;
}
@ -844,11 +844,16 @@ threading::Value* Manager::ValToLogVal(Val* val, BroType* ty)
val->Type()->AsEnumType()->Lookup(val->InternalInt());
if ( s )
lval->val.string_val = new string(s);
{
lval->val.string_val.data = copy_string(s);
lval->val.string_val.length = strlen(s);
}
else
{
val->Type()->Error("enum type does not contain value", val);
lval->val.string_val = new string();
lval->val.string_val.data = copy_string("");
lval->val.string_val.length = 0;
}
break;
}
@ -880,15 +885,20 @@ threading::Value* Manager::ValToLogVal(Val* val, BroType* ty)
case TYPE_STRING:
{
const BroString* s = val->AsString();
lval->val.string_val =
new string((const char*) s->Bytes(), s->Len());
char* buf = new char[s->Len()];
memcpy(buf, s->Bytes(), s->Len());
lval->val.string_val.data = buf;
lval->val.string_val.length = s->Len();
break;
}
case TYPE_FILE:
{
const BroFile* f = val->AsFile();
lval->val.string_val = new string(f->Name());
string s = f->Name();
lval->val.string_val.data = copy_string(s.c_str());
lval->val.string_val.length = s.size();
break;
}
@ -897,7 +907,9 @@ threading::Value* Manager::ValToLogVal(Val* val, BroType* ty)
ODesc d;
const Func* f = val->AsFunc();
f->Describe(&d);
lval->val.string_val = new string(d.Description());
const char* s = d.Description();
lval->val.string_val.data = copy_string(s);
lval->val.string_val.length = strlen(s);
break;
}
@ -977,7 +989,7 @@ threading::Value** Manager::RecordToFilterVals(Stream* stream, Filter* filter,
return vals;
}
WriterFrontend* Manager::CreateWriter(EnumVal* id, EnumVal* writer, const WriterBackend::WriterInfo& info,
WriterFrontend* Manager::CreateWriter(EnumVal* id, EnumVal* writer, WriterBackend::WriterInfo* info,
int num_fields, const threading::Field* const* fields, bool local, bool remote)
{
Stream* stream = FindStream(id);
@ -987,7 +999,7 @@ WriterFrontend* Manager::CreateWriter(EnumVal* id, EnumVal* writer, const Writer
return 0;
Stream::WriterMap::iterator w =
stream->writers.find(Stream::WriterPathPair(writer->AsEnum(), info.path));
stream->writers.find(Stream::WriterPathPair(writer->AsEnum(), info->path));
if ( w != stream->writers.end() )
// If we already have a writer for this. That's fine, we just
@ -1013,7 +1025,7 @@ WriterFrontend* Manager::CreateWriter(EnumVal* id, EnumVal* writer, const Writer
{
Filter* f = *it;
if ( f->writer->AsEnum() == writer->AsEnum() &&
f->path == info.path )
f->path == info->path )
{
found_filter_match = true;
winfo->interval = f->interval;
@ -1030,7 +1042,7 @@ WriterFrontend* Manager::CreateWriter(EnumVal* id, EnumVal* writer, const Writer
}
stream->writers.insert(
Stream::WriterMap::value_type(Stream::WriterPathPair(writer->AsEnum(), info.path),
Stream::WriterMap::value_type(Stream::WriterPathPair(writer->AsEnum(), info->path),
winfo));
// Still need to set the WriterInfo's rotation parameters, which we
@ -1038,11 +1050,11 @@ WriterFrontend* Manager::CreateWriter(EnumVal* id, EnumVal* writer, const Writer
const char* base_time = log_rotate_base_time ?
log_rotate_base_time->AsString()->CheckString() : 0;
winfo->info.rotation_interval = winfo->interval;
winfo->info.rotation_base = parse_rotate_base_time(base_time);
winfo->info->rotation_interval = winfo->interval;
winfo->info->rotation_base = parse_rotate_base_time(base_time);
winfo->writer = new WriterFrontend(id, writer, local, remote);
winfo->writer->Init(winfo->info, num_fields, fields);
winfo->writer = new WriterFrontend(*winfo->info, id, writer, local, remote);
winfo->writer->Init(num_fields, fields);
InstallRotationTimer(winfo);
@ -1124,7 +1136,7 @@ void Manager::SendAllWritersTo(RemoteSerializer::PeerID peer)
EnumVal writer_val(i->first.first, BifType::Enum::Log::Writer);
remote_serializer->SendLogCreateWriter(peer, (*s)->id,
&writer_val,
i->second->info,
*i->second->info,
writer->NumFields(),
writer->Fields());
}
@ -1260,14 +1272,14 @@ void Manager::InstallRotationTimer(WriterInfo* winfo)
timer_mgr->Add(winfo->rotation_timer);
DBG_LOG(DBG_LOGGING, "Scheduled rotation timer for %s to %.6f",
winfo->writer->Name().c_str(), winfo->rotation_timer->Time());
winfo->writer->Name(), winfo->rotation_timer->Time());
}
}
void Manager::Rotate(WriterInfo* winfo)
{
DBG_LOG(DBG_LOGGING, "Rotating %s at %.6f",
winfo->writer->Name().c_str(), network_time);
winfo->writer->Name(), network_time);
// Build a temporary path for the writer to move the file to.
struct tm tm;
@ -1278,15 +1290,14 @@ void Manager::Rotate(WriterInfo* winfo)
localtime_r(&teatime, &tm);
strftime(buf, sizeof(buf), date_fmt, &tm);
string tmp = string(fmt("%s-%s", winfo->writer->Info().path.c_str(), buf));
// Trigger the rotation.
const char* tmp = fmt("%s-%s", winfo->writer->Info().path, buf);
winfo->writer->Rotate(tmp, winfo->open_time, network_time, terminating);
++rotations_pending;
}
bool Manager::FinishedRotation(WriterFrontend* writer, string new_name, string old_name,
bool Manager::FinishedRotation(WriterFrontend* writer, const char* new_name, const char* old_name,
double open, double close, bool terminating)
{
--rotations_pending;
@ -1296,7 +1307,7 @@ bool Manager::FinishedRotation(WriterFrontend* writer, string new_name, string o
return true;
DBG_LOG(DBG_LOGGING, "Finished rotating %s at %.6f, new name %s",
writer->Name().c_str(), network_time, new_name.c_str());
writer->Name(), network_time, new_name);
WriterInfo* winfo = FindWriter(writer);
if ( ! winfo )
@ -1305,8 +1316,8 @@ bool Manager::FinishedRotation(WriterFrontend* writer, string new_name, string o
// Create the RotationInfo record.
RecordVal* info = new RecordVal(BifType::Record::Log::RotationInfo);
info->Assign(0, winfo->type->Ref());
info->Assign(1, new StringVal(new_name.c_str()));
info->Assign(2, new StringVal(winfo->writer->Info().path.c_str()));
info->Assign(1, new StringVal(new_name));
info->Assign(2, new StringVal(winfo->writer->Info().path));
info->Assign(3, new Val(open, TYPE_TIME));
info->Assign(4, new Val(close, TYPE_TIME));
info->Assign(5, new Val(terminating, TYPE_BOOL));

View file

@ -162,8 +162,8 @@ protected:
//// Function also used by the RemoteSerializer.
// Takes ownership of fields.
WriterFrontend* CreateWriter(EnumVal* id, EnumVal* writer, const WriterBackend::WriterInfo& info,
// Takes ownership of fields and info.
WriterFrontend* CreateWriter(EnumVal* id, EnumVal* writer, WriterBackend::WriterInfo* info,
int num_fields, const threading::Field* const* fields,
bool local, bool remote);
@ -175,7 +175,7 @@ protected:
void SendAllWritersTo(RemoteSerializer::PeerID peer);
// Signals that a file has been rotated.
bool FinishedRotation(WriterFrontend* writer, string new_name, string old_name,
bool FinishedRotation(WriterFrontend* writer, const char* new_name, const char* old_name,
double open, double close, bool terminating);
// Deletes the values as passed into Write().

View file

@ -18,20 +18,26 @@ namespace logging {
class RotationFinishedMessage : public threading::OutputMessage<WriterFrontend>
{
public:
RotationFinishedMessage(WriterFrontend* writer, string new_name, string old_name,
RotationFinishedMessage(WriterFrontend* writer, const char* new_name, const char* old_name,
double open, double close, bool terminating)
: threading::OutputMessage<WriterFrontend>("RotationFinished", writer),
new_name(new_name), old_name(old_name), open(open),
new_name(copy_string(new_name)), old_name(copy_string(old_name)), open(open),
close(close), terminating(terminating) { }
virtual ~RotationFinishedMessage()
{
delete [] new_name;
delete [] old_name;
}
virtual bool Process()
{
return log_mgr->FinishedRotation(Object(), new_name, old_name, open, close, terminating);
}
private:
string new_name;
string old_name;
const char* new_name;
const char* old_name;
double open;
double close;
bool terminating;
@ -65,12 +71,16 @@ bool WriterBackend::WriterInfo::Read(SerializationFormat* fmt)
{
int size;
if ( ! (fmt->Read(&path, "path") &&
string tmp_path;
if ( ! (fmt->Read(&tmp_path, "path") &&
fmt->Read(&rotation_base, "rotation_base") &&
fmt->Read(&rotation_interval, "rotation_interval") &&
fmt->Read(&size, "config_size")) )
return false;
path = copy_string(tmp_path.c_str());
config.clear();
while ( size )
@ -81,7 +91,7 @@ bool WriterBackend::WriterInfo::Read(SerializationFormat* fmt)
if ( ! (fmt->Read(&value, "config-value") && fmt->Read(&value, "config-key")) )
return false;
config.insert(std::make_pair(value, key));
config.insert(std::make_pair(copy_string(value.c_str()), copy_string(key.c_str())));
}
return true;
@ -98,7 +108,7 @@ bool WriterBackend::WriterInfo::Write(SerializationFormat* fmt) const
fmt->Write(size, "config_size")) )
return false;
for ( config_map::const_iterator i = config.begin(); i != config.end(); ++i )
for ( config_map::const_iterator i = config.begin(); i != config.end(); ++i )
{
if ( ! (fmt->Write(i->first, "config-value") && fmt->Write(i->second, "config-key")) )
return false;
@ -113,8 +123,7 @@ WriterBackend::WriterBackend(WriterFrontend* arg_frontend) : MsgThread()
fields = 0;
buffering = true;
frontend = arg_frontend;
info.path = "<path not yet set>";
info = new WriterInfo(frontend->Info());
SetName(frontend->Name());
}
@ -128,6 +137,8 @@ WriterBackend::~WriterBackend()
delete [] fields;
}
delete info;
}
void WriterBackend::DeleteVals(int num_writes, Value*** vals)
@ -144,7 +155,7 @@ void WriterBackend::DeleteVals(int num_writes, Value*** vals)
delete [] vals;
}
bool WriterBackend::FinishedRotation(string new_name, string old_name,
bool WriterBackend::FinishedRotation(const char* new_name, const char* old_name,
double open, double close, bool terminating)
{
SendOut(new RotationFinishedMessage(frontend, new_name, old_name, open, close, terminating));
@ -156,15 +167,12 @@ void WriterBackend::DisableFrontend()
SendOut(new DisableMessage(frontend));
}
bool WriterBackend::Init(const WriterInfo& arg_info, int arg_num_fields, const Field* const* arg_fields, const string& frontend_name)
bool WriterBackend::Init(int arg_num_fields, const Field* const* arg_fields)
{
info = arg_info;
num_fields = arg_num_fields;
fields = arg_fields;
SetName(frontend->Name());
if ( ! DoInit(arg_info, arg_num_fields, arg_fields) )
if ( ! DoInit(*info, arg_num_fields, arg_fields) )
{
DisableFrontend();
return false;
@ -246,7 +254,7 @@ bool WriterBackend::SetBuf(bool enabled)
return true;
}
bool WriterBackend::Rotate(string rotated_path, double open,
bool WriterBackend::Rotate(const char* rotated_path, double open,
double close, bool terminating)
{
if ( ! DoRotate(rotated_path, open, close, terminating) )

View file

@ -48,14 +48,17 @@ public:
*/
struct WriterInfo
{
typedef std::map<string, string> config_map;
// Structure takes ownership of these strings.
typedef std::map<const char*, const char*> config_map;
/**
* A string left to the interpretation of the writer
* implementation; it corresponds to the 'path' value configured
* on the script-level for the logging filter.
*
* Structure takes ownership of string.
*/
string path;
const char* path;
/**
* The rotation interval as configured for this writer.
@ -76,9 +79,38 @@ public:
* A map of key/value pairs corresponding to the relevant
* filter's "config" table.
*/
std::map<string, string> config;
config_map config;
WriterInfo()
{
path = 0;
}
WriterInfo(const WriterInfo& other)
{
path = other.path ? copy_string(other.path) : 0;
rotation_interval = other.rotation_interval;
rotation_base = other.rotation_base;
network_time = other.network_time;
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)));
}
~WriterInfo()
{
delete [] path;
for ( config_map::iterator i = config.begin(); i != config.end(); i++ )
{
delete [] i->first;
delete [] i->second;
}
}
private:
const WriterInfo& operator=(const WriterInfo& other); // Disable.
friend class ::RemoteSerializer;
// Note, these need to be adapted when changing the struct's
@ -90,7 +122,6 @@ public:
/**
* One-time initialization of the writer to define the logged fields.
*
* @param info Meta information for the writer.
* @param num_fields
*
* @param fields An array of size \a num_fields with the log fields.
@ -100,7 +131,7 @@ public:
*
* @return False if an error occured.
*/
bool Init(const WriterInfo& info, int num_fields, const threading::Field* const* fields, const string& frontend_name);
bool Init(int num_fields, const threading::Field* const* fields);
/**
* Writes one log entry.
@ -146,7 +177,7 @@ public:
*
* @return False if an error occured.
*/
bool Rotate(string rotated_path, double open, double close, bool terminating);
bool Rotate(const char* rotated_path, double open, double close, bool terminating);
/**
* Disables the frontend that has instantiated this backend. Once
@ -157,7 +188,7 @@ public:
/**
* Returns the additional writer information passed into the constructor.
*/
const WriterInfo& Info() const { return info; }
const WriterInfo& Info() const { return *info; }
/**
* Returns the number of log fields as passed into the constructor.
@ -193,7 +224,7 @@ public:
* @param terminating: True if the original rotation request occured
* due to the main Bro process shutting down.
*/
bool FinishedRotation(string new_name, string old_name,
bool FinishedRotation(const char* new_name, const char* old_name,
double open, double close, bool terminating);
/** Helper method to render an IP address as a string.
@ -322,7 +353,7 @@ protected:
* due the main Bro prcoess terminating (and not because we've
* reached a regularly scheduled time for rotation).
*/
virtual bool DoRotate(string rotated_path, double open, double close,
virtual bool DoRotate(const char* rotated_path, double open, double close,
bool terminating) = 0;
/**
@ -351,7 +382,7 @@ private:
// this class, it's running in a different thread!
WriterFrontend* frontend;
WriterInfo info; // Meta information as passed to Init().
const WriterInfo* info; // Meta information.
int num_fields; // Number of log fields.
const threading::Field* const* fields; // Log fields.
bool buffering; // True if buffering is enabled.

View file

@ -16,35 +16,36 @@ namespace logging {
class InitMessage : public threading::InputMessage<WriterBackend>
{
public:
InitMessage(WriterBackend* backend, const WriterBackend::WriterInfo& info, const int num_fields, const Field* const* fields, const string& frontend_name)
InitMessage(WriterBackend* backend, const int num_fields, const Field* const* fields)
: threading::InputMessage<WriterBackend>("Init", backend),
info(info), num_fields(num_fields), fields(fields),
frontend_name(frontend_name) { }
num_fields(num_fields), fields(fields)
{}
virtual bool Process() { return Object()->Init(info, num_fields, fields, frontend_name); }
virtual bool Process() { return Object()->Init(num_fields, fields); }
private:
WriterBackend::WriterInfo info;
const int num_fields;
const Field * const* fields;
const string frontend_name;
};
class RotateMessage : public threading::InputMessage<WriterBackend>
{
public:
RotateMessage(WriterBackend* backend, WriterFrontend* frontend, const string rotated_path, const double open,
RotateMessage(WriterBackend* backend, WriterFrontend* frontend, const char* rotated_path, const double open,
const double close, const bool terminating)
: threading::InputMessage<WriterBackend>("Rotate", backend),
frontend(frontend),
rotated_path(rotated_path), open(open),
rotated_path(copy_string(rotated_path)), open(open),
close(close), terminating(terminating) { }
virtual ~RotateMessage() { delete [] rotated_path; }
virtual bool Process() { return Object()->Rotate(rotated_path, open, close, terminating); }
private:
WriterFrontend* frontend;
const string rotated_path;
const char* rotated_path;
const double open;
const double close;
const bool terminating;
@ -96,7 +97,7 @@ private:
using namespace logging;
WriterFrontend::WriterFrontend(EnumVal* arg_stream, EnumVal* arg_writer, bool arg_local, bool arg_remote)
WriterFrontend::WriterFrontend(const WriterBackend::WriterInfo& arg_info, EnumVal* arg_stream, EnumVal* arg_writer, bool arg_local, bool arg_remote)
{
stream = arg_stream;
writer = arg_writer;
@ -109,7 +110,10 @@ WriterFrontend::WriterFrontend(EnumVal* arg_stream, EnumVal* arg_writer, bool ar
remote = arg_remote;
write_buffer = 0;
write_buffer_pos = 0;
ty_name = "<not set>";
info = new WriterBackend::WriterInfo(arg_info);
const char* w = arg_writer->Type()->AsEnumType()->Lookup(arg_stream->InternalInt());
name = copy_string(fmt("%s/%s", arg_info.path, w));
if ( local )
{
@ -127,14 +131,7 @@ WriterFrontend::~WriterFrontend()
{
Unref(stream);
Unref(writer);
}
string WriterFrontend::Name() const
{
if ( ! info.path.size() )
return ty_name;
return ty_name + "/" + info.path;
delete info;
}
void WriterFrontend::Stop()
@ -143,7 +140,7 @@ void WriterFrontend::Stop()
SetDisable();
}
void WriterFrontend::Init(const WriterBackend::WriterInfo& arg_info, int arg_num_fields, const Field* const * arg_fields)
void WriterFrontend::Init(int arg_num_fields, const Field* const * arg_fields)
{
if ( disabled )
return;
@ -151,19 +148,18 @@ void WriterFrontend::Init(const WriterBackend::WriterInfo& arg_info, int arg_num
if ( initialized )
reporter->InternalError("writer initialize twice");
info = arg_info;
num_fields = arg_num_fields;
fields = arg_fields;
initialized = true;
if ( backend )
backend->SendIn(new InitMessage(backend, arg_info, arg_num_fields, arg_fields, Name()));
backend->SendIn(new InitMessage(backend, arg_num_fields, arg_fields));
if ( remote )
remote_serializer->SendLogCreateWriter(stream,
writer,
arg_info,
*info,
arg_num_fields,
arg_fields);
@ -177,7 +173,7 @@ void WriterFrontend::Write(int num_fields, Value** vals)
if ( remote )
remote_serializer->SendLogWrite(stream,
writer,
info.path,
info->path,
num_fields,
vals);
@ -242,7 +238,7 @@ void WriterFrontend::Flush(double network_time)
backend->SendIn(new FlushMessage(backend, network_time));
}
void WriterFrontend::Rotate(string rotated_path, double open, double close, bool terminating)
void WriterFrontend::Rotate(const char* rotated_path, double open, double close, bool terminating)
{
if ( disabled )
return;

View file

@ -31,6 +31,10 @@ public:
* script-level \c Log::Writer enum (e.g., \a WRITER_ASCII). The
* frontend will internally instantiate a WriterBackend of the
* corresponding type.
*
* info: The meta information struct for the writer.
*
* writer_name: A descriptive name for the writer's type.
*
* local: If true, the writer will instantiate a local backend.
*
@ -39,7 +43,7 @@ public:
*
* Frontends must only be instantiated by the main thread.
*/
WriterFrontend(EnumVal* stream, EnumVal* writer, bool local, bool remote);
WriterFrontend(const WriterBackend::WriterInfo& info, EnumVal* stream, EnumVal* writer, bool local, bool remote);
/**
* Destructor.
@ -68,7 +72,7 @@ public:
*
* This method must only be called from the main thread.
*/
void Init(const WriterBackend::WriterInfo& info, int num_fields, const threading::Field* const* fields);
void Init(int num_fields, const threading::Field* const* fields);
/**
* Write out a record.
@ -130,7 +134,7 @@ public:
*
* This method must only be called from the main thread.
*/
void Rotate(string rotated_path, double open, double close, bool terminating);
void Rotate(const char* rotated_path, double open, double close, bool terminating);
/**
* Finalizes writing to this tream.
@ -175,7 +179,7 @@ public:
/**
* Returns the additional writer information as passed into the constructor.
*/
const WriterBackend::WriterInfo& Info() const { return info; }
const WriterBackend::WriterInfo& Info() const { return *info; }
/**
* Returns the number of log fields as passed into the constructor.
@ -188,7 +192,7 @@ public:
*
* This method is safe to call from any thread.
*/
string Name() const;
const char* Name() const { return name; }
/**
* Returns the log fields as passed into the constructor.
@ -210,8 +214,8 @@ protected:
bool local; // True if logging locally.
bool remote; // True if loggin remotely.
string ty_name; // Name of the backend type. Set by the manager.
WriterBackend::WriterInfo info; // The writer information.
const char* name; // Descriptive name of the
WriterBackend::WriterInfo* info; // The writer information.
int num_fields; // The number of log fields.
const threading::Field* const* fields; // The log fields.

View file

@ -52,6 +52,8 @@ Ascii::Ascii(WriterFrontend* frontend) : WriterBackend(frontend)
Ascii::~Ascii()
{
//fprintf(stderr, "DTOR %p\n", this);
// Normally, the file will be closed here already via the Finish()
// message. But when we terminate abnormally, we may still have it open.
if ( fd )
@ -78,7 +80,10 @@ void Ascii::CloseFile(double t)
return;
if ( include_meta )
WriteHeaderField("end", t ? Timestamp(t) : "<abnormal termination>");
{
string ts = t ? Timestamp(t) : string("<abnormal termination>");
WriteHeaderField("end", ts);
}
close(fd);
fd = 0;
@ -118,6 +123,8 @@ bool Ascii::DoInit(const WriterInfo& info, int num_fields, const Field* const *
if ( ! safe_write(fd, str.c_str(), str.length()) )
goto write_error;
string ts = Timestamp(info.network_time);
if ( ! (WriteHeaderField("set_separator", get_escaped_string(
string(set_separator, set_separator_len), false)) &&
WriteHeaderField("empty_field", get_escaped_string(
@ -125,8 +132,8 @@ bool Ascii::DoInit(const WriterInfo& info, int num_fields, const Field* const *
WriteHeaderField("unset_field", get_escaped_string(
string(unset_field, unset_field_len), false)) &&
WriteHeaderField("path", get_escaped_string(path, false)) &&
WriteHeaderField("start", Timestamp(info.network_time))) )
goto write_error;
WriteHeaderField("start", ts)) )
goto write_error;
for ( int i = 0; i < num_fields; ++i )
{
@ -136,8 +143,8 @@ bool Ascii::DoInit(const WriterInfo& info, int num_fields, const Field* const *
types += string(separator, separator_len);
}
names += fields[i]->name;
types += fields[i]->TypeName();
names += string(fields[i]->name);
types += fields[i]->TypeName().c_str();
}
if ( ! (WriteHeaderField("fields", names)
@ -229,8 +236,8 @@ bool Ascii::DoWriteOne(ODesc* desc, Value* val, const Field* field)
case TYPE_FILE:
case TYPE_FUNC:
{
int size = val->val.string_val->size();
const char* data = val->val.string_val->data();
int size = val->val.string_val.length;
const char* data = val->val.string_val.data;
if ( ! size )
{
@ -311,8 +318,7 @@ bool Ascii::DoWriteOne(ODesc* desc, Value* val, const Field* field)
}
default:
Error(Fmt("unsupported field format %d for %s", val->type,
field->name.c_str()));
Error(Fmt("unsupported field format %d for %s", val->type, field->name));
return false;
}
@ -366,7 +372,7 @@ write_error:
return false;
}
bool Ascii::DoRotate(string rotated_path, double open, double close, bool terminating)
bool Ascii::DoRotate(const char* rotated_path, double open, double close, bool terminating)
{
// Don't rotate special files or if there's not one currently open.
if ( ! fd || IsSpecial(Info().path) )
@ -374,10 +380,10 @@ bool Ascii::DoRotate(string rotated_path, double open, double close, bool termin
CloseFile(close);
string nname = rotated_path + "." + LogExt();
string nname = string(rotated_path) + "." + LogExt();
rename(fname.c_str(), nname.c_str());
if ( ! FinishedRotation(nname, fname, open, close, terminating) )
if ( ! FinishedRotation(nname.c_str(), fname.c_str(), open, close, terminating) )
{
Error(Fmt("error rotating %s to %s", fname.c_str(), nname.c_str()));
return false;
@ -401,19 +407,22 @@ bool Ascii::DoHeartbeat(double network_time, double current_time)
string Ascii::LogExt()
{
const char* ext = getenv("BRO_LOG_SUFFIX");
if ( ! ext ) ext = "log";
if ( ! ext )
ext = "log";
return ext;
}
string Ascii::Timestamp(double t)
{
struct tm tm;
char buf[128];
const char* const date_fmt = "%Y-%m-%d-%H-%M-%S";
time_t teatime = time_t(t);
localtime_r(&teatime, &tm);
strftime(buf, sizeof(buf), date_fmt, &tm);
struct tm tmbuf;
struct tm* tm = localtime_r(&teatime, &tmbuf);
char buf[128];
const char* const date_fmt = "%Y-%m-%d-%H-%M-%S";
strftime(buf, sizeof(buf), date_fmt, tm);
return buf;
}

View file

@ -24,7 +24,7 @@ protected:
virtual bool DoWrite(int num_fields, const threading::Field* const* fields,
threading::Value** vals);
virtual bool DoSetBuf(bool enabled);
virtual bool DoRotate(string rotated_path, double open,
virtual bool DoRotate(const char* rotated_path, double open,
double close, bool terminating);
virtual bool DoFlush(double network_time);
virtual bool DoFinish(double network_time);

View file

@ -78,10 +78,10 @@ std::string DataSeries::LogValueToString(threading::Value *val)
case TYPE_STRING:
case TYPE_FILE:
case TYPE_FUNC:
if ( ! val->val.string_val->size() )
if ( ! val->val.string_val.length )
return "";
return string(val->val.string_val->data(), val->val.string_val->size());
return string(val->val.string_val.data, val->val.string_val.length);
case TYPE_TABLE:
{
@ -302,7 +302,8 @@ bool DataSeries::DoInit(const WriterInfo& info, int num_fields, const threading:
if( ds_dump_schema )
{
FILE* pFile = fopen ( string(info.path + ".ds.xml").c_str() , "wb" );
string name = string(info.path) + ".ds.xml";
FILE* pFile = fopen(name.c_str(), "wb" );
if( pFile )
{
@ -394,17 +395,17 @@ bool DataSeries::DoWrite(int num_fields, const threading::Field* const * fields,
return true;
}
bool DataSeries::DoRotate(string rotated_path, double open, double close, bool terminating)
bool DataSeries::DoRotate(const char* rotated_path, double open, double close, bool terminating)
{
// Note that if DS files are rotated too often, the aggregate log
// size will be (much) larger.
CloseLog();
string dsname = Info().path + ".ds";
string nname = rotated_path + ".ds";
string dsname = string(Info().path) + ".ds";
string nname = string(rotated_path) + ".ds";
rename(dsname.c_str(), nname.c_str());
if ( ! FinishedRotation(nname, dsname, open, close, terminating) )
if ( ! FinishedRotation(nname.c_str(), dsname.c_str(), open, close, terminating) )
{
Error(Fmt("error rotating %s to %s", dsname.c_str(), nname.c_str()));
return false;

View file

@ -32,7 +32,7 @@ protected:
virtual bool DoWrite(int num_fields, const threading::Field* const* fields,
threading::Value** vals);
virtual bool DoSetBuf(bool enabled);
virtual bool DoRotate(string rotated_path, double open,
virtual bool DoRotate(const char* rotated_path, double open,
double close, bool terminating);
virtual bool DoFlush(double network_time);
virtual bool DoFinish(double network_time);

View file

@ -1,4 +1,6 @@
#include <algorithm>
#include "None.h"
#include "NetVar.h"
@ -15,8 +17,17 @@ bool None::DoInit(const WriterInfo& info, int num_fields,
std::cout << " rotation_interval=" << info.rotation_interval << std::endl;
std::cout << " rotation_base=" << info.rotation_base << std::endl;
for ( std::map<string,string>::const_iterator i = info.config.begin(); i != info.config.end(); i++ )
std::cout << " config[" << i->first << "] = " << i->second << std::endl;
// Output the config sorted by keys.
std::vector<std::pair<string, string> > keys;
for ( WriterInfo::config_map::const_iterator i = info.config.begin(); i != info.config.end(); i++ )
keys.push_back(std::make_pair(i->first, i->second));
std::sort(keys.begin(), keys.end());
for ( std::vector<std::pair<string,string> >::const_iterator i = keys.begin(); i != keys.end(); i++ )
std::cout << " config[" << (*i).first << "] = " << (*i).second << std::endl;
for ( int i = 0; i < num_fields; i++ )
{
@ -31,11 +42,11 @@ bool None::DoInit(const WriterInfo& info, int num_fields,
return true;
}
bool None::DoRotate(string rotated_path, double open, double close, bool terminating)
bool None::DoRotate(const char* rotated_path, double open, double close, bool terminating)
{
if ( ! FinishedRotation(string("/dev/null"), Info().path, open, close, terminating))
if ( ! FinishedRotation("/dev/null", Info().path, open, close, terminating))
{
Error(Fmt("error rotating %s", Info().path.c_str()));
Error(Fmt("error rotating %s", Info().path));
return false;
}

View file

@ -24,7 +24,7 @@ protected:
virtual bool DoWrite(int num_fields, const threading::Field* const* fields,
threading::Value** vals) { return true; }
virtual bool DoSetBuf(bool enabled) { return true; }
virtual bool DoRotate(string rotated_path, double open,
virtual bool DoRotate(const char* rotated_path, double open,
double close, bool terminating);
virtual bool DoFlush(double network_time) { return true; }
virtual bool DoFinish(double network_time) { return true; }