FTM.cpp revision dcc57944afcf23c538ec2147f0381e0688168a82
/* $Id$ */
/** @file
* FTM - Fault Tolerance Manager
*/
/*
* Copyright (C) 2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#define LOG_GROUP LOG_GROUP_FTM
#include "FTMInternal.h"
#include <iprt/semaphore.h>
/*******************************************************************************
* Global Variables *
*******************************************************************************/
static const char g_szWelcome[] = "VirtualBox-Fault-Tolerance-Sync-1.0\n";
/**
* Initializes the FTM.
*
* @returns VBox status code.
* @param pVM The VM to operate on.
*/
{
/*
* Assert alignment and sizes.
*/
/** @todo saved state for master nodes! */
pVM->fFaultTolerantMaster = false;
/*
* Initialize the PGM critical section.
*/
STAM_REL_REG(pVM, &pVM->ftm.s.StatReceivedMem, STAMTYPE_COUNTER, "/FT/Received/Mem", STAMUNIT_BYTES, "The amount of memory pages that was received.");
STAM_REL_REG(pVM, &pVM->ftm.s.StatReceivedState, STAMTYPE_COUNTER, "/FT/Received/State", STAMUNIT_BYTES, "The amount of state information that was received.");
STAM_REL_REG(pVM, &pVM->ftm.s.StatSentMem, STAMTYPE_COUNTER, "/FT/Sent/Mem", STAMUNIT_BYTES, "The amount of memory pages that was sent.");
STAM_REL_REG(pVM, &pVM->ftm.s.StatSentState, STAMTYPE_COUNTER, "/FT/Sent/State", STAMUNIT_BYTES, "The amount of state information that was sent.");
return VINF_SUCCESS;
}
/**
* Terminates the FTM.
*
* Termination means cleaning up and freeing all resources,
* the VM itself is at this point powered off or suspended.
*
* @returns VBox status code.
* @param pVM The VM to operate on.
*/
{
return VINF_SUCCESS;
}
{
if (RT_FAILURE(rc))
{
}
return rc;
}
{
char szMsg[256];
if (pszMsgText && *pszMsgText)
{
}
else
if (RT_FAILURE(rc))
return rc;
}
/**
* Reads a string from the socket.
*
* @returns VBox status code.
*
* @param pState The teleporter state structure.
* @param pszBuf The output buffer.
* @param cchBuf The size of the output buffer.
*
*/
{
*pszBuf = '\0';
/* dead simple approach. */
for (;;)
{
char ch;
if (RT_FAILURE(rc))
{
return rc;
}
if ( ch == '\n'
|| ch == '\0')
return VINF_SUCCESS;
if (cchBuf <= 1)
{
return VERR_BUFFER_OVERFLOW;
}
*pszBuf = '\0';
cchBuf--;
}
}
/**
* Reads an ACK or NACK.
*
* @returns VBox status code.
* @param pVM The VM to operate on.
* @param pszWhich Which ACK is this this?
* @param pszNAckMsg Optional NACK message.
*/
{
char szMsg[256];
if (RT_FAILURE(rc))
return rc;
return VINF_SUCCESS;
{
if (pszMsgText)
*pszMsgText++ = '\0';
if (rc == VINF_SUCCESS)
{
/*
* Well formed NACK, transform it into an error.
*/
if (pszNAckMsg)
{
return VERR_INTERNAL_ERROR;
}
if (pszMsgText)
{
}
return VERR_INTERNAL_ERROR_2;
}
if (pszMsgText)
}
return VERR_INTERNAL_ERROR_3;
}
/**
* Thread function which starts syncing process for this master VM
*
* @param Thread The thread id.
* @param pvUser Not used
* @return VINF_SUCCESS (ignored).
*
* @note Locks the Console object for writing.
*/
{
int rc = VINF_SUCCESS;
for (;;)
{
/*
* Try connect to the standby machine.
*/
if (RT_SUCCESS(rc))
{
/* Disable Nagle. */
/* Read and check the welcome message. */
if ( RT_SUCCESS(rc)
{
/* password */
if (RT_SUCCESS(rc))
{
/* ACK */
if (RT_SUCCESS(rc))
{
/** todo: verify VM config. */
break;
}
}
}
}
if (rc != VERR_TIMEOUT)
return VINF_SUCCESS; /* told to quit */
}
/* Successfully initialized the connection to the standby node.
* Start the sync process.
*/
for (;;)
{
{
/* sync the changed memory with the standby node. */
}
if (rc != VERR_TIMEOUT)
break; /* told to quit */
}
return rc;
}
/**
* Listen for incoming traffic destined for the standby VM.
*
* @copydoc FNRTTCPSERVE
*
* @returns VINF_SUCCESS or VERR_TCP_SERVER_STOP.
*/
{
/*
* Disable Nagle.
*/
/* Send the welcome message to the master node. */
if (RT_FAILURE(rc))
{
return VINF_SUCCESS;
}
/*
* Password.
*/
unsigned off = 0;
while (pszPassword[off])
{
char ch;
if ( RT_FAILURE(rc)
{
if (RT_FAILURE(rc))
else
return VINF_SUCCESS;
}
off++;
}
if (RT_FAILURE(rc))
return VINF_SUCCESS;
/** todo: verify VM config. */
/*
* Stop the server.
*
* Note! After this point we must return VERR_TCP_SERVER_STOP, while prior
* to it we must not return that value!
*/
/*
* Command processing loop.
*/
bool fDone = false;
for (;;)
{
char szCmd[128];
if (RT_FAILURE(rc))
break;
{
}
else
{
}
else
{
}
if (RT_FAILURE(rc))
break;
}
return VERR_TCP_SERVER_STOP;
}
/**
* Powers on the fault tolerant virtual machine.
*
* @returns VBox status code.
*
* @param pVM The VM to operate on.
* @param fMaster FT master or standby
* @param uInterval FT sync interval
* @param pszAddress Standby VM address
* @param uPort Standby VM port
* @param pszPassword FT password (NULL for none)
*
* @thread Any thread.
* @vmstate Created
* @vmstateto PoweringOn+Running (master), PoweringOn+Running_FT (standby)
*/
VMMR3DECL(int) FTMR3PowerOn(PVM pVM, bool fMaster, unsigned uInterval, const char *pszAddress, unsigned uPort, const char *pszPassword)
{
int rc = VINF_SUCCESS;
else
if (pszPassword)
if (fMaster)
{
if (RT_FAILURE(rc))
return rc;
if (RT_FAILURE(rc))
return rc;
pVM->fFaultTolerantMaster = true;
return VMR3PowerOn(pVM);
}
else
{
/* standby */
if (RT_FAILURE(rc))
return rc;
/** @todo deal with the exit code to check if we should activate this standby VM. */
}
return rc;
}
/**
* Powers off the fault tolerant virtual machine (standby).
*
* @returns VBox status code.
*
* @param pVM The VM to operate on.
*/
{
}
/**
* Performs a full sync to the standby node
*
* @returns VBox status code.
*
* @param pVM The VM to operate on.
*/
{
if (!pVM->fFaultTolerantMaster)
return VINF_SUCCESS;
return VERR_NOT_IMPLEMENTED;
}