[Box Backup-dev] COMMIT r744 - box/chris/merge/bin/bbackupd

boxbackup-dev@fluffy.co.uk boxbackup-dev@fluffy.co.uk
Wed, 9 Aug 2006 17:53:35 +0000 (GMT)


Author: chris
Date: 2006-08-09 17:53:34 +0000 (Wed, 09 Aug 2006)
New Revision: 744

Modified:
   box/chris/merge/bin/bbackupd/BackupDaemon.cpp
Log:
* bin/bbackupd/BackupDaemon.cpp
- Reverted to trunk


Modified: box/chris/merge/bin/bbackupd/BackupDaemon.cpp
===================================================================
--- box/chris/merge/bin/bbackupd/BackupDaemon.cpp	2006-08-09 17:51:00 UTC (rev 743)
+++ box/chris/merge/bin/bbackupd/BackupDaemon.cpp	2006-08-09 17:53:34 UTC (rev 744)
@@ -125,29 +125,6 @@
 	}
 
 #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,35 +263,16 @@
 void BackupDaemon::RunHelperThread(void)
 {
 	mpCommandSocketInfo = new CommandSocketInfo;
-	WinNamedPipeStream& rSocket(mpCommandSocketInfo->mListeningSocket);
+	this->mReceivedCommandConn = false;
 
 	// loop until the parent process exits
-	while (!IsTerminateWanted())
+	while (TRUE)
 	{
 		try
 		{
-			rSocket.Accept(BOX_NAMED_PIPE_NAME);
-		}
-		catch (BoxException &e)
-		{
-			::syslog(LOG_ERR, "Failed to open command socket: %s",
-				e.what());
-			SetTerminateWanted();
-			break; // this is fatal
-		}
-		catch (...)
-		{
-			::syslog(LOG_ERR, "Failed to open command socket: "
-				"unknown error");
-			SetTerminateWanted();
-			break; // this is fatal
-		}
+			mpCommandSocketInfo->mListeningSocket.Accept(
+				BOX_NAMED_PIPE_NAME);
 
-		try
-		{
-			// Errors here do not kill the thread,
-			// only the current connection.
-
 			// This next section comes from Ben's original function
 			// Log
 			::syslog(LOG_INFO, "Connection from command socket");
@@ -331,73 +289,18 @@
 				conf.GetKeyValueInt("MaxUploadWait"),
 				mState);
 
-			rSocket.Write(summary, summarySize);
-			rSocket.Write("ping\n", 5);
+			mpCommandSocketInfo->mListeningSocket.Write(summary, summarySize);
+			mpCommandSocketInfo->mListeningSocket.Write("ping\n", 5);
 
-			// old queued messages are not useful
-			EnterCriticalSection(&mMessageQueueLock);
-			mMessageList.clear();
-			ResetEvent(mhMessageToSendEvent);
-			LeaveCriticalSection(&mMessageQueueLock);
-
-			IOStreamGetLine readLine(rSocket);
+			IOStreamGetLine readLine(mpCommandSocketInfo->mListeningSocket);
 			std::string command;
 
-			while (rSocket.IsConnected() && !IsTerminateWanted())
+			while (mpCommandSocketInfo->mListeningSocket.IsConnected() &&
+			       readLine.GetLine(command) )
 			{
-				HANDLE handles[2];
-				handles[0] = mhMessageToSendEvent;
-				handles[1] = rSocket.GetReadableEvent();
+				TRACE1("Receiving command '%s' over "
+					"command socket\n", command.c_str());
 
-				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());
-
 				bool sendOK = false;
 				bool sendResponse = true;
 				bool disconnect = false;
@@ -435,18 +338,12 @@
 					SetTerminateWanted();
 					sendOK = true;
 				}
-				else
-				{
-					::syslog(LOG_ERR, "Received unknown command '%s' from client", command.c_str());
-					sendResponse = true;
-					sendOK = false;
-				}
 
 				// Send a response back?
 				if (sendResponse)
 				{
 					const char* response = sendOK ? "ok\n" : "error\n";
-					rSocket.Write(
+					mpCommandSocketInfo->mListeningSocket.Write(
 						response, strlen(response));
 				}
 
@@ -455,10 +352,10 @@
 					break;
 				}
 
-				// this->mReceivedCommandConn = true;
+				this->mReceivedCommandConn = true;
 			}
 
-			rSocket.Close();
+			mpCommandSocketInfo->mListeningSocket.Close();
 		}
 		catch (BoxException &e)
 		{
@@ -607,8 +504,8 @@
 		BackupClientContext::ClientStoreMarker_NotKnown;
 	// haven't contacted the store yet
 
- 	bool deleteStoreObjectInfoFile = DeserializeStoreObjectInfo(
-		clientStoreMarker, lastSyncTime, nextSyncTime);
+ 	bool deserialised = DeserializeStoreObjectInfo(clientStoreMarker, 
+		lastSyncTime, nextSyncTime);
  
 	// --------------------------------------------------------------------------------------------
 	
@@ -714,8 +611,7 @@
 			// Delete the serialised store object file,
 			// so that we don't try to reload it after a
 			// partially completed backup
-			if(deleteStoreObjectInfoFile && 
-				!DeleteStoreObjectInfo())
+			if(deserialised && !DeleteStoreObjectInfo())
 			{
 				::syslog(LOG_ERR, "Failed to delete the "
 					"StoreObjectInfoFile, backup cannot "
@@ -725,11 +621,6 @@
 				::sleep(60); 
 				continue;
 			}
-
-			// In case the backup throws an exception,
-			// we should not try to delete the store info
-			// object file again.
-			deleteStoreObjectInfoFile = false;
 			
 			// Do sync
 			bool errorOccurred = false;
@@ -838,15 +729,9 @@
 
 				// --------------------------------------------------------------------------------------------
 
-				// We had a successful backup, save the store 
-				// info. If we save successfully, we must 
-				// delete the file next time we start a backup
+				// We had a successful backup, save the store info
+				SerializeStoreObjectInfo(clientStoreMarker, lastSyncTime, nextSyncTime);
 
-				deleteStoreObjectInfoFile = 
-					SerializeStoreObjectInfo(
-						clientStoreMarker, 
-						lastSyncTime, nextSyncTime);
-
 				// --------------------------------------------------------------------------------------------
 			}
 			catch(BoxException &e)
@@ -1017,27 +902,25 @@
 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)
+	while ( this->mReceivedCommandConn == false )
 	{
-		DoSyncFlagOut = this->mDoSyncFlagOut;
-		SyncIsForcedOut = this->mSyncIsForcedOut;
-		ResetEvent(mhCommandReceivedEvent);
+		Sleep(1);
+
+		if ( timeout == 0 )
+		{
+			DoSyncFlagOut = false;
+			SyncIsForcedOut = false;
+			return;
+		}
+		timeout--;
 	}
-	else if (result == WAIT_TIMEOUT)
-	{
-		DoSyncFlagOut = false;
-		SyncIsForcedOut = false;
-	}
-	else
-	{
-		::syslog(LOG_ERR, "Unexpected result from "
-			"WaitForSingleObject: error %d", GetLastError());
-	}
+	this->mReceivedCommandConn = false;
+	DoSyncFlagOut = this->mDoSyncFlagOut;
+	SyncIsForcedOut = this->mSyncIsForcedOut;
 
 	return;
 #else // ! WIN32
@@ -1070,7 +953,7 @@
 			{
 #ifdef PLATFORM_CANNOT_FIND_PEER_UID_OF_UNIX_SOCKET
 				bool uidOK = true;
-				::syslog(LOG_WARNING, "On this platform, no security check can be made on the credentials of peers connecting to the command socket. (bbackupctl)");
+				::syslog(LOG_WARNING, "On this platform, no security check can be made on the credientials of peers connecting to the command socket. (bbackupctl)");
 #else
 				// Security check -- does the process connecting to this socket have
 				// the same UID as this process?
@@ -1140,13 +1023,8 @@
 		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());
-
-			#ifdef WIN32
-			SetEvent(mhCommandReceivedEvent);
-			#endif
-
+			TRACE1("Receiving command '%s' over command socket\n", command.c_str());
+			
 			bool sendOK = false;
 			bool sendResponse = true;
 		
@@ -1259,9 +1137,13 @@
 // --------------------------------------------------------------------------
 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.
+	// The bbackupctl program can't rely on a state change, because it may never
+	// change if the server doesn't need to be contacted.
 
+#ifdef __MINGW32__
+#warning race condition: what happens if socket is closed?
+#endif
+
 	if (mpCommandSocketInfo != NULL &&
 #ifdef WIN32
 	    mpCommandSocketInfo->mListeningSocket.IsConnected()
@@ -1270,18 +1152,15 @@
 #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(...)
@@ -1877,37 +1756,40 @@
 	// 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";
+	#ifndef _MSC_VER
+		#warning FIX ME: race condition
+	#endif
 
-	if(mpCommandSocketInfo == 0)
+	// 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())
 	{
-		return;
+		try
+		{
+			mpCommandSocketInfo->mListeningSocket.Write(newState, newStateSize);
+		}
+		catch(...)
+		{
+			CloseCommandConnection();
+		}
 	}
-
-	if (mpCommandSocketInfo->mpConnectedSocket.get() == 0)
+#else
+	if(mpCommandSocketInfo != 0 && mpCommandSocketInfo->mpConnectedSocket.get() != 0)
 	{
-		return;
+		// Something connected to the command socket, tell it about the new state
+		try
+		{
+			mpCommandSocketInfo->mpConnectedSocket->Write(newState, newStateSize);
+		}
+		catch(...)
+		{
+			CloseCommandConnection();
+		}
 	}
-
-	// Something connected to the command socket, tell it about the new state
-	try
-	{
-		mpCommandSocketInfo->mpConnectedSocket->Write(message.c_str(),
-			message.length());
-	}
-	catch(...)
-	{
-		CloseCommandConnection();
-	}
 #endif
 }
 
@@ -2291,11 +2173,11 @@
 static const std::string STOREOBJECTINFO_MAGIC_ID_STRING = "BBACKUPD-STATE";
 static const int STOREOBJECTINFO_VERSION = 1;
 
-bool BackupDaemon::SerializeStoreObjectInfo(int64_t aClientStoreMarker, box_time_t theLastSyncTime, box_time_t theNextSyncTime) const
+void BackupDaemon::SerializeStoreObjectInfo(int64_t aClientStoreMarker, box_time_t theLastSyncTime, box_time_t theNextSyncTime) const
 {
 	if(!GetConfiguration().KeyExists("StoreObjectInfoFile"))
 	{
-		return false;
+		return;
 	}
 
 	std::string StoreObjectInfoFile = 
@@ -2303,17 +2185,13 @@
 
 	if (StoreObjectInfoFile.size() <= 0)
 	{
-		return false;
+		return;
 	}
 
-	bool created = false;
-
 	try
 	{
 		FileStream aFile(StoreObjectInfoFile.c_str(), 
 			O_WRONLY | O_CREAT | O_TRUNC);
-		created = true;
-
 		Archive anArchive(aFile, 0);
 
 		anArchive.Write(STOREOBJECTINFO_MAGIC_ID_VALUE);
@@ -2358,8 +2236,6 @@
 			"not accessible or could not be created", 
 			StoreObjectInfoFile.c_str());
 	}
-
-	return created;
 }
 
 // --------------------------------------------------------------------------