summaryrefslogtreecommitdiff
path: root/bin/bbackupd
diff options
context:
space:
mode:
authorChris Wilson <chris+github@qwirx.com>2006-10-14 14:44:23 +0000
committerChris Wilson <chris+github@qwirx.com>2006-10-14 14:44:23 +0000
commit264ef04ecb8668b21df8539e3a807d3f266a1780 (patch)
tree1ba2cfb0f19cb9163b4e105e02e76c70b51c1699 /bin/bbackupd
parentfe290e01bcb715e5fc55c98f072f2afe0d28e67c (diff)
* Oops, svn merged too much, undo again
Diffstat (limited to 'bin/bbackupd')
-rw-r--r--bin/bbackupd/BackupDaemon.cpp300
1 files changed, 105 insertions, 195 deletions
diff --git a/bin/bbackupd/BackupDaemon.cpp b/bin/bbackupd/BackupDaemon.cpp
index d6f4b7f4..99abb01f 100644
--- a/bin/bbackupd/BackupDaemon.cpp
+++ b/bin/bbackupd/BackupDaemon.cpp
@@ -59,7 +59,6 @@
#include "BackupStoreFilenameClear.h"
#include "BackupClientInodeToIDMap.h"
#include "autogen_BackupProtocolClient.h"
-#include "autogen_ConversionException.h"
#include "BackupClientCryptoKeys.h"
#include "BannerText.h"
#include "BackupStoreFile.h"
@@ -126,29 +125,6 @@ BackupDaemon::BackupDaemon()
}
#ifdef WIN32
- // Create the event object to signal from main thread to worker
- // when new messages are queued to be sent to the command socket.
- mhMessageToSendEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- if(mhMessageToSendEvent == INVALID_HANDLE_VALUE)
- {
- syslog(LOG_ERR, "Failed to create event object: error %d",
- GetLastError);
- exit(1);
- }
-
- // Create the event object to signal from worker to main thread
- // when a command has been received on the command socket.
- mhCommandReceivedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- if(mhCommandReceivedEvent == INVALID_HANDLE_VALUE)
- {
- syslog(LOG_ERR, "Failed to create event object: error %d",
- GetLastError);
- exit(1);
- }
-
- // Create the critical section to protect the message queue
- InitializeCriticalSection(&mMessageQueueLock);
-
// Create a thread to handle the named pipe
HANDLE hThread;
unsigned int dwThreadId;
@@ -286,6 +262,7 @@ void BackupDaemon::DeleteAllLocations()
#ifdef WIN32
void BackupDaemon::RunHelperThread(void)
{
+ this->mReceivedCommandConn = false;
mpCommandSocketInfo = new CommandSocketInfo;
WinNamedPipeStream& rSocket(mpCommandSocketInfo->mListeningSocket);
@@ -351,69 +328,15 @@ void BackupDaemon::RunHelperThread(void)
rSocket.Write(summary, summarySize);
rSocket.Write("ping\n", 5);
- // old queued messages are not useful
- EnterCriticalSection(&mMessageQueueLock);
- mMessageList.clear();
- ResetEvent(mhMessageToSendEvent);
- LeaveCriticalSection(&mMessageQueueLock);
-
IOStreamGetLine readLine(rSocket);
std::string command;
- while (rSocket.IsConnected() && !IsTerminateWanted())
+ while (rSocket.IsConnected() &&
+ readLine.GetLine(command) &&
+ !IsTerminateWanted())
{
- HANDLE handles[2];
- handles[0] = mhMessageToSendEvent;
- handles[1] = rSocket.GetReadableEvent();
-
- DWORD result = WaitForMultipleObjects(
- sizeof(handles)/sizeof(*handles),
- handles, FALSE, 1000);
-
- if(result == 0)
- {
- ResetEvent(mhMessageToSendEvent);
-
- EnterCriticalSection(&mMessageQueueLock);
- try
- {
- while (mMessageList.size() > 0)
- {
- std::string message = *(mMessageList.begin());
- mMessageList.erase(mMessageList.begin());
- printf("Sending '%s' to waiting client... ", message.c_str());
- message += "\n";
- rSocket.Write(message.c_str(),
- message.length());
-
- printf("done.\n");
- }
- }
- catch (...)
- {
- LeaveCriticalSection(&mMessageQueueLock);
- throw;
- }
- LeaveCriticalSection(&mMessageQueueLock);
- continue;
- }
- else if(result == WAIT_TIMEOUT)
- {
- continue;
- }
- else if(result != 1)
- {
- ::syslog(LOG_ERR, "WaitForMultipleObjects returned invalid result %d", result);
- continue;
- }
-
- if(!readLine.GetLine(command))
- {
- ::syslog(LOG_ERR, "Failed to read line");
- continue;
- }
-
- printf("Received command '%s' from client\n", command.c_str());
+ TRACE1("Received command '%s' over "
+ "command socket\n", command.c_str());
bool sendOK = false;
bool sendResponse = true;
@@ -432,7 +355,6 @@ void BackupDaemon::RunHelperThread(void)
this->mDoSyncFlagOut = true;
this->mSyncIsForcedOut = false;
sendOK = true;
- SetEvent(mhCommandReceivedEvent);
}
else if(command == "force-sync")
{
@@ -440,21 +362,18 @@ void BackupDaemon::RunHelperThread(void)
this->mDoSyncFlagOut = true;
this->mSyncIsForcedOut = true;
sendOK = true;
- SetEvent(mhCommandReceivedEvent);
}
else if(command == "reload")
{
// Reload the configuration
SetReloadConfigWanted();
sendOK = true;
- SetEvent(mhCommandReceivedEvent);
}
else if(command == "terminate")
{
// Terminate the daemon cleanly
SetTerminateWanted();
sendOK = true;
- SetEvent(mhCommandReceivedEvent);
}
else
{
@@ -464,17 +383,19 @@ void BackupDaemon::RunHelperThread(void)
}
// Send a response back?
- if(sendResponse)
+ if (sendResponse)
{
const char* response = sendOK ? "ok\n" : "error\n";
rSocket.Write(
response, strlen(response));
}
- if(disconnect)
+ if (disconnect)
{
break;
}
+
+ this->mReceivedCommandConn = true;
}
rSocket.Close();
@@ -494,9 +415,6 @@ void BackupDaemon::RunHelperThread(void)
::syslog(LOG_ERR, "Communication error with control client");
}
}
-
- CloseHandle(mhCommandReceivedEvent);
- CloseHandle(mhMessageToSendEvent);
}
#endif
@@ -1016,21 +934,8 @@ int BackupDaemon::UseScriptToSeeIfSyncAllowed()
}
else
{
- try
- {
- // How many seconds to wait?
- waitInSeconds = BoxConvert::Convert<int32_t, const std::string&>(line);
- }
- catch(ConversionException &e)
- {
- ::syslog(LOG_ERR, "Invalid output "
- "from SyncAllowScript '%s': "
- "'%s'",
- conf.GetKeyValue("SyncAllowScript").c_str(),
- line.c_str());
- throw;
- }
-
+ // How many seconds to wait?
+ waitInSeconds = BoxConvert::Convert<int32_t, const std::string&>(line);
::syslog(LOG_INFO, "Delaying sync by %d seconds (SyncAllowScript '%s')", waitInSeconds, conf.GetKeyValue("SyncAllowScript").c_str());
}
}
@@ -1049,7 +954,7 @@ int BackupDaemon::UseScriptToSeeIfSyncAllowed()
}
// Wait and then cleanup child process, if any
- if(pid != 0)
+ if (pid != 0)
{
int status = 0;
::waitpid(pid, &status, 0);
@@ -1072,27 +977,25 @@ int BackupDaemon::UseScriptToSeeIfSyncAllowed()
void BackupDaemon::WaitOnCommandSocket(box_time_t RequiredDelay, bool &DoSyncFlagOut, bool &SyncIsForcedOut)
{
#ifdef WIN32
- DWORD requiredDelayMs = BoxTimeToMilliSeconds(RequiredDelay);
+ // Really could use some interprocess protection, mutex etc
+ // any side effect should be too bad???? :)
+ DWORD timeout = (DWORD)BoxTimeToMilliSeconds(RequiredDelay);
- DWORD result = WaitForSingleObject(mhCommandReceivedEvent,
- (DWORD)requiredDelayMs);
-
- if(result == WAIT_OBJECT_0)
- {
- DoSyncFlagOut = this->mDoSyncFlagOut;
- SyncIsForcedOut = this->mSyncIsForcedOut;
- ResetEvent(mhCommandReceivedEvent);
- }
- else if(result == WAIT_TIMEOUT)
- {
- DoSyncFlagOut = false;
- SyncIsForcedOut = false;
- }
- else
+ while ( this->mReceivedCommandConn == false )
{
- ::syslog(LOG_ERR, "Unexpected result from "
- "WaitForSingleObject: error %d", GetLastError());
+ Sleep(1);
+
+ if ( timeout == 0 )
+ {
+ DoSyncFlagOut = false;
+ SyncIsForcedOut = false;
+ return;
+ }
+ timeout--;
}
+ this->mReceivedCommandConn = false;
+ DoSyncFlagOut = this->mDoSyncFlagOut;
+ SyncIsForcedOut = this->mSyncIsForcedOut;
return;
#else // ! WIN32
@@ -1195,9 +1098,8 @@ void BackupDaemon::WaitOnCommandSocket(box_time_t RequiredDelay, bool &DoSyncFla
while(mpCommandSocketInfo->mpGetLine != 0 && !mpCommandSocketInfo->mpGetLine->IsEOF()
&& mpCommandSocketInfo->mpGetLine->GetLine(command, false /* no preprocessing */, timeout))
{
- TRACE1("Receiving command '%s' over command socket\n",
- command.c_str());
-
+ TRACE1("Receiving command '%s' over command socket\n", command.c_str());
+
bool sendOK = false;
bool sendResponse = true;
@@ -1334,7 +1236,11 @@ void BackupDaemon::SendSyncStartOrFinish(bool SendStart)
// The bbackupctl program can't rely on a state change, because it
// may never change if the server doesn't need to be contacted.
- if(mpCommandSocketInfo != NULL &&
+#ifdef __MINGW32__
+#warning race condition: what happens if socket is closed?
+#endif
+
+ if (mpCommandSocketInfo != NULL &&
#ifdef WIN32
mpCommandSocketInfo->mListeningSocket.IsConnected()
#else
@@ -1342,18 +1248,15 @@ void BackupDaemon::SendSyncStartOrFinish(bool SendStart)
#endif
)
{
- std::string message = SendStart ? "start-sync" : "finish-sync";
+ const char* message = SendStart ? "start-sync\n" : "finish-sync\n";
try
{
#ifdef WIN32
- EnterCriticalSection(&mMessageQueueLock);
- mMessageList.push_back(message);
- SetEvent(mhMessageToSendEvent);
- LeaveCriticalSection(&mMessageQueueLock);
+ mpCommandSocketInfo->mListeningSocket.Write(message,
+ (int)strlen(message));
#else
- message += "\n";
- mpCommandSocketInfo->mpConnectedSocket->Write(
- message.c_str(), message.size());
+ mpCommandSocketInfo->mpConnectedSocket->Write(message,
+ strlen(message));
#endif
}
catch(std::exception &e)
@@ -1955,36 +1858,51 @@ void BackupDaemon::SetState(int State)
// command socket if there's an error
char newState[64];
- sprintf(newState, "state %d", State);
- std::string message = newState;
+ char newStateSize = sprintf(newState, "state %d\n", State);
#ifdef WIN32
- EnterCriticalSection(&mMessageQueueLock);
- mMessageList.push_back(newState);
- SetEvent(mhMessageToSendEvent);
- LeaveCriticalSection(&mMessageQueueLock);
-#else
- message += "\n";
-
- if(mpCommandSocketInfo == 0)
- {
- return;
- }
-
- if(mpCommandSocketInfo->mpConnectedSocket.get() == 0)
- {
- return;
- }
+ #ifndef _MSC_VER
+ #warning FIX ME: race condition
+ #endif
- // Something connected to the command socket, tell it about the new state
- try
+ // what happens if the socket is closed by the other thread before
+ // we can write to it? Null pointer deref at best.
+ if (mpCommandSocketInfo &&
+ mpCommandSocketInfo->mListeningSocket.IsConnected())
{
- mpCommandSocketInfo->mpConnectedSocket->Write(message.c_str(),
- message.length());
+ try
+ {
+ mpCommandSocketInfo->mListeningSocket.Write(newState, newStateSize);
+ }
+ catch(std::exception &e)
+ {
+ ::syslog(LOG_ERR, "Internal error while writing state "
+ "to command socket: %s", e.what());
+ CloseCommandConnection();
+ }
+ catch(...)
+ {
+ CloseCommandConnection();
+ }
}
- catch(...)
+#else
+ if(mpCommandSocketInfo != 0 && mpCommandSocketInfo->mpConnectedSocket.get() != 0)
{
- CloseCommandConnection();
+ // Something connected to the command socket, tell it about the new state
+ try
+ {
+ mpCommandSocketInfo->mpConnectedSocket->Write(newState, newStateSize);
+ }
+ catch(std::exception &e)
+ {
+ ::syslog(LOG_ERR, "Internal error while writing state "
+ "to command socket: %s", e.what());
+ CloseCommandConnection();
+ }
+ catch(...)
+ {
+ CloseCommandConnection();
+ }
}
#endif
}
@@ -2167,12 +2085,12 @@ void BackupDaemon::Location::Deserialize(Archive &rArchive)
//
//
mpDirectoryRecord.reset(NULL);
- if(mpExcludeFiles)
+ if (mpExcludeFiles)
{
delete mpExcludeFiles;
mpExcludeFiles = NULL;
}
- if(mpExcludeDirs)
+ if (mpExcludeDirs)
{
delete mpExcludeDirs;
mpExcludeDirs = NULL;
@@ -2191,17 +2109,15 @@ void BackupDaemon::Location::Deserialize(Archive &rArchive)
int64_t aMagicMarker = 0;
rArchive.Read(aMagicMarker);
- if(aMagicMarker == ARCHIVE_MAGIC_VALUE_NOOP)
+ if (aMagicMarker == ARCHIVE_MAGIC_VALUE_NOOP)
{
// NOOP
}
- else if(aMagicMarker == ARCHIVE_MAGIC_VALUE_RECURSE)
+ else if (aMagicMarker == ARCHIVE_MAGIC_VALUE_RECURSE)
{
BackupClientDirectoryRecord *pSubRecord = new BackupClientDirectoryRecord(0, "");
- if(!pSubRecord)
- {
+ if (!pSubRecord)
throw std::bad_alloc();
- }
mpDirectoryRecord.reset(pSubRecord);
mpDirectoryRecord->Deserialize(rArchive);
@@ -2217,17 +2133,15 @@ void BackupDaemon::Location::Deserialize(Archive &rArchive)
//
rArchive.Read(aMagicMarker);
- if(aMagicMarker == ARCHIVE_MAGIC_VALUE_NOOP)
+ if (aMagicMarker == ARCHIVE_MAGIC_VALUE_NOOP)
{
// NOOP
}
- else if(aMagicMarker == ARCHIVE_MAGIC_VALUE_RECURSE)
+ else if (aMagicMarker == ARCHIVE_MAGIC_VALUE_RECURSE)
{
mpExcludeFiles = new ExcludeList;
- if(!mpExcludeFiles)
- {
+ if (!mpExcludeFiles)
throw std::bad_alloc();
- }
mpExcludeFiles->Deserialize(rArchive);
}
@@ -2242,17 +2156,15 @@ void BackupDaemon::Location::Deserialize(Archive &rArchive)
//
rArchive.Read(aMagicMarker);
- if(aMagicMarker == ARCHIVE_MAGIC_VALUE_NOOP)
+ if (aMagicMarker == ARCHIVE_MAGIC_VALUE_NOOP)
{
// NOOP
}
- else if(aMagicMarker == ARCHIVE_MAGIC_VALUE_RECURSE)
+ else if (aMagicMarker == ARCHIVE_MAGIC_VALUE_RECURSE)
{
mpExcludeDirs = new ExcludeList;
- if(!mpExcludeDirs)
- {
+ if (!mpExcludeDirs)
throw std::bad_alloc();
- }
mpExcludeDirs->Deserialize(rArchive);
}
@@ -2284,7 +2196,7 @@ void BackupDaemon::Location::Serialize(Archive & rArchive) const
//
//
//
- if(mpDirectoryRecord.get() == NULL)
+ if (mpDirectoryRecord.get() == NULL)
{
int64_t aMagicMarker = ARCHIVE_MAGIC_VALUE_NOOP;
rArchive.Write(aMagicMarker);
@@ -2300,7 +2212,7 @@ void BackupDaemon::Location::Serialize(Archive & rArchive) const
//
//
//
- if(!mpExcludeFiles)
+ if (!mpExcludeFiles)
{
int64_t aMagicMarker = ARCHIVE_MAGIC_VALUE_NOOP;
rArchive.Write(aMagicMarker);
@@ -2316,7 +2228,7 @@ void BackupDaemon::Location::Serialize(Archive & rArchive) const
//
//
//
- if(!mpExcludeDirs)
+ if (!mpExcludeDirs)
{
int64_t aMagicMarker = ARCHIVE_MAGIC_VALUE_NOOP;
rArchive.Write(aMagicMarker);
@@ -2385,7 +2297,7 @@ bool BackupDaemon::SerializeStoreObjectInfo(int64_t aClientStoreMarker, box_time
std::string StoreObjectInfoFile =
GetConfiguration().GetKeyValue("StoreObjectInfoFile");
- if(StoreObjectInfoFile.size() <= 0)
+ if (StoreObjectInfoFile.size() <= 0)
{
return false;
}
@@ -2414,7 +2326,7 @@ bool BackupDaemon::SerializeStoreObjectInfo(int64_t aClientStoreMarker, box_time
int64_t iCount = mLocations.size();
anArchive.Write(iCount);
- for(int v = 0; v < iCount; v++)
+ for (int v = 0; v < iCount; v++)
{
ASSERT(mLocations[v]);
mLocations[v]->Serialize(anArchive);
@@ -2426,7 +2338,7 @@ bool BackupDaemon::SerializeStoreObjectInfo(int64_t aClientStoreMarker, box_time
iCount = mIDMapMounts.size();
anArchive.Write(iCount);
- for(int v = 0; v < iCount; v++)
+ for (int v = 0; v < iCount; v++)
anArchive.Write(mIDMapMounts[v]);
//
@@ -2479,7 +2391,7 @@ bool BackupDaemon::DeserializeStoreObjectInfo(int64_t & aClientStoreMarker, box_
std::string StoreObjectInfoFile =
GetConfiguration().GetKeyValue("StoreObjectInfoFile");
- if(StoreObjectInfoFile.size() <= 0)
+ if (StoreObjectInfoFile.size() <= 0)
{
return false;
}
@@ -2495,7 +2407,7 @@ bool BackupDaemon::DeserializeStoreObjectInfo(int64_t & aClientStoreMarker, box_
int iMagicValue = 0;
anArchive.Read(iMagicValue);
- if(iMagicValue != STOREOBJECTINFO_MAGIC_ID_VALUE)
+ if (iMagicValue != STOREOBJECTINFO_MAGIC_ID_VALUE)
{
::syslog(LOG_WARNING, "Store object info file '%s' "
"is not a valid or compatible serialised "
@@ -2510,7 +2422,7 @@ bool BackupDaemon::DeserializeStoreObjectInfo(int64_t & aClientStoreMarker, box_
std::string strMagicValue;
anArchive.Read(strMagicValue);
- if(strMagicValue != STOREOBJECTINFO_MAGIC_ID_STRING)
+ if (strMagicValue != STOREOBJECTINFO_MAGIC_ID_STRING)
{
::syslog(LOG_WARNING, "Store object info file '%s' "
"is not a valid or compatible serialised "
@@ -2526,7 +2438,7 @@ bool BackupDaemon::DeserializeStoreObjectInfo(int64_t & aClientStoreMarker, box_
int iVersion = 0;
anArchive.Read(iVersion);
- if(iVersion != STOREOBJECTINFO_VERSION)
+ if (iVersion != STOREOBJECTINFO_VERSION)
{
::syslog(LOG_WARNING, "Store object info file '%s' "
"version %d unsupported. "
@@ -2543,7 +2455,7 @@ bool BackupDaemon::DeserializeStoreObjectInfo(int64_t & aClientStoreMarker, box_
box_time_t lastKnownConfigModTime;
anArchive.Read(lastKnownConfigModTime);
- if(lastKnownConfigModTime != GetLoadedConfigModifiedTime())
+ if (lastKnownConfigModTime != GetLoadedConfigModifiedTime())
{
::syslog(LOG_WARNING, "Store object info file '%s' "
"out of date. Will re-cache from store",
@@ -2564,13 +2476,11 @@ bool BackupDaemon::DeserializeStoreObjectInfo(int64_t & aClientStoreMarker, box_
int64_t iCount = 0;
anArchive.Read(iCount);
- for(int v = 0; v < iCount; v++)
+ for (int v = 0; v < iCount; v++)
{
Location* pLocation = new Location;
- if(!pLocation)
- {
+ if (!pLocation)
throw std::bad_alloc();
- }
pLocation->Deserialize(anArchive);
mLocations.push_back(pLocation);
@@ -2582,7 +2492,7 @@ bool BackupDaemon::DeserializeStoreObjectInfo(int64_t & aClientStoreMarker, box_
iCount = 0;
anArchive.Read(iCount);
- for(int v = 0; v < iCount; v++)
+ for (int v = 0; v < iCount; v++)
{
std::string strItem;
anArchive.Read(strItem);