// distribution boxbackup-0.10 (svn version: 494)
//
// Copyright (c) 2003 - 2006
// Ben Summers and contributors. 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.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. All use of this software and associated advertising materials must
// display the following acknowledgment:
// This product includes software developed by Ben Summers.
// 4. The names of the Authors may not be used to endorse or promote
// products derived from this software without specific prior written
// permission.
//
// [Where legally impermissible the Authors do not disclaim liability for
// direct physical injury or death caused solely by defects in the software
// unless it is modified by a third party.]
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, 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 DAMAGE.
//
//
//
// --------------------------------------------------------------------------
//
// File
// Name: BackupStoreDaemon.cpp
// Purpose: Backup store daemon
// Created: 2003/08/20
//
// --------------------------------------------------------------------------
#include "Box.h"
#include <stdlib.h>
#include <stdio.h>
#include <syslog.h>
#include <signal.h>
#include "BackupContext.h"
#include "BackupStoreDaemon.h"
#include "BackupStoreConfigVerify.h"
#include "autogen_BackupProtocolServer.h"
#include "RaidFileController.h"
#include "BackupStoreAccountDatabase.h"
#include "BackupStoreAccounts.h"
#include "BannerText.h"
#include "MemLeakFindOn.h"
// --------------------------------------------------------------------------
//
// Function
// Name: BackupStoreDaemon::BackupStoreDaemon()
// Purpose: Constructor
// Created: 2003/08/20
//
// --------------------------------------------------------------------------
BackupStoreDaemon::BackupStoreDaemon()
: mpAccountDatabase(0),
mpAccounts(0),
mExtendedLogging(false),
mHaveForkedHousekeeping(false),
mIsHousekeepingProcess(false),
mInterProcessComms(mInterProcessCommsSocket)
{
}
// --------------------------------------------------------------------------
//
// Function
// Name: BackupStoreDaemon::~BackupStoreDaemon()
// Purpose: Destructor
// Created: 2003/08/20
//
// --------------------------------------------------------------------------
BackupStoreDaemon::~BackupStoreDaemon()
{
// Must delete this one before the database ...
if(mpAccounts != 0)
{
delete mpAccounts;
mpAccounts = 0;
}
// ... as the mpAccounts object has a reference to it
if(mpAccountDatabase != 0)
{
delete mpAccountDatabase;
mpAccountDatabase = 0;
}
}
// --------------------------------------------------------------------------
//
// Function
// Name: BackupStoreDaemon::DaemonName()
// Purpose: Name of daemon
// Created: 2003/08/20
//
// --------------------------------------------------------------------------
const char *BackupStoreDaemon::DaemonName() const
{
return "bbstored";
}
// --------------------------------------------------------------------------
//
// Function
// Name: BackupStoreDaemon::DaemonBanner()
// Purpose: Daemon banner
// Created: 1/1/04
//
// --------------------------------------------------------------------------
const char *BackupStoreDaemon::DaemonBanner() const
{
#ifndef NDEBUG
// Don't display banner in debug builds
return 0;
#else
return BANNER_TEXT("Backup Store Server");
#endif
}
// --------------------------------------------------------------------------
//
// Function
// Name: BackupStoreDaemon::GetConfigVerify()
// Purpose: Configuration definition
// Created: 2003/08/20
//
// --------------------------------------------------------------------------
const ConfigurationVerify *BackupStoreDaemon::GetConfigVerify() const
{
return &BackupConfigFileVerify;
}
// --------------------------------------------------------------------------
//
// Function
// Name: BackupStoreDaemon::SetupInInitialProcess()
// Purpose: Setup before we fork -- get raid file controller going
// Created: 2003/08/20
//
// --------------------------------------------------------------------------
void BackupStoreDaemon::SetupInInitialProcess()
{
const Configuration &config(GetConfiguration());
// Initialise the raid files controller
RaidFileController &rcontroller = RaidFileController::GetController();
rcontroller.Initialise(config.GetKeyValue("RaidFileConf").c_str());
// Load the account database
std::auto_ptr<BackupStoreAccountDatabase> pdb(BackupStoreAccountDatabase::Read(config.GetKeyValue("AccountDatabase").c_str()));
mpAccountDatabase = pdb.release();
// Create a accounts object
mpAccounts = new BackupStoreAccounts(*mpAccountDatabase);
// Ready to go!
}
// --------------------------------------------------------------------------
//
// Function
// Name: BackupStoreDaemon::Run()
// Purpose: Run shim for the store daemon -- read some config details
// Created: 2003/10/24
//
// --------------------------------------------------------------------------
void BackupStoreDaemon::Run()
{
// Get extended logging flag
mExtendedLogging = false;
const Configuration &config(GetConfiguration());
mExtendedLogging = config.GetKeyValueBool("ExtendedLogging");
// Fork off housekeeping daemon -- must only do this the first time Run() is called
if(!mHaveForkedHousekeeping)
{
// Open a socket pair for communication
int sv[2] = {-1,-1};
if(::socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, sv) != 0)
{
THROW_EXCEPTION(ServerException, SocketPairFailed)
}
int whichSocket = 0;
// Fork
switch(::fork())
{
case -1:
{
// Error
THROW_EXCEPTION(ServerException, ServerForkError)
}
break;
case 0:
{
// In child process
mIsHousekeepingProcess = true;
SetProcessTitle("housekeeping, idle");
whichSocket = 1;
// Change the log name
::openlog("bbstored/hk", LOG_PID, LOG_LOCAL6);
// Log that housekeeping started
::syslog(LOG_INFO, "Housekeeping process started");
// Ignore term and hup
// Parent will handle these and alert the child via the socket, don't want to randomly die
::signal(SIGHUP, SIG_IGN);
::signal(SIGTERM, SIG_IGN);
}
break;
default:
{
// Parent process
whichSocket = 0;
}
break;
}
// Mark that this has been, so -HUP doesn't try and do this again
mHaveForkedHousekeeping = true;
// Attach the comms thing to the right socket, and close the other one
mInterProcessCommsSocket.Attach(sv[whichSocket]);
if(::close(sv[(whichSocket == 0)?1:0]) != 0)
{
THROW_EXCEPTION(ServerException, SocketCloseError)
}
}
if(mIsHousekeepingProcess)
{
// Housekeeping process -- do other stuff
HousekeepingProcess();
}
else
{
// In server process -- use the base class to do the magic
ServerTLS<BOX_PORT_BBSTORED>::Run();
// Why did it stop? Tell the housekeeping process to do the same
if(IsReloadConfigWanted())
{
mInterProcessCommsSocket.Write("h\n", 2);
}
if(IsTerminateWanted())
{
mInterProcessCommsSocket.Write("t\n", 2);
}
}
}
// --------------------------------------------------------------------------
//
// Function
// Name: BackupStoreDaemon::Connection(SocketStreamTLS &)
// Purpose: Handles a connection
// Created: 2003/08/20
//
// --------------------------------------------------------------------------
void BackupStoreDaemon::Connection(SocketStreamTLS &rStream)
{
// Get the common name from the certificate
std::string clientCommonName(rStream.GetPeerCommonName());
// Log the name
::syslog(LOG_INFO, "Certificate CN: %s\n", clientCommonName.c_str());
// Check it
int32_t id;
if(::sscanf(clientCommonName.c_str(), "BACKUP-%x", &id) != 1)
{
// Bad! Disconnect immediately
return;
}
// Make ps listings clearer
SetProcessTitle("client %08x", id);
// Create a context, using this ID
BackupContext context(id, *this);
// See if the client has an account?
if(mpAccounts && mpAccounts->AccountExists(id))
{
std::string root;
int discSet;
mpAccounts->GetAccountRoot(id, root, discSet);
context.SetClientHasAccount(root, discSet);
}
// Handle a connection with the backup protocol
BackupProtocolServer server(rStream);
server.SetLogToSysLog(mExtendedLogging);
server.SetTimeout(BACKUP_STORE_TIMEOUT);
try
{
server.DoServer(context);
}
catch(...)
{
LogConnectionStats(clientCommonName.c_str(), rStream);
throw;
}
LogConnectionStats(clientCommonName.c_str(), rStream);
context.CleanUp();
}
void BackupStoreDaemon::LogConnectionStats(const char *commonName,
const SocketStreamTLS &s)
{
// Log the amount of data transferred
::syslog(LOG_INFO, "Connection statistics for %s: "
"IN=%lld OUT=%lld TOTAL=%lld\n", commonName,
s.GetBytesRead(), s.GetBytesWritten(),
s.GetBytesRead() + s.GetBytesWritten());
}
syntax highlighted by Code2HTML, v. 0.9.1