blob: 738531f45f499e3e41240ea57d558aa44d390ee0 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author Sergey L. Ivashin
*
*/
#include "CountWriters.h"
#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#ifdef _WIN32
#pragma pack(push)
#include <windows.h>
#pragma pack(pop)
#endif
using namespace std;
#define MAILSLOT "Jitrino.Counters"
#define RUNSTART "---Dump of counters begins---"
#define RUNSTOP "---Dump of counters ends---"
namespace Jitrino
{
//=============================================================================================
// class CounterBase implementation
//=============================================================================================
CounterBase::CounterBase (const char* s)
: key(s)
{
next = head;
head = this;
}
CounterBase::~CounterBase ()
{
}
void CounterBase::link ()
{
for (CounterBase* ptr = head; ptr != 0; ptr = ptr->next)
if (ptr == this)
return;
next = head;
head = this;
}
CounterBase* CounterBase::head = 0;
//=============================================================================================
// class CountWriterFile implementation
//=============================================================================================
CountWriterFile::CountWriterFile (const char* s)
:file(0)
{
open(s);
}
CountWriterFile::~CountWriterFile ()
{
close();
}
bool CountWriterFile::open (const char* fname)
{
assert(file == 0);
if (fname != 0 && *fname != 0)
{
file = new ofstream;
file->open(fname, ios::app);
if (!*file)
{
delete file;
file = 0;
return false;
}
}
return true;
}
static bool compareCounters (CounterBase* a, CounterBase* b)
{
return strcmp(a->key, b->key) < 0;
}
void CountWriterFile::close ()
{
if ((os = file) == 0)
os = &cout;
*os << RUNSTART << endl;
vector<CounterBase*> counts;
for (CounterBase* ptr = CounterBase::head; ptr != 0 ; ptr = ptr->next)
if (ptr->key != 0)
counts.push_back(ptr);
sort(counts.begin(), counts.end(), compareCounters);
for (vector<CounterBase*>::iterator ptr = counts.begin(), end = counts.end(); ptr != end; ++ptr)
(*ptr)->write(*this);
*os << RUNSTOP << endl;
if (file != 0)
{
delete file;
file = 0;
}
}
void CountWriterFile::write (const char* key, const char* value)
{
*os << key << "=" << value << endl;
}
void CountWriterFile::write (const char* key, int value)
{
*os << key << "=" << value << endl;
}
void CountWriterFile::write (const char* key, size_t value)
{
*os << key << "=" << value << endl;
}
void CountWriterFile::write (const char* key, double value)
{
*os << key << "=" << value << endl;
}
//=============================================================================================
// class CountWriterMail implementation
//=============================================================================================
#ifdef _WIN32
CountWriterMail::CountWriterMail (const char* s)
: sloth(INVALID_HANDLE_VALUE)
{
open(s);
}
CountWriterMail::~CountWriterMail ()
{
if (sloth != INVALID_HANDLE_VALUE)
close();
}
// 'server' should be name of the computer to which mail is sent or 0
//
bool CountWriterMail::open (const char* server)
{
assert(sloth == INVALID_HANDLE_VALUE);
char slotname[128];
_snprintf(slotname, sizeof(slotname), "\\\\%s\\mailslot\\"MAILSLOT, (server == 0 || *server == 0) ? "." : server);
sloth = CreateFile(slotname, GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
mail(RUNSTART"\0", strlen(RUNSTART));
if (sloth == INVALID_HANDLE_VALUE)
cerr << "CountWriter failed to write to '" << slotname << "' (server not running?)" << endl;
return sloth != INVALID_HANDLE_VALUE;
}
void CountWriterMail::close ()
{
for (CounterBase* ptr = CounterBase::head; ptr != 0 && sloth != INVALID_HANDLE_VALUE; ptr = ptr->next)
if (ptr->key != 0)
ptr->write(*this);
mail(RUNSTOP"\0", strlen(RUNSTOP));
if (sloth != INVALID_HANDLE_VALUE)
{
CloseHandle(sloth);
sloth = INVALID_HANDLE_VALUE;
}
}
void CountWriterMail::write (const char* key, const char* value)
{
char buff[128];
mail(buff, _snprintf(buff, sizeof(buff), "%s=%s", key, value));
}
void CountWriterMail::write (const char* key, int value)
{
char buff[128];
mail(buff, _snprintf(buff, sizeof(buff), "%s=%i", key, value));
}
void CountWriterMail::write (const char* key, size_t value)
{
char buff[128];
mail(buff, _snprintf(buff, sizeof(buff), "%s=%u", key, value));
}
void CountWriterMail::write (const char* key, double value)
{
char buff[128];
mail(buff, _snprintf(buff, sizeof(buff), "%s=%G", key, value));
}
void CountWriterMail::mail (const char* str, size_t bytes)
{
assert(str[bytes] == 0);
bytes++;
DWORD written;
if (sloth != INVALID_HANDLE_VALUE &&
WriteFile(sloth, str, static_cast<DWORD>(bytes), &written, 0) == 0)
{
CloseHandle(sloth);
sloth = INVALID_HANDLE_VALUE;
}
}
#endif //#ifdef _WIN32
} //namespace Jitrino