[mapguide-commits] r4403 - in trunk/MgDev:
Common/MapGuideCommon/Services Common/MapGuideCommon/System
Server/src/Core
svn_mapguide at osgeo.org
svn_mapguide at osgeo.org
Wed Dec 9 16:13:55 EST 2009
Author: brucedechant
Date: 2009-12-09 16:13:53 -0500 (Wed, 09 Dec 2009)
New Revision: 4403
Modified:
trunk/MgDev/Common/MapGuideCommon/Services/Command.cpp
trunk/MgDev/Common/MapGuideCommon/Services/ServerConnection.cpp
trunk/MgDev/Common/MapGuideCommon/Services/ServerConnection.h
trunk/MgDev/Common/MapGuideCommon/Services/SiteConnection.cpp
trunk/MgDev/Common/MapGuideCommon/Services/SiteManager.cpp
trunk/MgDev/Common/MapGuideCommon/Services/SiteManager.h
trunk/MgDev/Common/MapGuideCommon/System/ConfigProperties.cpp
trunk/MgDev/Common/MapGuideCommon/System/ConfigProperties.h
trunk/MgDev/Server/src/Core/serverconfig.ini
Log:
Fix for trac ticket 1131 - Load balancing doesn't support fail over
http://trac.osgeo.org/mapguide/ticket/1131
Notes:
- Updated load balancing algorithm to remove failed servers and periodically add them back in when they are up and running again
Modified: trunk/MgDev/Common/MapGuideCommon/Services/Command.cpp
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/Services/Command.cpp 2009-12-09 21:05:09 UTC (rev 4402)
+++ trunk/MgDev/Common/MapGuideCommon/Services/Command.cpp 2009-12-09 21:13:53 UTC (rev 4403)
@@ -34,6 +34,8 @@
//TODO: Parse url and pull machine name into target
}
+ MG_TRY()
+
Ptr<MgUserInformation> userInfo = connProp->GetUserInfo();
Ptr<MgServerConnection> serviceConn = MgServerConnection::Acquire(userInfo, connProp);
Ptr<MgStream> stream = serviceConn->GetStream();
@@ -114,6 +116,29 @@
stream->WriteStreamEnd();
GetResponse(serviceConn, retType);
+
+ MG_CATCH(L"MgCommand.ExecuteCommand")
+
+ if (NULL != mgException)
+ {
+ if (mgException->IsOfClass(MapGuide_Exception_MgConnectionFailedException))
+ {
+ // The server didn't respond so it needs to be marked as unavailable in the list of servers.
+ // We will check to see if it can be made available later.
+ MgSiteManager* siteManager = MgSiteManager::GetInstance();
+ Ptr<MgSiteInfo> badSite = siteManager->GetSiteInfo(connProp->GetTarget(), connProp->GetPort());
+ if(NULL != badSite.p)
+ {
+ // Update the status of the failed server
+ badSite->SetStatus(MgSiteInfo::UnableToConnect);
+ }
+
+ // Need to remove the server connection from the pool
+ MgServerConnection::Remove(connProp);
+ }
+
+ MG_THROW();
+ }
}
//////////////////////////////////////////////////////////////////
Modified: trunk/MgDev/Common/MapGuideCommon/Services/ServerConnection.cpp
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/Services/ServerConnection.cpp 2009-12-09 21:05:09 UTC (rev 4402)
+++ trunk/MgDev/Common/MapGuideCommon/Services/ServerConnection.cpp 2009-12-09 21:13:53 UTC (rev 4403)
@@ -275,10 +275,10 @@
/// </summary>
///
/// <param name="userInformation">
-/// User information to authenticate against
+/// User information to authenticate against.
/// </param>
-/// <param name="target">
-/// Target server. NULL or "" indicates local server
+/// <param name="connProp">
+/// Connection properties for the server to connect to.
/// </param>
/// <returns>
/// Nothing
@@ -342,3 +342,28 @@
return msc.Detach();
}
+//////////////////////////////////////////////////////////////////
+/// <summary>
+/// Removes a connection to a Mg server
+/// </summary>
+///
+/// <param name="connProp">
+/// Connection properties of the server to remove.
+/// </param>
+/// <returns>
+/// Nothing
+/// </returns>
+/// EXCEPTIONS:
+/// AuthorizationFailed
+/// TargetNotFound
+void MgServerConnection::Remove(MgConnectionProperties* connProp)
+{
+ CHECKNULL((MgConnectionProperties*)connProp, L"MgServerConnection.Remove");
+
+ {
+ ACE_MT(ACE_GUARD(ACE_Recursive_Thread_Mutex, ace_mon, sm_mutex));
+
+ wstring hash = connProp->Hash();
+ g_connectionPool->pool.erase(hash);
+ }
+}
Modified: trunk/MgDev/Common/MapGuideCommon/Services/ServerConnection.h
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/Services/ServerConnection.h 2009-12-09 21:05:09 UTC (rev 4402)
+++ trunk/MgDev/Common/MapGuideCommon/Services/ServerConnection.h 2009-12-09 21:13:53 UTC (rev 4403)
@@ -105,6 +105,19 @@
//////////////////////////////////////////////////////////////////
/// \brief
+ /// Removes the TCP/IP connection to a MapGuide server from the
+ /// internal connection pool.
+ ///
+ /// \param connProp
+ /// Connection properties for target server
+ ///
+ /// \return
+ /// Nothing
+ ///
+ static void Remove(MgConnectionProperties* connProp);
+
+ //////////////////////////////////////////////////////////////////
+ /// \brief
/// Internal method used for getting stream helper
/// which will then be used in serialize/deserialize
///
Modified: trunk/MgDev/Common/MapGuideCommon/Services/SiteConnection.cpp
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/Services/SiteConnection.cpp 2009-12-09 21:05:09 UTC (rev 4402)
+++ trunk/MgDev/Common/MapGuideCommon/Services/SiteConnection.cpp 2009-12-09 21:13:53 UTC (rev 4403)
@@ -129,7 +129,8 @@
if (m_connProp == NULL)
{
- throw new MgLogicException(L"MgSiteConnection.Open",
+ // There might not be any MapGuide servers running for the site
+ throw new MgConnectionFailedException(L"MgSiteConnection.Open",
__LINE__, __WFILE__, NULL, L"", NULL);
}
Modified: trunk/MgDev/Common/MapGuideCommon/Services/SiteManager.cpp
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/Services/SiteManager.cpp 2009-12-09 21:05:09 UTC (rev 4402)
+++ trunk/MgDev/Common/MapGuideCommon/Services/SiteManager.cpp 2009-12-09 21:13:53 UTC (rev 4403)
@@ -19,6 +19,94 @@
// Process-wide MgSiteManager
Ptr<MgSiteManager> MgSiteManager::sm_siteManager = (MgSiteManager*)NULL;
+// Background thread function
+ACE_THR_FUNC_RETURN CheckServers(void* param)
+{
+ SMThreadData* threadData = (SMThreadData*)param;
+ // Store our unique thread ID
+ threadData->threadId = ACE_Thread::self();
+
+ MgSiteManager* siteManager = MgSiteManager::GetInstance();
+
+ bool bDone = false;
+ while(!bDone)
+ {
+ INT32 sleepTime = threadData->failoverRetryTime;
+
+ MgSiteVector* sites = siteManager->GetSites();
+ if(sites)
+ {
+ for(size_t i=0;i<sites->size();i++)
+ {
+ MgSiteInfo* siteInfo = sites->at(i);
+
+ // Check the server status
+ if (MgSiteInfo::Ok != siteInfo->GetStatus())
+ {
+ // This is an unavailable server so we need to check if it is now available
+ MG_TRY()
+
+ // Send a simple request to the server to see if it can respond
+ Ptr<MgUserInformation> userInformation = new MgUserInformation(L"", L"");
+ Ptr<MgConnectionProperties> connProp = siteManager->GetConnectionProperties(userInformation, siteInfo, MgSiteInfo::Admin);
+
+ // Use GetSiteStatus because it doesn't require authentication
+ MgCommand cmd;
+ cmd.ExecuteCommand(connProp, // Connection
+ MgCommand::knObject, // Return type expected
+ MgServerAdminServiceOpId::GetSiteStatus, // Command Code
+ 0, // No of arguments
+ ServerAdmin_Service, // Service Id
+ BUILD_VERSION(2,2,0), // Operation version
+ MgCommand::knNone);
+
+ // The server responded so update the status if the server is online
+ Ptr<MgPropertyCollection> properties = (MgPropertyCollection*)cmd.GetReturnValue().val.m_obj;
+ if(properties.p)
+ {
+ // Check the status of the server
+ Ptr<MgBooleanProperty> boolProp = (MgBooleanProperty*)properties->GetItem(MgServerInformationProperties::Status);
+ if(boolProp->GetValue())
+ {
+ // Server is there and "Online"
+ ACE_MT(ACE_GUARD_RETURN(ACE_Recursive_Thread_Mutex, ace_mon, siteManager->m_mutex, NULL));
+ siteInfo->SetStatus(MgSiteInfo::Ok);
+ }
+ }
+
+ MG_CATCH_AND_RELEASE()
+ if(NULL != mgException.p)
+ {
+ // Exception was thrown
+ STRING message = mgException->GetMessage();
+ }
+ }
+ }
+
+ // Does this site only contain 1 server?
+ if(sites->size() == 1)
+ {
+ MgSiteInfo* siteInfo = sites->at(0);
+
+ // Check the server status in case it was just updated
+ if (MgSiteInfo::Ok != siteInfo->GetStatus())
+ {
+ // There is only 1 server in the site and it is not in a "Good" state yet so reduce the sleep time
+ sleepTime = 1;
+ }
+ }
+ }
+
+ // Sleep the thread as thread resume/suspend is not supported on all platforms
+ ACE_OS::sleep(sleepTime);
+
+ // Update whether we are done or not
+ bDone = siteManager->GetCheckServersThreadDone();
+ }
+
+ return 0;
+}
+
///----------------------------------------------------------------------------
/// <summary>
/// Constructs the object.
@@ -43,6 +131,10 @@
ClearSiteInfo();
+ // Block any threads as we are updating the thread done
+ ACE_MT(ACE_GUARD(ACE_Recursive_Thread_Mutex, ace_mon, m_mutex));
+ m_bCheckServersThreadDone = true;
+
MG_CATCH(L"MgSiteManager.~MgSiteManager")
}
@@ -179,6 +271,24 @@
m_sites.push_back(siteInfo.Detach());
}
+ // Create background thread that will check any unavailable servers to see if their status has changed
+ INT32 failoverRetryTime = MgConfigProperties::DefaultGeneralPropertyFailoverRetryTime;
+ configuration->GetIntValue(
+ MgConfigProperties::GeneralPropertiesSection,
+ MgConfigProperties::GeneralPropertyFailoverRetryTime,
+ failoverRetryTime,
+ MgConfigProperties::DefaultGeneralPropertyFailoverRetryTime);
+
+ m_threadData.failoverRetryTime = failoverRetryTime;
+
+ m_bCheckServersThreadDone = false;
+
+ // Need a thread manager
+ ACE_Thread_Manager* manager = ACE_Thread_Manager::instance();
+
+ // Create the background thread
+ manager->spawn(ACE_THR_FUNC(CheckServers), &m_threadData);
+
MG_CATCH_AND_THROW(L"MgSiteManager.Initialize")
}
@@ -213,12 +323,19 @@
{
STRING siteHexString = sessionId.substr(
length - MgSiteInfo::HexStringLength, MgSiteInfo::HexStringLength);
- Ptr<MgSiteInfo> siteInfo = new MgSiteInfo(siteHexString);
+ Ptr<MgSiteInfo> siteInfo = GetSiteInfo(siteHexString);
if (MgSiteInfo::Ok == siteInfo->GetStatus())
{
connProps = GetConnectionProperties(userInfo, siteInfo, portType);
}
+ else
+ {
+ // This site is not currently working
+
+ // We have a session, but it will not exist on any other machine so we force the session exception
+ throw new MgSessionExpiredException(L"MgSiteManager.GetConnectionProperties",__LINE__,__WFILE__, NULL, L"", NULL);
+ }
}
}
else
@@ -233,7 +350,8 @@
if (NULL == connProps.p)
{
- throw new MgLogicException(
+ // There might not be any MapGuide servers running for the site
+ throw new MgConnectionFailedException(
L"MgSiteManager.GetConnectionProperties",
__LINE__, __WFILE__, NULL, L"", NULL);
}
@@ -371,3 +489,64 @@
return SAFE_ADDREF(matchingSiteInfo);
}
+
+///----------------------------------------------------------------------------
+/// <summary>
+/// Retrieves site info for the site server matching the specified target and port
+/// contained within the specifed hex string.
+/// </summary>
+///----------------------------------------------------------------------------
+MgSiteInfo* MgSiteManager::GetSiteInfo(CREFSTRING hexString)
+{
+ MgSiteInfo* matchingSiteInfo = NULL;
+
+ if(hexString.length() >= MgSiteInfo::HexStringLength)
+ {
+ UINT32 n1, n2, n3, n4;
+ INT32 sitePort, clientPort, adminPort;
+ STRING target;
+
+ // Read the IP parts into their variables
+ if(::swscanf(hexString.c_str(), L"%2X%2X%2X%2X%4X%4X%4X", &n1, &n2, &n3, &n4, &sitePort, &clientPort, &adminPort) == 7)
+ {
+ // Write the 4 'n' values into an IP string
+ wchar_t buffer[20];
+ swprintf(buffer, 20, L"%u.%u.%u.%u", n1, n2, n3, n4);
+ target = buffer;
+ }
+
+ ACE_MT(ACE_GUARD_RETURN(ACE_Recursive_Thread_Mutex, ace_mon, m_mutex, NULL));
+
+ for (INT32 i = 0; i < (INT32)m_sites.size(); i++)
+ {
+ MgSiteInfo* siteInfo = m_sites.at(i);
+
+ if (siteInfo->GetTarget() == target
+ && (siteInfo->GetPort(MgSiteInfo::Site) == sitePort ||
+ siteInfo->GetPort(MgSiteInfo::Client) == clientPort ||
+ siteInfo->GetPort(MgSiteInfo::Admin) == adminPort))
+ {
+ matchingSiteInfo = siteInfo;
+ break;
+ }
+ }
+ }
+
+ return SAFE_ADDREF(matchingSiteInfo);
+}
+
+MgSiteVector* MgSiteManager::GetSites()
+{
+ return &m_sites;
+}
+
+bool MgSiteManager::GetCheckServersThreadDone()
+{
+ return m_bCheckServersThreadDone;
+}
+
+void MgSiteManager::SetCheckServersThreadDone(bool bDone)
+{
+ ACE_MT(ACE_GUARD(ACE_Recursive_Thread_Mutex, ace_mon, m_mutex));
+ m_bCheckServersThreadDone = bDone;
+}
Modified: trunk/MgDev/Common/MapGuideCommon/Services/SiteManager.h
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/Services/SiteManager.h 2009-12-09 21:05:09 UTC (rev 4402)
+++ trunk/MgDev/Common/MapGuideCommon/Services/SiteManager.h 2009-12-09 21:13:53 UTC (rev 4403)
@@ -21,6 +21,13 @@
class MgSiteInfo;
typedef std::vector<MgSiteInfo*> MgSiteVector;
+// Data structure which is passed to thread
+struct SMThreadData
+{
+ ACE_thread_t threadId;
+ INT32 failoverRetryTime;
+};
+
class MG_MAPGUIDE_API MgSiteManager : public MgGuardDisposable
{
DECLARE_CLASSNAME(MgSiteManager)
@@ -63,9 +70,16 @@
MgSiteInfo* GetSiteInfo(INT32 index);
MgSiteInfo* GetSiteInfo(CREFSTRING target, INT32 port);
+ MgSiteInfo* GetSiteInfo(CREFSTRING hexString);
INT32 GetSiteCount();
+ MgSiteVector* GetSites();
+ ACE_Recursive_Thread_Mutex m_mutex;
+
+ bool GetCheckServersThreadDone();
+ void SetCheckServersThreadDone(bool bDone);
+
private:
void Initialize();
@@ -79,9 +93,10 @@
static Ptr<MgSiteManager> sm_siteManager;
- ACE_Recursive_Thread_Mutex m_mutex;
INT32 m_index;
MgSiteVector m_sites;
+ SMThreadData m_threadData;
+ bool m_bCheckServersThreadDone;
};
#endif // MG_SITEMANAGER_H_
Modified: trunk/MgDev/Common/MapGuideCommon/System/ConfigProperties.cpp
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/System/ConfigProperties.cpp 2009-12-09 21:05:09 UTC (rev 4402)
+++ trunk/MgDev/Common/MapGuideCommon/System/ConfigProperties.cpp 2009-12-09 21:13:53 UTC (rev 4403)
@@ -161,6 +161,8 @@
const INT32 MgConfigProperties::DefaultGeneralPropertyWorkerThreadPoolSize = 1;
const STRING MgConfigProperties::GeneralPropertyRenderer = L"Renderer";
const STRING MgConfigProperties::DefaultGeneralPropertyRenderer = L"GD";
+const STRING MgConfigProperties::GeneralPropertyFailoverRetryTime = L"FailoverRetryTime"; // for internal use only
+const INT32 MgConfigProperties::DefaultGeneralPropertyFailoverRetryTime = 60;
// ******************************************************************
// Administrative Connection Properties
@@ -505,6 +507,7 @@
{ MgConfigProperties::GeneralPropertyWfsDocumentPath , MgPropertyType::String , MG_CONFIG_MIN_PATH_LENGTH , MG_CONFIG_MAX_PATH_LENGTH , MG_CONFIG_PATH_RESERVED_CHARACTERS },
{ MgConfigProperties::GeneralPropertyWmsDocumentPath , MgPropertyType::String , MG_CONFIG_MIN_PATH_LENGTH , MG_CONFIG_MAX_PATH_LENGTH , MG_CONFIG_PATH_RESERVED_CHARACTERS },
{ MgConfigProperties::GeneralPropertyWorkerThreadPoolSize , MgPropertyType::Int32 , MG_CONFIG_MIN_THREAD_POOL_SIZE , MG_CONFIG_MAX_THREAD_POOL_SIZE , L"" },
+ { MgConfigProperties::GeneralPropertyFailoverRetryTime , MgPropertyType::Int32 , MG_CONFIG_MIN_TIMER_INTERVAL , MG_CONFIG_MAX_TIMER_INTERVAL , L"" },
{ L"" , 0 , 0.0 , 0.0 , L"" }
};
Modified: trunk/MgDev/Common/MapGuideCommon/System/ConfigProperties.h
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/System/ConfigProperties.h 2009-12-09 21:05:09 UTC (rev 4402)
+++ trunk/MgDev/Common/MapGuideCommon/System/ConfigProperties.h 2009-12-09 21:13:53 UTC (rev 4403)
@@ -135,6 +135,10 @@
static const STRING GeneralPropertyWorkerThreadPoolSize; /// value("WorkerThreadPoolSize")
static const INT32 DefaultGeneralPropertyWorkerThreadPoolSize; /// value(1)
+ /// Sets the failover retry time
+ static const STRING GeneralPropertyFailoverRetryTime; /// value("FailoverRetryTime")
+ static const INT32 DefaultGeneralPropertyFailoverRetryTime; /// value(60)
+
EXTERNAL_API:
/// ADMINISTRATIVE CONNECTION PROPERTIES SECTION ---------------------------------------------------------------------
Modified: trunk/MgDev/Server/src/Core/serverconfig.ini
===================================================================
--- trunk/MgDev/Server/src/Core/serverconfig.ini 2009-12-09 21:05:09 UTC (rev 4402)
+++ trunk/MgDev/Server/src/Core/serverconfig.ini 2009-12-09 21:13:53 UTC (rev 4403)
@@ -1,4 +1,4 @@
-# *****************************************************************************
+# *****************************************************************************
# MapGuide Server Configuration File
#
# The following configuration is based on a single CPU with a single core.
@@ -83,6 +83,7 @@
ConnectionTimerInterval = 60
DefaultMessageLocale = en
DisplayName =
+FailoverRetryTime = 60
FdoPath = FDO/
LicenseServerPath = @localhost
Locale =
More information about the mapguide-commits
mailing list