[Mapguide_dev] svn commit: r1040 - RFC3 Session Affinity

Chris Claydon chris.claydon at autodesk.com
Thu Jan 11 10:38:53 EST 2007


Revision: 1040
Author: chrisclaydon
Date: 8:55:32 AM, January 11, 2007
Message:
RFC3 - Session Affinity
----
Modified :
/trunk/MgDev/Common/MapGuideCommon/Controller/DwfController.cpp
Modified : /trunk/MgDev/Common/MapGuideCommon/Makefile.am
Modified : /trunk/MgDev/Common/MapGuideCommon/MapGuideCommon.h
Modified : /trunk/MgDev/Common/MapGuideCommon/MapGuideCommon.vcproj
Modified : /trunk/MgDev/Common/MapGuideCommon/MapGuideCommonBuild.cpp
Modified : /trunk/MgDev/Common/MapGuideCommon/Services/ServerAdmin.cpp
Modified : /trunk/MgDev/Common/MapGuideCommon/Services/ServerAdmin.h
Modified :
/trunk/MgDev/Common/MapGuideCommon/Services/ServerConnection.cpp
Modified : /trunk/MgDev/Common/MapGuideCommon/Services/Site.cpp
Modified : /trunk/MgDev/Common/MapGuideCommon/Services/Site.h
Modified :
/trunk/MgDev/Common/MapGuideCommon/Services/SiteConnection.cpp
Added : /trunk/MgDev/Common/MapGuideCommon/Services/SiteInfo.cpp
Added : /trunk/MgDev/Common/MapGuideCommon/Services/SiteInfo.h
Added : /trunk/MgDev/Common/MapGuideCommon/Services/SiteManager.cpp
Added : /trunk/MgDev/Common/MapGuideCommon/Services/SiteManager.h
Modified :
/trunk/MgDev/Common/MapGuideCommon/System/MapGuideCommonClassId.h
Modified :
/trunk/MgDev/Common/MapGuideCommon/System/MapGuideCommonFactory.cpp
Modified : /trunk/MgDev/Common/MapGuideCommon/System/UserInformation.cpp
Modified : /trunk/MgDev/Common/MapGuideCommon/System/UserInformation.h
Modified : /trunk/MgDev/Server/src/Common/Manager/SessionCache.cpp
Modified : /trunk/MgDev/Server/src/Services/Site/ServerSiteService.cpp
Modified : /trunk/MgDev/Server/src/UnitTesting/Makefile.am
Added : /trunk/MgDev/Server/src/UnitTesting/TestSiteManager.cpp
Added : /trunk/MgDev/Server/src/UnitTesting/TestSiteManager.h
Modified : /trunk/MgDev/Server/src/UnitTesting/UnitTesting.cpp
Modified : /trunk/MgDev/Server/src/UnitTesting/UnitTesting.vcproj
Modified : /trunk/MgDev/Web/src/HttpHandler/HttpGetSiteInfo.cpp
Modified : /trunk/MgDev/Web/src/HttpHandler/HttpGetSiteVersion.cpp
Modified : /trunk/MgDev/Web/src/HttpHandler/HttpWmsGetCapabilities.cpp
Modified : /trunk/MgDev/Web/src/HttpHandler/WmsMapUtil.cpp
Modified : /trunk/MgDev/Web/src/MapGuideApi/MapGuideApiGen.xml
Modified : /trunk/MgDev/Web/src/mapadmin/about.php
Modified : /trunk/MgDev/Web/src/mapadmin/displaypackagelog.php
Modified : /trunk/MgDev/Web/src/mapadmin/loadpackage.php
Modified : /trunk/MgDev/Web/src/mapadmin/login.php
Modified : /trunk/MgDev/Web/src/mapadmin/makepackage.php
Modified : /trunk/MgDev/Web/src/mapadmin/packagemanagement.php
Modified : /trunk/MgDev/Web/src/mapadmin/resizablepagecomponents.php
Modified : /trunk/MgDev/Web/src/mapadmin/serverdatafunctions.php
Modified : /trunk/MgDev/Web/src/mapadmin/servermanagement.php
Modified : /trunk/MgDev/Web/src/mapadmin/serverproperties.php
Modified : /trunk/MgDev/Web/src/mapadmin/servicesproperties.php

Index: Common/MapGuideCommon/Services/SiteManager.h
===================================================================
--- Common/MapGuideCommon/Services/SiteManager.h	(revision 0)
+++ Common/MapGuideCommon/Services/SiteManager.h	(revision 1040)
@@ -0,0 +1,78 @@
+//
+//  Copyright (C) 2004-2006  Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software
Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301  USA
+//
+#include "MapGuideCommon.h"
+
+#ifndef MG_SITEMANAGER_H_
+#define MG_SITEMANAGER_H_
+
+class MgSiteInfo;
+typedef std::vector<MgSiteInfo*> MgSiteVector;
+
+class MG_MAPGUIDE_API MgSiteManager : public MgGuardDisposable
+{
+DECLARE_CLASSNAME(MgSiteManager)
+
+public:
+
+/// Constructors/Destructor
+
+    virtual ~MgSiteManager();
+
+private:
+
+    MgSiteManager();
+
+/// Methods
+
+public:
+
+    virtual void Dispose();
+    static MgSiteManager* GetInstance();
+
+    MgConnectionProperties* GetConnectionProperties(MgUserInformation*
userInfo, 
+        MgSiteInfo* siteInfo,
+        MgSiteInfo::MgPortType type);
+
+    MgConnectionProperties* GetConnectionProperties(MgUserInformation*
userInfo, 
+        MgSiteInfo::MgPortType type,
+        bool useSessionIP);
+
+    MgConnectionProperties*
GetSupportServerConnectionProperties(CREFSTRING supportServer,
+        MgUserInformation* userInfo, 
+        MgSiteInfo::MgPortType type);
+
+    MgSiteInfo* GetSiteInfo(INT32 index);
+    MgSiteInfo* GetSiteInfo(STRING target, INT32 port);
+    MgSiteInfo* GetNextSite();
+    INT32 GetSiteCount();
+
+private:
+    void Initialize();
+    void ClearSiteInfo();
+
+/// Data Members
+ 
+private:
+    MgConfiguration* m_configuration;
+    static Ptr<MgSiteManager> sm_siteManager;
+    static ACE_Recursive_Thread_Mutex sm_siteManagerMutex;
+
+    UINT16 m_index;
+    MgSiteVector m_sites;
+};
+
+#endif // MG_SITEMANAGER_H_
Index: Common/MapGuideCommon/Services/Site.h
===================================================================
--- Common/MapGuideCommon/Services/Site.h	(revision 1039)
+++ Common/MapGuideCommon/Services/Site.h	(revision 1040)
@@ -338,7 +338,7 @@
     /// \exception MgConnectionFailedException
     ///
     void Open(MgUserInformation* userInformation);
-
+    void Open(MgUserInformation* userInformation, MgSiteInfo*
siteInfo);
 
////////////////////////////////////////////////////////////////////////
///////////
     /// \brief
     /// Closes the current Site Server connection.
@@ -350,17 +350,7 @@
     ///
     void Close();
 
-
////////////////////////////////////////////////////////////////////////
///////////
     /// \brief
-    /// Gets the address of the Site Server.  This value may be used in
ServerAdmin to open a connection to the
-    /// Site Server for administration purposes.
-    ///
-    /// \return
-    /// Returns the site server address.
-    ///
-    STRING GetSiteServerAddress();
-
-    /// \brief
     /// HasWarning() method reports if there is a current warning.
     ///
     /// \return
@@ -772,6 +762,10 @@
     ///
     void RemoveServer(CREFSTRING name);
 
+    MgSiteInfo* GetSiteServerInfo(INT32 index);
+    INT32 GetSiteServerCount();
+    STRING GetCurrentSiteAddress();
+
 INTERNAL_API:
 
 
////////////////////////////////////////////////////////////////////////
///
@@ -796,6 +790,9 @@
     ///
     /// \param userInformation
     /// User information to authenticate against.
+    /// \param siteInfo
+    /// Used to specify which site server to connect to. If NULL, the
next 
+    /// available site server is used.
     /// \param requiredRoles
     /// Required roles to validate against.
     /// \param returnAssignedRoles
@@ -810,6 +807,7 @@
     /// \exception MgUnauthorizedAccessException
     ///
     MgStringCollection* Authenticate(MgUserInformation*
userInformation,
+        MgSiteInfo* siteInfo,
         MgStringCollection* requiredRoles, bool returnAssignedRoles);
 
  protected:
Index: Common/MapGuideCommon/Services/SiteInfo.cpp
===================================================================
--- Common/MapGuideCommon/Services/SiteInfo.cpp	(revision 0)
+++ Common/MapGuideCommon/Services/SiteInfo.cpp	(revision 1040)
@@ -0,0 +1,210 @@
+//
+//  Copyright (C) 2004-2006  Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software
Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301  USA
+//
+#include "MapGuideCommon.h"
+
+IMPLEMENT_DYNCREATE(MgSiteInfo);
+
+///--------------------------------------------------------------------
--------
+/// <summary>
+/// Constructs the object.
+/// </summary>
+///--------------------------------------------------------------------
--------
+
+MgSiteInfo::MgSiteInfo(CREFSTRING target, INT32 sitePort, INT32
clientPort, INT32 adminPort) :
+    m_clientPort(clientPort),
+    m_sitePort(sitePort),
+    m_adminPort(adminPort),
+    m_target(target),
+    m_status(Ok)
+{
+}
+
+///--------------------------------------------------------------------
--------
+/// <summary>
+/// Constructs the object.
+/// </summary>
+///--------------------------------------------------------------------
--------
+
+MgSiteInfo::MgSiteInfo() :
+    m_clientPort(0),
+    m_sitePort(0),
+    m_adminPort(0),
+    m_target(L""),
+    m_status(Uninitialized)
+{
+}
+
+///--------------------------------------------------------------------
--------
+/// <summary>
+/// Constructs the object.
+/// </summary>
+///--------------------------------------------------------------------
--------
+
+MgSiteInfo::MgSiteInfo(CREFSTRING hexString) :
+    m_clientPort(0),
+    m_sitePort(0),
+    m_adminPort(0),
+    m_target(L""),
+    m_status(Uninitialized)
+{
+    if(hexString.length() >= HexStringLength)
+    {
+        UINT32 n1, n2, n3, n4;
+
+        // Read the IP parts into their variables
+        if(::swscanf(hexString.c_str(), L"%2X%2X%2X%2X%4X%4X%4X", &n1,
&n2, &n3, &n4, &m_sitePort, &m_clientPort, &m_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);   
+            m_target = buffer;
+            m_status = Ok;
+        }
+    }
+}
+
+///--------------------------------------------------------------------
--------
+/// <summary>
+/// Destructs the object.
+/// </summary>
+///--------------------------------------------------------------------
--------
+
+MgSiteInfo::~MgSiteInfo()
+{
+}
+
+///--------------------------------------------------------------------
--------
+/// <summary>
+/// Disposes the object.
+/// </summary>
+///--------------------------------------------------------------------
--------
+
+void MgSiteInfo::Dispose()
+{
+    delete this;
+}
+
+/////////////////////////////////////////////////////////////////
+/// <summary>
+/// Returns the classId.
+/// </summary>
+INT32 MgSiteInfo::GetClassId() 
+{ 
+    return m_cls_id; 
+}
+
+///////////////////////////////////////////////////////////////////////
////////
+/// <summary>
+/// Serialize data to TCP/IP stream.
+/// </summary>
+void MgSiteInfo::Serialize(MgStream* stream)
+{
+    stream->WriteString(m_target);
+    stream->WriteInt32(m_sitePort);
+    stream->WriteInt32(m_clientPort);
+    stream->WriteInt32(m_adminPort);
+    stream->WriteInt32((INT32)m_status);
+}
+
+///////////////////////////////////////////////////////////////////////
////////
+/// <summary>
+/// Deserialize data from TCP/IP stream.
+/// </summary>
+void MgSiteInfo::Deserialize(MgStream* stream)
+{
+    stream->GetString(m_target);
+    stream->GetInt32(m_sitePort);
+    stream->GetInt32(m_clientPort);
+    stream->GetInt32(m_adminPort);
+    INT32 statusVal;    
+    stream->GetInt32(statusVal);
+    m_status = (MgSiteStatus)statusVal;
+}
+
+///////////////////////////////////////////////////////////////////////
////////
+/// <summary>
+/// Returns the hex string representation of the target and ports
+/// </summary>
+STRING MgSiteInfo::ToHexString()
+{
+    STRING hexString;
+    UINT32 n1, n2, n3, n4;
+    wchar_t buffer[30];
+    if (4 == ::swscanf(m_target.c_str(), L"%u.%u.%u.%u", &n1, &n2, &n3,
&n4))
+    {
+        swprintf(buffer, 30, L"%.2X%.2X%.2X%.2X%.4X%.4X%.4X", n1, n2,
n3, n4, m_sitePort, m_clientPort, m_adminPort);   
+        hexString = buffer;
+    }
+    return hexString;
+}
+
+///////////////////////////////////////////////////////////////////////
////////
+/// <summary>
+/// Returns the IP target
+/// </summary>
+STRING MgSiteInfo::GetTarget()
+{
+    return m_target;
+}
+
+///////////////////////////////////////////////////////////////////////
////////
+/// <summary>
+/// Returns the port for the specified connection type
+/// </summary>
+INT32 MgSiteInfo::GetPort(MgPortType type)
+{
+    INT32 port = 0;
+    switch(type)
+    {
+        case Client:
+        {
+            port = m_clientPort;
+            break;
+        }
+        case Site:
+        {
+            port = m_sitePort;
+            break;
+        }
+        case Admin:
+        {
+            port = m_adminPort;
+            break;
+        }
+    };
+    return port;
+}
+
+///////////////////////////////////////////////////////////////////////
////////
+/// <summary>
+/// Returns the status of this site server connection
+/// </summary>
+MgSiteInfo::MgSiteStatus MgSiteInfo::GetStatus()
+{
+    return m_status;
+}
+
+///////////////////////////////////////////////////////////////////////
////////
+/// <summary>
+/// Sets the status of this site server connection
+/// </summary>
+void MgSiteInfo::SetStatus(MgSiteStatus status)
+{
+    m_status = status;
+}
+
+
Index: Common/MapGuideCommon/Services/SiteConnection.cpp
===================================================================
--- Common/MapGuideCommon/Services/SiteConnection.cpp	(revision 1039)
+++ Common/MapGuideCommon/Services/SiteConnection.cpp	(revision 1040)
@@ -118,10 +118,16 @@
         m_connProp = new MgConnectionProperties(userInformation, L"",
0);
     }
     // Site connection properties for web-tier or server-2-server
interaction
-    else if (m_isWebTier || m_isServer)
+    else if (m_isWebTier)
     {
-        m_connProp = GetSiteConnectionProperties(userInformation);
+        MgSiteManager* siteManager = MgSiteManager::GetInstance();
+        m_connProp =
siteManager->GetConnectionProperties(userInformation,
MgSiteInfo::Client, true);
     }
+    else if(m_isServer)
+    {
+        MgSiteManager* siteManager = MgSiteManager::GetInstance();
+        m_connProp =
siteManager->GetConnectionProperties(userInformation,
MgSiteInfo::Client, false);
+    }
 
     if (m_connProp == NULL)
     {
@@ -303,7 +309,8 @@
          IsServiceLocal(MgServiceType::MappingService)   ||
          IsServiceLocal(MgServiceType::RenderingService) ||
          IsServiceLocal(MgServiceType::ResourceService)  ||
-         IsServiceLocal(MgServiceType::TileService) )
+         IsServiceLocal(MgServiceType::TileService)      ||
+         IsServiceLocal(MgServiceType::KmlService) )
     {
         isServer = true;
     }
@@ -502,51 +509,6 @@
     return connProp.Detach();
 }
 
-/// <summary>
-/// Gets the site ipaddress and port# for connection
-/// </summary>
-
-MgConnectionProperties* MgSiteConnection::GetSiteConnectionProperties(
-    MgUserInformation* userInformation)
-{
-    Ptr<MgConnectionProperties> connProp;
-    STRING target = L"";
-    INT32 port = 0;
-
-    try
-    {
-        // Get ip address for site server
-        m_config->GetStringValue(
MgConfigProperties::SiteConnectionPropertiesSection,
-
MgConfigProperties::SiteConnectionPropertyIpAddress,
-                                    target,
-
MgConfigProperties::DefaultSiteConnectionPropertyIpAddress);
-
-        // Get the client port
-        m_config->GetIntValue(
MgConfigProperties::ClientConnectionPropertiesSection,
-
MgConfigProperties::ClientConnectionPropertyPort,
-                                port,
-
MgConfigProperties::DefaultClientConnectionPropertyPort);
-
-        // Use the client port for Server/Web Tier communications.
-        connProp = new MgConnectionProperties(userInformation, target,
port);
-
-    }
-    catch (MgException* me)
-    {
-        // Site property address/client port not found, invalid
config.ini
-        SAFE_RELEASE(me);
-
-        MgStringCollection arguments;
-        arguments.Add(m_config->GetFileName());
-
-        throw new MgConfigurationException(
-            L"MgSiteConnection.GetSiteConnectionProperties", 
-            __LINE__, __WFILE__, &arguments, L"", NULL);
-    }
-
-    return connProp.Detach();
-}
-
 
////////////////////////////////////////////////////////////////////////
///////
 /// <summary>
 /// Authenticates a user.
Index: Common/MapGuideCommon/Services/SiteManager.cpp
===================================================================
--- Common/MapGuideCommon/Services/SiteManager.cpp	(revision 0)
+++ Common/MapGuideCommon/Services/SiteManager.cpp	(revision 1040)
@@ -0,0 +1,346 @@
+//
+//  Copyright (C) 2004-2006  Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software
Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301  USA
+//
+#include "MapGuideCommon.h"
+
+// Process-wide MgSiteManager
+Ptr<MgSiteManager> MgSiteManager::sm_siteManager =
(MgSiteManager*)NULL;
+ACE_Recursive_Thread_Mutex MgSiteManager::sm_siteManagerMutex;
+
+#define MIN(x,y) ((x) < (y) ? (x) : (y))
+
+///--------------------------------------------------------------------
--------
+/// <summary>
+/// Constructs the object.
+/// </summary>
+///--------------------------------------------------------------------
--------
+
+MgSiteManager::MgSiteManager()
+{
+    m_configuration = MgConfiguration::GetInstance();
+    assert(NULL != m_configuration);
+
+    Initialize();
+}
+
+///--------------------------------------------------------------------
--------
+/// <summary>
+/// Destructs the object.
+/// </summary>
+///--------------------------------------------------------------------
--------
+
+MgSiteManager::~MgSiteManager()
+{
+    MG_TRY()
+
+    ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)
MgSiteManager::~MgSiteManager()\n")));
+
+    ClearSiteInfo();
+
+    MG_CATCH(L"MgSiteManager.~MgSiteManager")
+}
+
+///--------------------------------------------------------------------
--------
+/// <summary>
+/// Disposes the object.
+/// </summary>
+///--------------------------------------------------------------------
--------
+
+void MgSiteManager::Dispose()
+{
+    delete this;
+}
+
+///--------------------------------------------------------------------
--------
+/// <summary>
+/// Releases the stored site information
+/// </summary>
+///--------------------------------------------------------------------
--------
+
+void MgSiteManager::ClearSiteInfo()
+{
+    for(MgSiteVector::iterator iter = m_sites.begin(); iter !=
m_sites.end(); iter++)
+    {
+        SAFE_RELEASE(*iter);
+    }
+    m_sites.clear();
+}
+
+///--------------------------------------------------------------------
--------
+/// <summary>
+/// Returns the pointer to a process-wide MgSiteManager.
+/// </summary>
+///--------------------------------------------------------------------
--------
+
+MgSiteManager* MgSiteManager::GetInstance()
+{
+    MG_TRY()
+
+    ACE_TRACE("MgSiteManager::GetInstance");
+
+    if (MgSiteManager::sm_siteManager == NULL)
+    {
+        // Perform Double-Checked Locking Optimization.
+        ACE_MT(ACE_GUARD_RETURN(ACE_Recursive_Thread_Mutex, ace_mon,
*ACE_Static_Object_Lock::instance(), NULL));
+
+        if (MgSiteManager::sm_siteManager == NULL)
+        {
+            MgSiteManager::sm_siteManager = new MgSiteManager();
+        }
+    }
+
+    MG_CATCH_AND_THROW(L"MgSiteManager.GetInstance")
+
+    // To avoid overheads and maintain thread safety,
+    // do not assign this returned static singleton to a Ptr object.
+    return MgSiteManager::sm_siteManager;
+}
+
+///--------------------------------------------------------------------
--------
+/// <summary>
+/// Intializes the site manager.
+/// </summary>
+///--------------------------------------------------------------------
--------
+
+void MgSiteManager::Initialize()
+{
+    ACE_MT(ACE_GUARD(ACE_Recursive_Thread_Mutex, ace_mon,
sm_siteManagerMutex));
+
+    MG_TRY()
+
+    ACE_DEBUG((LM_DEBUG, ACE_TEXT( "(%P|%t)
MgSiteManager::Initialize()\n")));
+
+    ClearSiteInfo();
+    MgConfiguration* configuration = MgConfiguration::GetInstance();
+    assert(NULL != configuration);
+
+    // Get the IP address and port for the site server.
+
+    STRING targets;
+    STRING sitePorts;
+    STRING clientPorts;
+    STRING adminPorts;
+
+    configuration->GetStringValue(
+        MgConfigProperties::SiteConnectionPropertiesSection,
+        MgConfigProperties::SiteConnectionPropertyIpAddress,
+        targets,
+        MgConfigProperties::DefaultSiteConnectionPropertyIpAddress);
+    
+    configuration->GetStringValue(
+        MgConfigProperties::SiteConnectionPropertiesSection,
+        MgConfigProperties::SiteConnectionPropertyPort,
+        sitePorts,
+        L"");
+
+    configuration->GetStringValue(
+        MgConfigProperties::ClientConnectionPropertiesSection,
+        MgConfigProperties::ClientConnectionPropertyPort,
+        clientPorts,
+        L"");
+
+    configuration->GetStringValue(
+        MgConfigProperties::AdministrativeConnectionPropertiesSection,
+        MgConfigProperties::AdministrativeConnectionPropertyPort,
+        adminPorts,
+        L"");
+
+    Ptr<MgStringCollection> targetValues =
MgStringCollection::ParseCollection(targets, L",");
+    Ptr<MgStringCollection> sitePortValues =
MgStringCollection::ParseCollection(sitePorts, L",");
+    Ptr<MgStringCollection> clientPortValues =
MgStringCollection::ParseCollection(clientPorts, L",");
+    Ptr<MgStringCollection> adminPortValues =
MgStringCollection::ParseCollection(adminPorts, L",");
+
+    INT32 defaultSitePort = sitePortValues->GetCount() > 0 ?
MgUtil::StringToInt32(sitePortValues->GetItem(0)) :
MgConfigProperties::DefaultSiteConnectionPropertyPort;
+    INT32 defaultClientPort = clientPortValues->GetCount() > 0 ?
MgUtil::StringToInt32(clientPortValues->GetItem(0)) :
MgConfigProperties::DefaultClientConnectionPropertyPort;
+    INT32 defaultAdminPort = adminPortValues->GetCount() > 0 ?
MgUtil::StringToInt32(adminPortValues->GetItem(0)) :
MgConfigProperties::DefaultAdministrativeConnectionPropertyPort;
+
+    int numTargets = targetValues->GetCount();
+    for(int i = 0; i < numTargets; i++)
+    {
+        INT32 sitePort = sitePortValues->GetCount() > i ?
MgUtil::StringToInt32(sitePortValues->GetItem(i)) : defaultSitePort;
+        INT32 clientPort = clientPortValues->GetCount() > i ?
MgUtil::StringToInt32(clientPortValues->GetItem(i)) : defaultClientPort;
+        INT32 adminPort = adminPortValues->GetCount() > i ?
MgUtil::StringToInt32(adminPortValues->GetItem(i)) : defaultAdminPort;
+
+        STRING targetIP;
+        MgIpUtil::HostNameToAddress(targetValues->GetItem(i),
targetIP);
+        Ptr<MgSiteInfo> siteInfo = new MgSiteInfo(targetIP,
+            sitePort, clientPort, adminPort);
+        m_sites.push_back(SAFE_ADDREF((MgSiteInfo*)siteInfo));
+    }
+
+    MG_CATCH_AND_THROW(L"MgSiteManager.Initialize")
+}
+
+///--------------------------------------------------------------------
--------
+/// <summary>
+/// Retrieves connection properties for a site server. If useSessionIP
is true
+/// and the userInfo contains a session ID, the connection properties
will be
+/// generated for the site that contains that session.
+/// </summary>
+///--------------------------------------------------------------------
--------
+
+MgConnectionProperties*
MgSiteManager::GetConnectionProperties(MgUserInformation* userInfo, 
+
MgSiteInfo::MgPortType type,
+                                                               bool
useSessionIP)
+{
+    MgConnectionProperties* connProps = NULL;
+    
+    // Determine if the user info contains a session ID
+    STRING sessionId = userInfo->GetMgSessionId();
+    if(useSessionIP && !sessionId.empty())
+    {
+        size_t length = sessionId.length();
+        if(length > MgSiteInfo::HexStringLength)
+        {
+            STRING siteHexString = sessionId.substr(length -
MgSiteInfo::HexStringLength, MgSiteInfo::HexStringLength);
+            Ptr<MgSiteInfo> siteInfo = new MgSiteInfo(siteHexString);
+            if(siteInfo->GetStatus() == MgSiteInfo::Ok)
+            {
+                connProps = GetConnectionProperties(userInfo, siteInfo,
type);
+            }
+        }
+    }
+    else
+    {
+        Ptr<MgSiteInfo> nextSite = GetNextSite();
+        if(nextSite != NULL)
+        {
+            connProps = GetConnectionProperties(userInfo, nextSite,
type);
+        }
+    }
+
+    return connProps;
+}
+
+///--------------------------------------------------------------------
--------
+/// <summary>
+/// Retrieves connection properties for the site specified in the
siteInfo object
+/// </summary>
+///--------------------------------------------------------------------
--------
+MgConnectionProperties*
MgSiteManager::GetConnectionProperties(MgUserInformation* userInfo, 
+        MgSiteInfo* siteInfo,
+        MgSiteInfo::MgPortType type)
+{
+    MgConnectionProperties* connProps = NULL;
+    if(siteInfo != NULL)
+    {
+        connProps = new MgConnectionProperties(userInfo,
siteInfo->GetTarget(), siteInfo->GetPort(type));
+    }
+    return connProps;
+}
+
+///--------------------------------------------------------------------
--------
+/// <summary>
+/// Retrieves connection properties for a support server. If
useSessionIP is true
+/// and the userInfo contains a session ID, the connection properties
will be
+/// generated for the site that contains that session.
+/// </summary>
+///--------------------------------------------------------------------
--------
+MgConnectionProperties*
MgSiteManager::GetSupportServerConnectionProperties(CREFSTRING
supportServer,
+
MgUserInformation* userInfo, 
+
MgSiteInfo::MgPortType type)
+{
+    MgConnectionProperties* supportConnProps = NULL; 
+    
+    // Session Affinity: Retrieve the site server corresponding to this
user info
+    MgConnectionProperties* siteConnProps =
GetConnectionProperties(userInfo, type, true);
+    if(siteConnProps != NULL)
+    {
+        // Create support server connection props using the specified
IP target and the same admin port
+        // used by the site server
+        supportConnProps = new MgConnectionProperties(userInfo,
supportServer, siteConnProps->GetPort());
+    }
+    return supportConnProps;
+}
+
+///--------------------------------------------------------------------
--------
+/// <summary>
+/// Retrieves site info for the next site server that has an Ok status.
+/// </summary>
+///--------------------------------------------------------------------
--------
+MgSiteInfo* MgSiteManager::GetNextSite()
+{
+    MgSiteInfo* nextSite = NULL;
+    
+    int numSites = (int)m_sites.size();
+    for(int siteIndex = 0; siteIndex < numSites; siteIndex++)
+    {
+        int siteToTry = (m_index + siteIndex) % numSites;
+        MgSiteInfo* siteInfo = m_sites.at(siteToTry);
+        if(siteInfo->GetStatus() == MgSiteInfo::Ok)
+        {
+            nextSite = siteInfo;
+            m_index = siteToTry + 1;
+            break;
+        }
+    }
+
+    return SAFE_ADDREF(nextSite);
+}
+
+///--------------------------------------------------------------------
--------
+/// <summary>
+/// Retrieves the number of configured site servers
+/// </summary>
+///--------------------------------------------------------------------
--------
+INT32 MgSiteManager::GetSiteCount()
+{
+    return (INT32)m_sites.size();
+}
+
+///--------------------------------------------------------------------
--------
+/// <summary>
+/// Retrieves site info for the site server corresponding to the
specified index
+/// </summary>
+///--------------------------------------------------------------------
--------
+MgSiteInfo* MgSiteManager::GetSiteInfo(INT32 index)
+{
+    MgSiteInfo* siteInfo = NULL;
+    if((UINT32)index < m_sites.size())
+    {
+        siteInfo = m_sites.at(index);
+    }
+    return SAFE_ADDREF(siteInfo);
+}
+
+///--------------------------------------------------------------------
--------
+/// <summary>
+/// Retrieves site info for the site server matching the specified
target and port
+/// </summary>
+///--------------------------------------------------------------------
--------
+MgSiteInfo* MgSiteManager::GetSiteInfo(STRING target, INT32 port)
+{
+    Ptr<MgSiteInfo> matchingSiteInfo;
+    matchingSiteInfo = NULL;
+
+    for(int i = 0; i < GetSiteCount(); i++)
+    {
+        Ptr<MgSiteInfo> siteInfo = GetSiteInfo(i);
+        if(siteInfo->GetTarget() == target)
+        {
+            INT32 sitePort = siteInfo->GetPort(MgSiteInfo::Site);
+            INT32 clientPort = siteInfo->GetPort(MgSiteInfo::Client);
+            INT32 adminPort = siteInfo->GetPort(MgSiteInfo::Admin);
+            if(port == sitePort || port == clientPort || port ==
adminPort)
+            {
+                matchingSiteInfo = siteInfo;
+                break;
+            }
+        }
+    }
+
+    return SAFE_ADDREF((MgSiteInfo*)matchingSiteInfo);
+}
Index: Common/MapGuideCommon/Services/ServerAdmin.h
===================================================================
--- Common/MapGuideCommon/Services/ServerAdmin.h	(revision 1039)
+++ Common/MapGuideCommon/Services/ServerAdmin.h	(revision 1040)
@@ -69,6 +69,21 @@
 
 
////////////////////////////////////////////////////////////////////////
///////////
     /// \brief
+    /// Opens a connection to a Server.
+    ///
+    /// \param userInformation
+    /// User information - credentials, locale, session identifier
+    ///
+    /// \return
+    /// Nothing
+    ///
+    /// \exception MgServerNotFoundException
+    /// \exception MgConnectionFailedException
+    ///
+    void Open(MgUserInformation* userInformation);
+
+
////////////////////////////////////////////////////////////////////////
///////////
+    /// \brief
     /// Closes the current Server connection.
     ///
     /// \return
Index: Common/MapGuideCommon/Services/SiteInfo.h
===================================================================
--- Common/MapGuideCommon/Services/SiteInfo.h	(revision 0)
+++ Common/MapGuideCommon/Services/SiteInfo.h	(revision 1040)
@@ -0,0 +1,106 @@
+//
+//  Copyright (C) 2004-2006  Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software
Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301  USA
+//
+#include "MapGuideCommon.h"
+
+#ifndef MG_SITEINFO_H_
+#define MG_SITEINFO_H_
+
+class MG_MAPGUIDE_API MgSiteInfo : public MgSerializable
+{
+    DECLARE_DYNCREATE_COREDATA();
+    DECLARE_CLASSNAME(MgSiteInfo)
+        
+EXTERNAL_API:
+
+    enum MgSiteStatus
+    {
+        Ok,
+        UnableToConnect,
+        TimedOut,
+        Uninitialized
+    };
+
+    enum MgPortType
+    {
+        Client,
+        Site,
+        Admin
+    };
+
+
+/// Constructors/Destructor
+
+    MgSiteInfo();
+    MgSiteInfo(CREFSTRING target, INT32 sitePort, INT32 clientPort,
INT32 adminPort);
+    virtual ~MgSiteInfo();
+    
+/// Methods
+
+    STRING GetTarget();
+    INT32 GetPort(MgPortType type);
+    MgSiteStatus GetStatus();
+    void SetStatus(MgSiteStatus);
+
+INTERNAL_API:
+    
+    //////////////////////////////////////////////////////////////////
+    /// \brief
+    /// Serialize data to TCP/IP stream
+    ///
+    /// \param stream
+    /// Stream
+    ///
+    virtual void Serialize(MgStream* stream);
+
+    //////////////////////////////////////////////////////////////////
+    /// \brief
+    /// Deserialize data from TCP/IP stream
+    ///
+    /// \param stream
+    /// Stream
+    ///
+    virtual void Deserialize(MgStream* stream);
+
+    // Create a new MgSiteInfo instance, and initialize it from a hex
string
+    MgSiteInfo(CREFSTRING hexString);
+    
+    // Retrieve a hex string that encodes the site info connection
params
+    STRING ToHexString();
+
+    static const INT32 HexStringLength = 20;
+
+protected:
+
+    INT32 GetClassId();
+    virtual void Dispose();
+
+/// Data Members
+ 
+private:
+
+    STRING m_target;
+    INT32 m_clientPort;
+    INT32 m_sitePort;
+    INT32 m_adminPort;
+    MgSiteStatus m_status;   
+
+CLASS_ID:
+    static const INT32 m_cls_id = MapGuide_Service_SiteInfo;
+
+};
+
+#endif // MG_SITEINFO_H_
Index: Common/MapGuideCommon/Services/ServerAdmin.cpp
===================================================================
--- Common/MapGuideCommon/Services/ServerAdmin.cpp	(revision 1039)
+++ Common/MapGuideCommon/Services/ServerAdmin.cpp	(revision 1040)
@@ -52,18 +52,33 @@
 
 
////////////////////////////////////////////////////////////////////////
///////////
 /// <summary>
-/// Opens a connection to a specified Server.
+/// Opens a connection to a specified support Server.
 /// <param name="server">
 /// Server IP address or DNS name.
 /// </summary>
 /// </param>
-// <param name="credentials">
+/// <param name="userInformation">
 /// UserCredentials to authenticate against
 /// </param>
-/// <param name="locale">
-/// Administrator's locale.  Server should honor all operations on this
connection
-/// using the Administrator's locale.  In the first revision, this may
only apply to
-/// error and warning messages.
+/// <returns>
+/// Nothing
+/// </returns>
+///
+/// EXCEPTIONS:
+/// MgServerNotFoundException
+/// MgConnectionFailedException
+void MgServerAdmin::Open(CREFSTRING supportServer, MgUserInformation*
userInformation)
+{
+    MgSiteManager* siteManager = MgSiteManager::GetInstance();
+    m_connProp =
siteManager->GetSupportServerConnectionProperties(supportServer,
userInformation, MgSiteInfo::Admin);
+}
+
+///////////////////////////////////////////////////////////////////////
////////////
+/// <summary>
+/// Opens a connection to a server.
+/// </summary>
+/// <param name="userInformation">
+/// UserCredentials to authenticate against
 /// </param>
 /// <returns>
 /// Nothing
@@ -72,18 +87,10 @@
 /// EXCEPTIONS:
 /// MgServerNotFoundException
 /// MgConnectionFailedException
-void MgServerAdmin::Open(CREFSTRING server, MgUserInformation*
userInformation)
+void MgServerAdmin::Open(MgUserInformation* userInformation)
 {
-    INT32 adminPort;
-    //get the port for administration connection
-    MgConfiguration* config = MgConfiguration::GetInstance();
-
config->GetIntValue(MgConfigProperties::AdministrativeConnectionProperti
esSection,
-
MgConfigProperties::AdministrativeConnectionPropertyPort,
-                        adminPort,
-
MgConfigProperties::DefaultAdministrativeConnectionPropertyPort);
-
-
-    m_connProp = new MgConnectionProperties(userInformation, server,
adminPort);
+    MgSiteManager* siteManager = MgSiteManager::GetInstance();
+    m_connProp = siteManager->GetConnectionProperties(userInformation,
MgSiteInfo::Admin, true);
 }
 
 
////////////////////////////////////////////////////////////////////////
///////////
Index: Common/MapGuideCommon/Services/ServerConnection.cpp
===================================================================
--- Common/MapGuideCommon/Services/ServerConnection.cpp	(revision 1039)
+++ Common/MapGuideCommon/Services/ServerConnection.cpp	(revision 1040)
@@ -88,13 +88,19 @@
 void MgServerConnection::Open(MgUserInformation* userInformation,
MgConnectionProperties* connProp)
 {
     m_connProp = SAFE_ADDREF(connProp);
-    bool connected =
m_serverConnImp->Connect((MgUtil::WideCharToMultiByte(m_connProp->GetTar
get())).c_str(), m_connProp->GetPort());
+    bool connected = m_serverConnImp->Connect((
+        MgUtil::WideCharToMultiByte(m_connProp->GetTarget())).c_str(), 
+        m_connProp->GetPort());
 
     // Could not connect
     if (!connected)
+    {
         throw new
MgConnectionFailedException(L"MgServerConnection.Open", __LINE__,
__WFILE__, NULL, L"", NULL);
-
-    m_isOpen = true;
+    }
+    else
+    {
+        m_isOpen = true;
+    }
 }
 
 //////////////////////////////////////////////////////////////////
Index: Common/MapGuideCommon/Services/Site.cpp
===================================================================
--- Common/MapGuideCommon/Services/Site.cpp	(revision 1039)
+++ Common/MapGuideCommon/Services/Site.cpp	(revision 1040)
@@ -78,7 +78,7 @@
 
 
////////////////////////////////////////////////////////////////////////
///////
 /// <summary>
-/// Opens a connection to the Site Server.
+/// Opens a connection to a Site Server.
 /// </summary>
 
 void MgSite::Open(MgUserInformation* userInformation)
@@ -87,11 +87,27 @@
 
     // Authenticate the user.
 
-    Authenticate(userInformation, NULL, false);
+    Authenticate(userInformation, NULL, NULL, false);
 
     MG_SITE_CATCH_AND_THROW(L"MgSite.Open")
 }
 
+///////////////////////////////////////////////////////////////////////
////////
+/// <summary>
+/// Opens a connection to the specified Site Server.
+/// </summary>
+
+void MgSite::Open(MgUserInformation* userInformation, MgSiteInfo*
siteInfo)
+{
+    MG_SITE_TRY()
+
+    // Authenticate the user.
+
+    Authenticate(userInformation, siteInfo, NULL, false);
+
+    MG_SITE_CATCH_AND_THROW(L"MgSite.Open")
+}
+
 
////////////////////////////////////////////////////////////////////////
///////////
 /// <summary>
 /// Closes the current Site Server connection.
@@ -109,31 +125,43 @@
 
 
////////////////////////////////////////////////////////////////////////
///////////
 /// <summary>
-/// Gets the address of the Site Server.  This value may be used in
ServerAdmin to open a connection to the
-/// Site Server for administration purposes.
+/// Gets the addresses of the Site Servers.  
 /// </summary>
 /// <returns>
 /// Returns the site server address.
 /// </returns>
 ///
-STRING MgSite::GetSiteServerAddress()
+MgSiteInfo* MgSite::GetSiteServerInfo(INT32 index)
 {
-    STRING address = L"";
+    MgSiteManager* siteManager = MgSiteManager::GetInstance();
+    return siteManager->GetSiteInfo(index);
+}
 
-    MG_SITE_TRY()
+///////////////////////////////////////////////////////////////////////
////////////
+/// <summary>
+/// Gets the addresses of the Site Servers.  
+/// </summary>
+/// <returns>
+/// Returns the site server address.
+/// </returns>
+///
+INT32 MgSite::GetSiteServerCount()
+{
+    MgSiteManager* siteManager = MgSiteManager::GetInstance();
+    return siteManager->GetSiteCount();
+}
 
-    // Get Site Server Address
-    MgConfiguration* pConfig = MgConfiguration::GetInstance();
-    pConfig->GetStringValue(
MgConfigProperties::SiteConnectionPropertiesSection,
-
MgConfigProperties::SiteConnectionPropertyIpAddress,
-                               address,
-
MgConfigProperties::DefaultSiteConnectionPropertyIpAddress);
+STRING MgSite::GetCurrentSiteAddress()
+{
+    STRING target = L"";
+    if(m_connProp != NULL)
+    {
+        target = m_connProp->GetTarget();
+    }
+    return target;
+}
 
-    MG_SITE_CATCH_AND_THROW( L"MgSite::GetSiteServerAddress" )
 
-    return address;
-}
-
 
////////////////////////////////////////////////////////////////////////
///////////
 /// <summary>
 /// Create a session for the user and return the unique session
identifier. For the
@@ -1186,7 +1214,7 @@
 }
 
 MgStringCollection* MgSite::Authenticate(MgUserInformation*
userInformation,
-    MgStringCollection* requiredRoles, bool returnAssignedRoles)
+    MgSiteInfo* siteInfo, MgStringCollection* requiredRoles, bool
returnAssignedRoles)
 {
     MgCommand cmd;
 
@@ -1197,24 +1225,18 @@
     MgConfiguration* configuration = MgConfiguration::GetInstance();
     assert(NULL != configuration);
 
-    // Get the IP address and port for the site server.
-
-    STRING target;
-    INT32 port = 0;
-
-    configuration->GetStringValue(
-        MgConfigProperties::SiteConnectionPropertiesSection,
-        MgConfigProperties::SiteConnectionPropertyIpAddress,
-        target,
-        MgConfigProperties::DefaultSiteConnectionPropertyIpAddress);
-    configuration->GetIntValue(
-        MgConfigProperties::SiteConnectionPropertiesSection,
-        MgConfigProperties::SiteConnectionPropertyPort,
-        port,
-        MgConfigProperties::DefaultSiteConnectionPropertyPort);
-
     assert(m_connProp == NULL);
-    m_connProp = new MgConnectionProperties(userInformation, target,
port);
+    MgSiteManager* siteManager = MgSiteManager::GetInstance();
+    if(siteInfo != NULL)
+    {
+        m_connProp =
siteManager->GetConnectionProperties(userInformation, 
+            siteInfo, MgSiteInfo::Site);
+    }
+    else
+    {
+        m_connProp =
siteManager->GetConnectionProperties(userInformation, 
+            MgSiteInfo::Site, true);
+    }
 
     cmd.ExecuteCommand(m_connProp,                          //
Connection
                         MgCommand::knObject,                // Return
type
Index: Common/MapGuideCommon/Controller/DwfController.cpp
===================================================================
--- Common/MapGuideCommon/Controller/DwfController.cpp	(revision 1039)
+++ Common/MapGuideCommon/Controller/DwfController.cpp	(revision 1040)
@@ -44,6 +44,17 @@
 MgByteReader* MgDwfController::GetMap(MgResourceIdentifier*
mapDefinition,
     CREFSTRING dwfVersion, CREFSTRING eMapVersion,
MgPropertyCollection* mapViewCommands)
 {
+    //create a session id to associate with this map
+    STRING sessionId;
+    Ptr<MgUserInformation> userInfo = m_siteConn->GetUserInfo();
+    if (userInfo.p != NULL) sessionId = userInfo->GetMgSessionId();
+    if (sessionId.empty())
+    {
+        Ptr<MgSite> site = m_siteConn->GetSite();
+        sessionId = site->CreateSession();
+        userInfo->SetMgSessionId(sessionId);
+    }
+
     //get an instance of the resource service
     Ptr<MgResourceService> resourceService =
(MgResourceService*)GetService(MgServiceType::ResourceService);
 
@@ -56,17 +67,6 @@
     //apply commands
     ApplyMapViewCommands(map, mapViewCommands);
 
-    //create a session id to associate with this map
-    STRING sessionId;
-    Ptr<MgUserInformation> userInfo = m_siteConn->GetUserInfo();
-    if (userInfo.p != NULL) sessionId = userInfo->GetMgSessionId();
-    if (sessionId.empty())
-    {
-        Ptr<MgSite> site = m_siteConn->GetSite();
-        sessionId = site->CreateSession();
-        userInfo->SetMgSessionId(sessionId);
-    }
-
     //save the map state in the session repository
     Ptr<MgResourceIdentifier> resId = new
MgResourceIdentifier(L"Session:" + sessionId + L"//" +
mapDefinition->GetName() + L"." + MgResourceType::Map);
     map->Save((MgResourceService*)resourceService,
(MgResourceIdentifier*)resId);
Index: Common/MapGuideCommon/System/UserInformation.cpp
===================================================================
--- Common/MapGuideCommon/System/UserInformation.cpp	(revision 1039)
+++ Common/MapGuideCommon/System/UserInformation.cpp	(revision 1040)
@@ -221,6 +221,29 @@
 
 ///////////////////////////////
 ///<summary>
+///Create a sessionid, and encode the IP address of the site server
that
+///created it into the ID
+///</summary>
+STRING MgUserInformation::CreateMgSessionId(MgSiteInfo* siteInfo)
+{
+    STRING id = CreateMgSessionId();
+
+    STRING hexAddress;
+    if(siteInfo != NULL)
+    {
+        hexAddress = siteInfo->ToHexString();
+        if(!hexAddress.empty())
+        {
+            id.append(L"_");
+            id.append(hexAddress);
+        }
+    }
+
+    return id;
+}
+
+///////////////////////////////
+///<summary>
 ///Clears the current sessionid
 ///</summary>
 void MgUserInformation::ClearMgSessionId()
Index: Common/MapGuideCommon/System/UserInformation.h
===================================================================
--- Common/MapGuideCommon/System/UserInformation.h	(revision 1039)
+++ Common/MapGuideCommon/System/UserInformation.h	(revision 1040)
@@ -37,7 +37,9 @@
 class MgUserInformation;
 template class MG_MAPGUIDE_API Ptr<MgUserInformation>;
 
+class MgSiteInfo;
 
+
 /// \defgroup MgUserInformation MgUserInformation
 /// \ingroup Common_Module
 /// \{
@@ -317,6 +319,7 @@
     /// New session id
     ///
     STRING CreateMgSessionId();
+    STRING CreateMgSessionId(MgSiteInfo* siteInfo);
 
     ///////////////////////////////
     /// \brief
Index: Common/MapGuideCommon/System/MapGuideCommonFactory.cpp
===================================================================
--- Common/MapGuideCommon/System/MapGuideCommonFactory.cpp
(revision 1039)
+++ Common/MapGuideCommon/System/MapGuideCommonFactory.cpp
(revision 1040)
@@ -94,6 +94,7 @@
     fact->Register(MapGuide_Service_ServerInformation,
MgServerInformation::CreateObject);
     fact->Register(MapGuide_Service_PackageStatusInformation,
MgPackageStatusInformation::CreateObject);
     fact->Register(MapGuide_Service_UserInformation,
MgUserInformation::CreateObject);
+    fact->Register(MapGuide_Service_SiteInfo,
MgSiteInfo::CreateObject);
     fact->Register(PlatformBase_FeatureService_DataReader,
MgProxyDataReader::CreateObject);
     fact->Register(PlatformBase_FeatureService_FeatureReader,
MgProxyFeatureReader::CreateObject);
     fact->Register(PlatformBase_FeatureService_GwsFeatureReader,
MgProxyGwsFeatureReader::CreateObject);
Index: Common/MapGuideCommon/System/MapGuideCommonClassId.h
===================================================================
--- Common/MapGuideCommon/System/MapGuideCommonClassId.h
(revision 1039)
+++ Common/MapGuideCommon/System/MapGuideCommonClassId.h
(revision 1040)
@@ -105,6 +105,7 @@
 #define MapGuide_Service_Site
MAPGUIDE_SERVICE_ID+5
 #define MapGuide_Service_UserInformation
MAPGUIDE_SERVICE_ID+6
 #define MapGuide_Service_ServerAdmin
MAPGUIDE_SERVICE_ID+7
+#define MapGuide_Service_SiteInfo
MAPGUIDE_SERVICE_ID+8
 
 // Drawing Service
 #define MapGuide_DrawingService_DrawingService
MAPGUIDE_DRAWINGSERVICE_ID+0
Index: Common/MapGuideCommon/MapGuideCommonBuild.cpp
===================================================================
--- Common/MapGuideCommon/MapGuideCommonBuild.cpp	(revision 1039)
+++ Common/MapGuideCommon/MapGuideCommonBuild.cpp	(revision 1040)
@@ -115,6 +115,8 @@
 #include  "Services/ServerConnectionStack.cpp"
 #include  "Services/ServerInformation.cpp"
 #include  "Services/Site.cpp"
+#include  "Services/SiteManager.cpp"
+#include  "Services/SiteInfo.cpp"
 #include  "Services/SiteConnection.cpp"
 #include  "Services/TileDefs.cpp"
 #include  "Services/TileService.cpp"
Index: Common/MapGuideCommon/MapGuideCommon.vcproj
===================================================================
--- Common/MapGuideCommon/MapGuideCommon.vcproj	(revision 1039)
+++ Common/MapGuideCommon/MapGuideCommon.vcproj	(revision 1040)
@@ -1029,6 +1029,22 @@
 				>
 			</File>
 			<File
+				RelativePath=".\Services\SiteInfo.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\Services\SiteInfo.h"
+				>
+			</File>
+			<File
+
RelativePath=".\Services\SiteManager.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\Services\SiteManager.h"
+				>
+			</File>
+			<File
 				RelativePath=".\Services\TileDefs.cpp"
 				>
 			</File>
Index: Common/MapGuideCommon/Makefile.am
===================================================================
--- Common/MapGuideCommon/Makefile.am	(revision 1039)
+++ Common/MapGuideCommon/Makefile.am	(revision 1040)
@@ -108,6 +108,8 @@
   Services/ServerConnectionStack.cpp \
   Services/ServerInformation.cpp \
   Services/Site.cpp \
+  Services/SiteManager.cpp \
+  Services/SiteInfo.cpp \
   Services/SiteConnection.cpp \
   Services/TileDefs.cpp \
   Services/TileService.cpp \
@@ -221,6 +223,8 @@
   Services/ServerConnectionStack.h \
   Services/ServerInformation.h \
   Services/Site.h \
+  Services/SiteManager.h \
+  Services/SiteInfo.h \
   Services/SiteConnection.h \
   Services/TileDefs.h \
   Services/TileService.h \
Index: Common/MapGuideCommon/MapGuideCommon.h
===================================================================
--- Common/MapGuideCommon/MapGuideCommon.h	(revision 1039)
+++ Common/MapGuideCommon/MapGuideCommon.h	(revision 1040)
@@ -99,6 +99,8 @@
 #include "Net/IOperationHandler.h"
 #include "Services/Command.h"
 #include "Services/Site.h"
+#include "Services/SiteInfo.h"
+#include "Services/SiteManager.h"
 #include "Services/ConnectionProperties.h"
 #include "Services/SiteConnection.h"
 #include "Services/DrawingDefs.h"
Index: Server/src/Services/Site/ServerSiteService.cpp
===================================================================
--- Server/src/Services/Site/ServerSiteService.cpp	(revision 1039)
+++ Server/src/Services/Site/ServerSiteService.cpp	(revision 1040)
@@ -720,7 +720,9 @@
 
     if (session.empty())
     {
-        session = currUserInfo->CreateMgSessionId();
+        MgSiteManager* siteManager = MgSiteManager::GetInstance();
+        Ptr<MgSiteInfo> siteInfo = siteManager->GetSiteInfo(0);
+        session = currUserInfo->CreateMgSessionId(siteInfo);
         currUserInfo->SetMgSessionId(session);
     }
     else
Index: Server/src/Common/Manager/SessionCache.cpp
===================================================================
--- Server/src/Common/Manager/SessionCache.cpp	(revision 1039)
+++ Server/src/Common/Manager/SessionCache.cpp	(revision 1040)
@@ -144,6 +144,22 @@
 MgSessionInfo* MgSessionCache::GetSessionInfo(CREFSTRING session,
     bool strict) const
 {
+#ifdef _DEBUG
+    // Session Affinity: Check that the session was created by this
server 
+    if(!session.empty())
+    {
+        STRING hexString = session.substr(session.length() -
MgSiteInfo::HexStringLength);
+        Ptr<MgSiteInfo> sessionSiteInfo = new MgSiteInfo(hexString);
+        if(sessionSiteInfo->GetStatus() == MgSiteInfo::Ok)
+        {
+            MgSiteManager* siteManager = MgSiteManager::GetInstance();
+            Ptr<MgSiteInfo> firstSite = siteManager->GetSiteInfo(0);
+
assert(sessionSiteInfo->GetTarget().compare(firstSite->GetTarget()) ==
0);
+            assert(sessionSiteInfo->GetPort(MgSiteInfo::Site) ==
firstSite->GetPort(MgSiteInfo::Site));
+        }
+    }
+#endif //_DEBUG
+
     MgSessionInfo* sessionInfo = NULL;
     MgSessionInfoMap::const_iterator i =
m_sessionInfoMap.find(session);
 
Index: Server/src/UnitTesting/UnitTesting.vcproj
===================================================================
--- Server/src/UnitTesting/UnitTesting.vcproj	(revision 1039)
+++ Server/src/UnitTesting/UnitTesting.vcproj	(revision 1040)
@@ -277,6 +277,14 @@
 			>
 		</File>
 		<File
+			RelativePath=".\TestSiteManager.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\TestSiteManager.h"
+			>
+		</File>
+		<File
 			RelativePath=".\TestSiteService.cpp"
 			>
 		</File>
Index: Server/src/UnitTesting/TestSiteManager.h
===================================================================
--- Server/src/UnitTesting/TestSiteManager.h	(revision 0)
+++ Server/src/UnitTesting/TestSiteManager.h	(revision 1040)
@@ -0,0 +1,59 @@
+//
+//  Copyright (C) 2004-2006  Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software
Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301  USA
+//
+
+#ifndef _TestSiteManager_H
+#define _TestSiteManager_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class TestSiteManager : public CppUnit::TestFixture
+{
+    CPPUNIT_TEST_SUITE(TestSiteManager);
+    CPPUNIT_TEST(TestStart); // This must be the very first unit test
+
+    CPPUNIT_TEST(TestCase_ValidSiteManager);
+    CPPUNIT_TEST(TestCase_GetSiteConnectionProperties);
+    CPPUNIT_TEST(TestCase_GetSiteConnectionPropertiesWithSession);
+    CPPUNIT_TEST(TestCase_GetSiteConnectionPropertiesIgnoreSession);
+    CPPUNIT_TEST(TestCase_GetSpecificSiteConnectionProperties);
+    CPPUNIT_TEST(TestCase_GetSupportServerConnectionProperties);
+    CPPUNIT_TEST(TestCase_GetSiteInfo);
+    CPPUNIT_TEST(TestCase_GetSiteCount);
+
+    CPPUNIT_TEST(TestEnd); // This must be the very last unit test
+    CPPUNIT_TEST_SUITE_END();
+
+public:
+    void setUp();
+    void tearDown();
+    void TestStart();
+    void TestEnd();
+
+    void TestCase_ValidSiteManager();
+    void TestCase_GetSiteConnectionProperties();
+    void TestCase_GetSiteConnectionPropertiesWithSession();
+    void TestCase_GetSiteConnectionPropertiesIgnoreSession();
+    void TestCase_GetSpecificSiteConnectionProperties();
+    void TestCase_GetSupportServerConnectionProperties();
+    void TestCase_GetSiteInfo();
+    void TestCase_GetSiteCount();
+
+private:
+    static void TestWorkerThreads();
+};
+
+#endif // _TestSiteManager_H
Index: Server/src/UnitTesting/UnitTesting.cpp
===================================================================
--- Server/src/UnitTesting/UnitTesting.cpp	(revision 1039)
+++ Server/src/UnitTesting/UnitTesting.cpp	(revision 1040)
@@ -55,6 +55,7 @@
 
runner.addTest(CppUnit::TestFactoryRegistry::getRegistry("TestServerMana
ger").makeTest());
 
runner.addTest(CppUnit::TestFactoryRegistry::getRegistry("TestServiceMan
ager").makeTest());
 
runner.addTest(CppUnit::TestFactoryRegistry::getRegistry("TestSiteServic
e").makeTest());
+
runner.addTest(CppUnit::TestFactoryRegistry::getRegistry("TestSiteManage
r").makeTest());
         }
         else if(ACE_OS::strcasecmp(MG_WCHAR_TO_TCHAR(test),
MG_WCHAR_TO_TCHAR(MgResources::ServerCmdTestListTests)) == 0)
         {
@@ -75,6 +76,7 @@
             ACE_OS::printf("  ServerManager\n");
             ACE_OS::printf("  ServiceManager\n");
             ACE_OS::printf("  SiteService\n");
+            ACE_OS::printf("  SiteManager\n");
             ACE_OS::printf("\n");
 
             bRunTests = false;
@@ -139,6 +141,11 @@
             ACE_DEBUG((LM_INFO, ACE_TEXT(">>>>> Running only Site
Service tests. <<<<<\n\n")));
 
runner.addTest(CppUnit::TestFactoryRegistry::getRegistry("TestSiteServic
e").makeTest());
         }
+        else if(ACE_OS::strcasecmp(MG_WCHAR_TO_TCHAR(test),
ACE_LIB_TEXT("SiteManager")) == 0)
+        {
+            ACE_DEBUG((LM_INFO, ACE_TEXT(">>>>> Running only Site
Manager tests. <<<<<\n\n")));
+
runner.addTest(CppUnit::TestFactoryRegistry::getRegistry("TestSiteManage
r").makeTest());
+        }
         else
         {
             // Test suite not found
@@ -162,6 +169,7 @@
 
runner.addTest(CppUnit::TestFactoryRegistry::getRegistry("TestServerMana
ger").makeTest());
 
runner.addTest(CppUnit::TestFactoryRegistry::getRegistry("TestServiceMan
ager").makeTest());
 
runner.addTest(CppUnit::TestFactoryRegistry::getRegistry("TestSiteServic
e").makeTest());
+
runner.addTest(CppUnit::TestFactoryRegistry::getRegistry("TestSiteManage
r").makeTest());
     }
 
     if(bRunTests)
Index: Server/src/UnitTesting/TestSiteManager.cpp
===================================================================
--- Server/src/UnitTesting/TestSiteManager.cpp	(revision 0)
+++ Server/src/UnitTesting/TestSiteManager.cpp	(revision 1040)
@@ -0,0 +1,315 @@
+//
+//  Copyright (C) 2004-2006  Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software
Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301  USA
+//
+
+#include "MapGuideCommon.h"
+#include "TestSiteManager.h"
+
+const STRING TEST_SESSION_ID =
L"48cb0286-0000-1000-8001-005056c00008_en_6F7A8590045708AE0D05";
+const STRING TEST_TARGET = L"111.122.133.144";
+const STRING TEST_SUPPORT_SERVER = L"144.133.122.111";
+const INT32 TEST_SITE_PORT = 1111;
+const INT32 TEST_CLIENT_PORT = 2222;
+const INT32 TEST_ADMIN_PORT = 3333;
+const STRING TEST_LOCALE = L"en";
+
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(TestSiteManager,
"TestSiteManager");
+
+void TestSiteManager::setUp()
+{
+}
+
+void TestSiteManager::tearDown()
+{
+}
+
+void TestSiteManager::TestStart()
+{
+    ACE_DEBUG((LM_INFO, ACE_TEXT("\nRunning Site Manager tests.\n")));
+}
+
+void TestSiteManager::TestEnd()
+{
+    ACE_DEBUG((LM_INFO, ACE_TEXT("\nSite Manager tests
completed.\n\n")));
+}
+
+///--------------------------------------------------------------------
--------
+/// Test Case Description:
+///
+/// This test case checks to see if there is a valid MgSiteManager and
that
+/// there is only 1 MgSiteManager.
+///--------------------------------------------------------------------
--------
+void TestSiteManager::TestCase_ValidSiteManager()
+{
+    MgSiteManager* pMgSiteManager = MgSiteManager::GetInstance();
+    CPPUNIT_ASSERT(pMgSiteManager != NULL);
+
+    MgSiteManager* pMgSiteManager2 = MgSiteManager::GetInstance();
+    CPPUNIT_ASSERT(pMgSiteManager == pMgSiteManager2);
+}
+
+///--------------------------------------------------------------------
--------
+/// Test Case Description:
+///
+/// Get the MgConnectionProperties for a site connection
+///--------------------------------------------------------------------
--------
+void TestSiteManager::TestCase_GetSiteConnectionProperties()
+{
+    try
+    {
+        // Get the site manager instance
+        MgSiteManager* pSiteManager = MgSiteManager::GetInstance();
+        
+        // Create admin user info
+        Ptr<MgUserInformation> userInfo = new
MgUserInformation(L"Administrator", L"admin");
+        
+        // Get connection properties
+        Ptr<MgConnectionProperties> connProps =
pSiteManager->GetConnectionProperties(userInfo, MgSiteInfo::Site,
false);
+
+        // Verify that we received connection properties
+        CPPUNIT_ASSERT(connProps != NULL);
+       
+    }
+    catch(MgException* e)
+    {
+        STRING message = e->GetDetails(TEST_LOCALE);
+        SAFE_RELEASE(e);
+        CPPUNIT_FAIL(MG_WCHAR_TO_CHAR(message.c_str()));
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+///--------------------------------------------------------------------
--------
+/// Test Case Description:
+///
+/// Get the MgConnectionProperties for a site connection when the user
info
+/// contains a session ID
+///--------------------------------------------------------------------
--------
+void TestSiteManager::TestCase_GetSiteConnectionPropertiesWithSession()
+{
+    try
+    {
+        // Get the site manager instance
+        MgSiteManager* pSiteManager = MgSiteManager::GetInstance();
+        
+        // Create admin user info
+        Ptr<MgUserInformation> userInfo = new
MgUserInformation(L"Administrator", L"admin");
+        userInfo->SetMgSessionId(TEST_SESSION_ID);
+        
+        // Get connection properties, allowing overrides from the
session ID
+        Ptr<MgConnectionProperties> connPropsSite =
pSiteManager->GetConnectionProperties(userInfo, MgSiteInfo::Site, true);
+        Ptr<MgConnectionProperties> connPropsClient =
pSiteManager->GetConnectionProperties(userInfo, MgSiteInfo::Client,
true);
+        Ptr<MgConnectionProperties> connPropsAdmin =
pSiteManager->GetConnectionProperties(userInfo, MgSiteInfo::Admin,
true);
+
+        // Verify that the connection properties match those in the
session ID
+        CPPUNIT_ASSERT(connPropsSite != NULL && connPropsClient != NULL
&& connPropsAdmin != NULL);
+        CPPUNIT_ASSERT(connPropsSite->GetTarget() == TEST_TARGET);
+        CPPUNIT_ASSERT(connPropsSite->GetPort() == TEST_SITE_PORT);
+        CPPUNIT_ASSERT(connPropsClient->GetPort() == TEST_CLIENT_PORT);
+        CPPUNIT_ASSERT(connPropsAdmin->GetPort() == TEST_ADMIN_PORT);
+    }
+    catch(MgException* e)
+    {
+        STRING message = e->GetDetails(TEST_LOCALE);
+        SAFE_RELEASE(e);
+        CPPUNIT_FAIL(MG_WCHAR_TO_CHAR(message.c_str()));
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+///--------------------------------------------------------------------
--------
+/// Test Case Description:
+///
+/// Get the MgConnectionProperties for a site connection when the user
info
+/// contains a session ID, but that ID is not to be used to override
the
+/// connection parameters
+///--------------------------------------------------------------------
--------
+void
TestSiteManager::TestCase_GetSiteConnectionPropertiesIgnoreSession()
+{
+    try
+    {
+        // Get the site manager instance
+        MgSiteManager* pSiteManager = MgSiteManager::GetInstance();
+        
+        // Create admin user info
+        Ptr<MgUserInformation> userInfo = new
MgUserInformation(L"Administrator", L"admin");
+        userInfo->SetMgSessionId(TEST_SESSION_ID);
+        
+        // Get connection properties without allowing overrides from
the session ID
+        Ptr<MgConnectionProperties> connPropsSite =
pSiteManager->GetConnectionProperties(userInfo, MgSiteInfo::Site,
false);
+
+        CPPUNIT_ASSERT(connPropsSite != NULL);
+        CPPUNIT_ASSERT(connPropsSite->GetTarget() != TEST_TARGET);
+    }
+    catch(MgException* e)
+    {
+        STRING message = e->GetDetails(TEST_LOCALE);
+        SAFE_RELEASE(e);
+        CPPUNIT_FAIL(MG_WCHAR_TO_CHAR(message.c_str()));
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+///--------------------------------------------------------------------
--------
+/// Test Case Description:
+///
+/// Get a connection to a site specified in an MgSiteInfo object
+///--------------------------------------------------------------------
--------
+void TestSiteManager::TestCase_GetSpecificSiteConnectionProperties()
+{
+    try
+    {
+        // Get the site manager instance
+        MgSiteManager* pSiteManager = MgSiteManager::GetInstance();
+        
+        // Create admin user info
+        Ptr<MgUserInformation> userInfo = new
MgUserInformation(L"Administrator", L"admin");
+
+        // Create MgSiteInfo object
+        Ptr<MgSiteInfo> siteInfo = new MgSiteInfo(TEST_TARGET,
TEST_SITE_PORT, TEST_CLIENT_PORT, TEST_ADMIN_PORT);
+        
+        // Get connection properties for the specified site
+        Ptr<MgConnectionProperties> connPropsSite =
pSiteManager->GetConnectionProperties(userInfo, siteInfo,
MgSiteInfo::Admin);
+
+        CPPUNIT_ASSERT(connPropsSite != NULL);
+        CPPUNIT_ASSERT(connPropsSite->GetTarget() == TEST_TARGET);
+        CPPUNIT_ASSERT(connPropsSite->GetPort() == TEST_ADMIN_PORT);
+    }
+    catch(MgException* e)
+    {
+        STRING message = e->GetDetails(TEST_LOCALE);
+        SAFE_RELEASE(e);
+        CPPUNIT_FAIL(MG_WCHAR_TO_CHAR(message.c_str()));
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+///--------------------------------------------------------------------
--------
+/// Test Case Description:
+///
+/// Get a connection to a support server. The support server IP is
specified
+/// in the request, but the port is the one used by the site server.
+///--------------------------------------------------------------------
--------
+void TestSiteManager::TestCase_GetSupportServerConnectionProperties()
+{
+    try
+    {
+        // Get the site manager instance
+        MgSiteManager* pSiteManager = MgSiteManager::GetInstance();
+        
+        // Create admin user info
+        Ptr<MgUserInformation> userInfo = new
MgUserInformation(L"Administrator", L"admin");
+        userInfo->SetMgSessionId(TEST_SESSION_ID);
+
+        // Create MgSiteInfo object
+        Ptr<MgSiteInfo> siteInfo = new MgSiteInfo(TEST_TARGET,
TEST_SITE_PORT, TEST_CLIENT_PORT, TEST_ADMIN_PORT);
+        
+        // Get connection properties for the specified site
+        Ptr<MgConnectionProperties> connPropsSite =
pSiteManager->GetSupportServerConnectionProperties(TEST_SUPPORT_SERVER,
userInfo, MgSiteInfo::Site);
+
+        // The port should come from the site stored in the session ID.
The target should be the support server IP.
+        CPPUNIT_ASSERT(connPropsSite != NULL);
+        CPPUNIT_ASSERT(connPropsSite->GetTarget() ==
TEST_SUPPORT_SERVER);
+        CPPUNIT_ASSERT(connPropsSite->GetPort() == TEST_SITE_PORT);
+    }
+    catch(MgException* e)
+    {
+        STRING message = e->GetDetails(TEST_LOCALE);
+        SAFE_RELEASE(e);
+        CPPUNIT_FAIL(MG_WCHAR_TO_CHAR(message.c_str()));
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+///--------------------------------------------------------------------
--------
+/// Test Case Description:
+///
+/// Get an MgSiteInfo object representing the connection properties for
this
+/// site server
+///--------------------------------------------------------------------
--------
+void TestSiteManager::TestCase_GetSiteInfo()
+{
+    try
+    {
+        // Get the site manager instance
+        MgSiteManager* pSiteManager = MgSiteManager::GetInstance();
+
+        // Get the number of site servers
+        Ptr<MgSiteInfo> siteInfo = pSiteManager->GetSiteInfo(0);

+
+        // Verify that we received a valid site info object
+        CPPUNIT_ASSERT(siteInfo != NULL);
+        CPPUNIT_ASSERT(siteInfo->GetTarget() != L"");
+    }
+    catch(MgException* e)
+    {
+        STRING message = e->GetDetails(TEST_LOCALE);
+        SAFE_RELEASE(e);
+        CPPUNIT_FAIL(MG_WCHAR_TO_CHAR(message.c_str()));
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+///--------------------------------------------------------------------
--------
+/// Test Case Description:
+///
+/// Get the number of site servers configured in the INI file. Should
always be
+/// 1 for serverconfig.ini.
+///--------------------------------------------------------------------
--------
+void TestSiteManager::TestCase_GetSiteCount()
+{
+    try
+    {
+        // Get the site manager instance
+        MgSiteManager* pSiteManager = MgSiteManager::GetInstance();
+
+        // Get the number of site servers
+        INT32 numSites = pSiteManager->GetSiteCount();        
+
+        // The number of sites should always be 1 on the server. 
+        // It can be greater than 1 in the web tier.
+        CPPUNIT_ASSERT(numSites == 1);
+    }
+    catch(MgException* e)
+    {
+        STRING message = e->GetDetails(TEST_LOCALE);
+        SAFE_RELEASE(e);
+        CPPUNIT_FAIL(MG_WCHAR_TO_CHAR(message.c_str()));
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
Index: Server/src/UnitTesting/Makefile.am
===================================================================
--- Server/src/UnitTesting/Makefile.am	(revision 1039)
+++ Server/src/UnitTesting/Makefile.am	(revision 1040)
@@ -38,6 +38,7 @@
   TestServiceManager.cpp \
   TestSiteService.cpp \
   TestTileService.cpp \
+  TestSiteManager.cpp \
   UnitTesting.cpp
 
 noinst_HEADERS = \
@@ -55,6 +56,7 @@
   TestServiceManager.h \
   TestSiteService.h \
   TestTileService.h \
+  TestSiteManager.h \
   UnitTesting.h
 
 libMgUnitTesting_la_LIBADD = -lcppunit
Index: Web/src/MapGuideApi/MapGuideApiGen.xml
===================================================================
--- Web/src/MapGuideApi/MapGuideApiGen.xml	(revision 1039)
+++ Web/src/MapGuideApi/MapGuideApiGen.xml	(revision 1040)
@@ -258,6 +258,7 @@
     <Header
path="../../../Common/PlatformBase/Services/BaseService.h"/>
     <Header path="../../../Common/PlatformBase/Services/Service.h"/>
     <Header path="../../../Common/MapGuideCommon/Services/Site.h"/>
+    <Header path="../../../Common/MapGuideCommon/Services/SiteInfo.h"/>
     <Header
path="../../../Common/MapGuideCommon/Services/SiteConnection.h"/>
     <Header
path="../../../Common/PlatformBase/Services/ResourceIdentifier.h"/>
     <Header
path="../../../Common/PlatformBase/Services/ResourceService.h"/>
Index: Web/src/mapadmin/makepackage.php
===================================================================
--- Web/src/mapadmin/makepackage.php	(revision 1039)
+++ Web/src/mapadmin/makepackage.php	(revision 1040)
@@ -28,9 +28,8 @@
         global $site;
         global $userInfo;
 		
-        $siteServerAddress = $site->GetSiteServerAddress();
         $serverAdmin = new MgServerAdmin();
-        $serverAdmin->Open( $siteServerAddress, $userInfo );
+        $serverAdmin->Open( $userInfo );
 		
 		// Make sure folder name begins with "Library://" and
ends with "/"
 		if ( ( strcasecmp( "Library", $folderName ) == 0 ) || (
strcasecmp( "Library:", $folderName ) == 0 ) )
Index: Web/src/mapadmin/serverdatafunctions.php
===================================================================
--- Web/src/mapadmin/serverdatafunctions.php	(revision 1039)
+++ Web/src/mapadmin/serverdatafunctions.php	(revision 1040)
@@ -623,7 +623,7 @@
 
         // Put Site Server in $targetTable.
         $serverRec = new ServerTableRecord( "Site Server", "" );
-        $serverKey = $site->GetSiteServerAddress();
+        $serverKey = $site->GetCurrentSiteAddress();
         $targetTable[ $serverKey ] = $serverRec;
 
         $dbData = $site->EnumerateServers();
@@ -642,7 +642,6 @@
             $targetTable[ $key ] = $val;
 
         // Get values for Online and Services fields
-        $siteServerAddress = $site->GetSiteServerAddress();
         foreach ( $targetTable as $key => $val )
         {
             try
@@ -1789,9 +1788,8 @@
         global $site;
         global $userInfo;
 
-        $siteServerAddress = $site->GetSiteServerAddress();
         $serverAdmin = new MgServerAdmin();
-        $serverAdmin->Open( $siteServerAddress, $userInfo );
+        $serverAdmin->Open( $userInfo );
 
         // Call server to get comprehensive list of packages.
 
@@ -1836,9 +1834,8 @@
             return false;
 
         // Delete the package
-        $siteServerAddress = $site->GetSiteServerAddress();
         $serverAdmin = new MgServerAdmin();
-        $serverAdmin->Open( $siteServerAddress, $userInfo );
+        $serverAdmin->Open( $userInfo );
         $serverAdmin->DeletePackage( $packageName );
         $serverAdmin->Close();
 
@@ -1865,9 +1862,8 @@
         $targetTable = array();
         $packages = GetPackageList();
 
-        $siteServerAddress = $site->GetSiteServerAddress();
         $serverAdmin = new MgServerAdmin();
-        $serverAdmin->Open( $siteServerAddress, $userInfo );
+        $serverAdmin->Open( $userInfo );
 
         $iPackage = -1;
         foreach ( $packages as $val )
@@ -1951,9 +1947,8 @@
             global $errInvalidWMSFile;
 
             // Get WMS reader
-            $siteServer = $site->GetSiteServerAddress();
             $serverAdmin = new MgServerAdmin();
-            $serverAdmin->Open( $siteServer, $userInfo );
+            $serverAdmin->Open( $userInfo );
             $wmsReader = $serverAdmin->GetDocument(
'Wms:OgcWmsService.config' );
             $serverAdmin->Close();
 
@@ -2008,9 +2003,8 @@
             global $errInvalidWMSFile;
 
             // Get WMS reader
-            $siteServer = $site->GetSiteServerAddress();
             $serverAdmin = new MgServerAdmin();
-            $serverAdmin->Open( $siteServer, $userInfo );
+            $serverAdmin->Open( $userInfo );
             $wmsReader = $serverAdmin->GetDocument(
'Wms:OgcWmsService.config' );
 
             // Set WMS metadata
@@ -2111,9 +2105,8 @@
             global $errInvalidWFSFile;
 
             // Get WFS reader
-            $siteServer = $site->GetSiteServerAddress();
             $serverAdmin = new MgServerAdmin();
-            $serverAdmin->Open( $siteServer, $userInfo );
+            $serverAdmin->Open( $userInfo );
             $wfsReader = $serverAdmin->GetDocument(
'Wfs:OgcWfsService.config' );
             $serverAdmin->Close();
 
@@ -2168,9 +2161,8 @@
             global $errInvalidWFSFile;
 
             // Get WFS reader
-            $siteServer = $site->GetSiteServerAddress();
             $serverAdmin = new MgServerAdmin();
-            $serverAdmin->Open( $siteServer, $userInfo );
+            $serverAdmin->Open( $userInfo );
             $wfsReader = $serverAdmin->GetDocument(
'Wfs:OgcWfsService.config' );
 
             // Set WFS metadata
Index: Web/src/mapadmin/servermanagement.php
===================================================================
--- Web/src/mapadmin/servermanagement.php	(revision 1039)
+++ Web/src/mapadmin/servermanagement.php	(revision 1040)
@@ -65,8 +65,8 @@
     $currPage = 1;
 
 
-    $siteServerAddress = $site->GetSiteServerAddress();
-
+    $siteServerAddress = $site->GetCurrentSiteAddress();
+ 
     if ( array_key_exists( $selectedServerID, $_POST ) )
     {
         $selectedServer = $_POST[ $selectedServerID ];
Index: Web/src/mapadmin/login.php
===================================================================
--- Web/src/mapadmin/login.php	(revision 1039)
+++ Web/src/mapadmin/login.php	(revision 1040)
@@ -29,10 +29,12 @@
         $homePage = NULL;
         $adminID = "";
         $adminIDID = 'adminID';
+        $serverSelectionID = 'SiteServer';
         $adminPassword = "";
         $adminPasswordID = 'adminPassword';
         $locale = "en"; // localizable string
         $errorMsg = "";
+        $numSites = 0;
 
         if ( FirstTimeHere( $pageName ) )
         {
@@ -75,21 +77,57 @@
             $userInfo->SetClientAgent( $clientAgent );
             $clientIp = array_key_exists( 'REMOTE_ADDR', $_SERVER ) ?
$_SERVER['REMOTE_ADDR'] : "";
             $userInfo->SetClientIp( $clientIp );
-
+            
             // Create a Site object and open the Site Server.
             $site = new MgSite();
             $site->Open( $userInfo );
-
+            
             // Check that we have Administrator permission.
             $servers = $site->EnumerateServers();
+            
+            // Determine the available site servers
+            $numSites = $site->GetSiteServerCount();
+            
+            if($numSites == 1)
+            {
+                // Create session
+                $adminSession = $site->CreateSession();
+                
+                // Save session variables
+                SaveSessionVars();
+                
+                // Success - switch to ServerManagement page.
+                header( 'Location:
servermanagement.php?'.strip_tags(SID) );
+                exit();
+            }
+            else
+            {
+                $siteInfo = GetSiteServerSelection($serverSelectionID);
+                if($siteInfo != NULL)
+                {            
+                    // Close the existing site connection
+                    if($site != NULL)
+                    {
+                        $site->Close();
+                    }
+                    
+                    // Determine the selected site
+                    $site = new MgSite();
+                        
+                    // Create a connection to the selected site
+                    $site->Open($userInfo, $siteInfo);
+                    
+                    // Create a session
+                    $adminSession = $site->CreateSession();
+                    $userInfo->SetMgSessionId($adminSession);
 
-            // Create session
-            $adminSession = $site->CreateSession();
-
-            // Success - switch to ServerManagement page.
-            SaveSessionVars();
-            header( 'Location:  servermanagement.php?'.strip_tags(SID)
);
-            exit();
+                    // Save the session variables. All requests will
now be directed to
+                    // our selected server since it hosts the current
session.
+                    SaveSessionVars();
+                    header( 'Location:
servermanagement.php?'.strip_tags(SID) );
+                    exit();
+                }
+            }
         }
     }
     catch ( MgException $e )
@@ -128,6 +166,15 @@
 
                 <!-- Input Area -->
                 <table border="0" cellspacing="0" class="inputForm">
+                    <?php
+                    if($site != NULL && $numSites > 1)
+                    {
+                        echo '<tr><td class="loginInputLabel">Site
Server:</td>', "\n";
+                        echo '<td class="loginInputFormValue">';
+                        DisplaySiteServerSelector($serverSelectionID);
+                        echo '</td></tr>', "\n";
+                    }
+                    ?>
                     <tr>
                         <td class="loginInputLabel">Administrator
ID:</td>
                         <td class="loginInputFormValue"><input
class="loginInputFormValue" name="<?php echo $adminIDID?>" type="text"
class="TableCell" size="50" value="<?php echo $adminID ?>"></td>
Index: Web/src/mapadmin/resizablepagecomponents.php
===================================================================
--- Web/src/mapadmin/resizablepagecomponents.php	(revision 1039)
+++ Web/src/mapadmin/resizablepagecomponents.php	(revision 1040)
@@ -67,6 +67,7 @@
     define( 'CONFIGURE_LOGS_TITLE',             "Configure Logs" );
     define( 'CONFIGURE_SERVICES_TITLE',         "Configure Services" );
     define( 'LOG_MANAGEMENT_TITLE',             "Manage Logs" );
+    define( 'SELECT_SITE_SERVER_TITLE',         "Select Site Server" );
 
     define( 'ADD_GROUP_TITLE',                  "Add Group" );
     define( 'EDIT_GROUP_TITLE',                 "Edit Group" );
@@ -454,7 +455,64 @@
             echo '<br>',"\n";
         }
     }
+    
+    function DisplaySiteServerSelector( $selectedSiteServerID )
+    {
+        global $site;
+        
+        echo '<select class="serverSelector"
name="',$selectedSiteServerID.NO_PERSISTENCE_FLAG,'" size="1" >', "\n";
+        for($i = 0; $i < $site->GetSiteServerCount(); $i++)
+        {
+            $selectedStr = "";
+            $siteInfo = $site->GetSiteServerInfo($i);
+            if($siteInfo != NULL)
+            {
+                $target = $siteInfo->GetTarget();
+                $port = $siteInfo->GetPort(MgSiteInfo_Admin);
+                echo '<option class="serverSelector"
',$selectedStr,'>',$target,':',$port,'</option>', "\n";
+            }
+        }
+        echo '</select>', "\n";
+    }
+    
+    function GetSiteServerSelection( $selectedSiteServerID )
+    {
+        global $site;
+        global $_POST;
+        global $_GET;
+        global $errNotFound;
+        $selectedSite = NULL;
+        $selectedSiteServerName = "";
+        if ( array_key_exists(
$selectedSiteServerID.NO_PERSISTENCE_FLAG, $_POST ) )
+        {
+            $selectedSiteServerName = $_POST[
$selectedSiteServerID.NO_PERSISTENCE_FLAG ];
+        }
+        else
+        {
+            if ( array_key_exists( $selectedSiteServerID, $_GET ) )
+                $selectedSiteServerName = $_GET[ $selectedSiteServerID
];
+        }
+        if($site != NULL && $selectedSiteServerName != "")
+        {
+            for($i = 0; $i < $site->GetSiteServerCount(); $i++)
+            {
+                $siteInfo = $site->GetSiteServerInfo($i);
+                if($siteInfo != NULL)
+                {
+                    $target = $siteInfo->GetTarget();
+                    $port = $siteInfo->GetPort(MgSiteInfo_Admin);
+                    $id = $target.":".strval($port);
+                    if($id == $selectedSiteServerName)
+                    {
+                        $selectedSite = $siteInfo;
+                    }
+                }
+            }
+        }
+        return $selectedSite;
+    }
 
+
     class ToolbarButtonRecord
     {
         var $id;
@@ -763,7 +821,8 @@
         if ( $serviceSelector == NULL )
             return;
 
-        if ( $serviceSelector->serverAddress ==
$site->GetSiteServerAddress() )
+        $siteServerAddress = $site->GetCurrentSiteAddress();
+        if ( $serviceSelector->serverAddress == $siteServerAddress )
         {
             echo '<input type="checkbox" checked disabled>Site<br>',
"\n";
             echo '<input type="checkbox" checked disabled><a
href="servicesproperties.php?Server=',$serviceSelector->serverAddress,'"
>Resource</a><br>', "\n";
Index: Web/src/mapadmin/packagemanagement.php
===================================================================
--- Web/src/mapadmin/packagemanagement.php	(revision 1039)
+++ Web/src/mapadmin/packagemanagement.php	(revision 1040)
@@ -64,9 +64,9 @@
 	// Construct suggestedPackageName
 	$dateData = getdate();
 	$dateStr = sprintf( "%04u%02u%02u", $dateData[ 'year' ],
$dateData[ 'mon' ], $dateData[ 'mday' ] );
-	$siteServer = $site->GetSiteServerAddress();
+	$siteServer = $site->GetCurrentSiteAddress();
 	$serverAdmin = new MgServerAdmin();
-    $serverAdmin->Open( $siteServer, $userInfo );
+    $serverAdmin->Open( $userInfo );
 	$genProps = new GeneralPropsRecord();
     $genProps->GetProps( $serverAdmin );
 	$serverAdmin->Close();
Index: Web/src/mapadmin/loadpackage.php
===================================================================
--- Web/src/mapadmin/loadpackage.php	(revision 1039)
+++ Web/src/mapadmin/loadpackage.php	(revision 1040)
@@ -28,9 +28,8 @@
         global $site;
         global $userInfo;
 
-        $siteServerAddress = $site->GetSiteServerAddress();
         $serverAdmin = new MgServerAdmin();
-        $serverAdmin->Open( $siteServerAddress, $userInfo );
+        $serverAdmin->Open( $userInfo );
 
         set_time_limit(0);
         $serverAdmin->LoadPackage( $packageName );
Index: Web/src/mapadmin/servicesproperties.php
===================================================================
--- Web/src/mapadmin/servicesproperties.php	(revision 1039)
+++ Web/src/mapadmin/servicesproperties.php	(revision 1040)
@@ -50,9 +50,8 @@
     $pageEnabled = false;
     $bSiteServer = false;
 
-
     // Get Server
-    $siteServerAddress = $site->GetSiteServerAddress();
+    $siteServerAddress = $site->GetCurrentSiteAddress();
     GetServerSelection( $selectedServerID, $selectedServer );
     $serverRec = GetDataForServer( $selectedServer );
     if ( $serverRec == NULL )
Index: Web/src/mapadmin/about.php
===================================================================
--- Web/src/mapadmin/about.php	(revision 1039)
+++ Web/src/mapadmin/about.php	(revision 1040)
@@ -32,9 +32,8 @@
         $appVersion = SITE_ADMINISTRATOR_VERSION;
         $errorMsg = "";
 
-        $siteServerAddress = $site->GetSiteServerAddress();
         $serverAdmin = new MgServerAdmin();
-        $serverAdmin->Open( $siteServerAddress, $userInfo );
+        $serverAdmin->Open( $userInfo );
         $serverVersion = GetVersion( $serverAdmin );
     }
     catch ( MgException $e )
Index: Web/src/mapadmin/displaypackagelog.php
===================================================================
--- Web/src/mapadmin/displaypackagelog.php	(revision 1039)
+++ Web/src/mapadmin/displaypackagelog.php	(revision 1040)
@@ -30,9 +30,8 @@
         global $site;
         global $userInfo;
 
-        $siteServerAddress = $site->GetSiteServerAddress();
         $serverAdmin = new MgServerAdmin();
-        $serverAdmin->Open( $siteServerAddress, $userInfo );
+        $serverAdmin->Open( $userInfo );
         $logReader = $serverAdmin->GetPackageLog( $packageName );
         $serverAdmin->Close();
 
Index: Web/src/mapadmin/serverproperties.php
===================================================================
--- Web/src/mapadmin/serverproperties.php	(revision 1039)
+++ Web/src/mapadmin/serverproperties.php	(revision 1040)
@@ -76,7 +76,7 @@
 
 
     // Get Server
-    $siteServer = $site->GetSiteServerAddress();
+    $siteServerAddress = $site->GetCurrentSiteAddress();
     GetServerSelection( $selectedServerID, $selectedServer );
     $serverRec = GetDataForServer( $selectedServer );
     if ( $serverRec == NULL )
@@ -86,7 +86,7 @@
 
     // Are we configuring the site or a support server?
     $pageEnabled = true;
-    $configuringSupportServer = $siteServer != $selectedServer;
+    $configuringSupportServer = $siteServerAddress != $selectedServer;
 
     // Is a refresh needed?
     if ( FirstTimeHere( $pageName ) )
Index: Web/src/HttpHandler/HttpGetSiteVersion.cpp
===================================================================
--- Web/src/HttpHandler/HttpGetSiteVersion.cpp	(revision 1039)
+++ Web/src/HttpHandler/HttpGetSiteVersion.cpp	(revision 1040)
@@ -51,14 +51,9 @@
     // Check common parameters
     ValidateCommonParameters();
 
-    // Open connection to Mg server
-    Ptr<MgSite> mgSite = m_siteConn->GetSite();
-
-    STRING serverAddress = mgSite->GetSiteServerAddress();
-
     // Create ServerAdmin object
     Ptr<MgServerAdmin> serverAdmin = new MgServerAdmin();
-    serverAdmin->Open(serverAddress, m_userInfo);
+    serverAdmin->Open(m_userInfo);
 
     // call the C++ APIs
     Ptr<MgPropertyCollection> properties =
serverAdmin->GetInformationProperties();
Index: Web/src/HttpHandler/HttpWmsGetCapabilities.cpp
===================================================================
--- Web/src/HttpHandler/HttpWmsGetCapabilities.cpp	(revision 1039)
+++ Web/src/HttpHandler/HttpWmsGetCapabilities.cpp	(revision 1040)
@@ -47,13 +47,8 @@
 {
     //TODO: Remove dependency on thread local storage
     MgUserInformation* userInfo =
MgUserInformation::GetCurrentUserInfo();
-    Ptr<MgSite> mgSite;
-    mgSite = new MgSite();
-    mgSite->Open(userInfo);
-    STRING serverAddress = mgSite->GetSiteServerAddress();
-
     Ptr<MgServerAdmin> serverAdmin = new MgServerAdmin();
-    serverAdmin->Open(serverAddress,userInfo);
+    serverAdmin->Open(userInfo);
 
     Ptr<MgByteReader> brDoc;
     brDoc = serverAdmin->GetDocument(pszDoc);
Index: Web/src/HttpHandler/HttpGetSiteInfo.cpp
===================================================================
--- Web/src/HttpHandler/HttpGetSiteInfo.cpp	(revision 1039)
+++ Web/src/HttpHandler/HttpGetSiteInfo.cpp	(revision 1040)
@@ -51,14 +51,9 @@
     // Check common parameters
     ValidateCommonParameters();
 
-    // Open connection to Mg server
-    Ptr<MgSite> mgSite = m_siteConn->GetSite();
-
-    STRING serverAddress = mgSite->GetSiteServerAddress();
-
     // Create ServerAdmin object
     Ptr<MgServerAdmin> serverAdmin = new MgServerAdmin();
-    serverAdmin->Open(serverAddress, m_userInfo);
+    serverAdmin->Open(m_userInfo);
 
     // call the C++ APIs
     Ptr<MgPropertyCollection> properties =
serverAdmin->GetInformationProperties();
Index: Web/src/HttpHandler/WmsMapUtil.cpp
===================================================================
--- Web/src/HttpHandler/WmsMapUtil.cpp	(revision 1039)
+++ Web/src/HttpHandler/WmsMapUtil.cpp	(revision 1040)
@@ -47,13 +47,8 @@
 {
     //TODO: Remove dependency on thread local storage
     MgUserInformation* userInfo =
MgUserInformation::GetCurrentUserInfo();
-    Ptr<MgSite> mgSite;
-    mgSite = new MgSite();
-    mgSite->Open(userInfo);
-    STRING serverAddress = mgSite->GetSiteServerAddress();
-
     Ptr<MgServerAdmin> serverAdmin = new MgServerAdmin();
-    serverAdmin->Open(serverAddress,userInfo);
+    serverAdmin->Open(userInfo);
 
     Ptr<MgByteReader> brDoc;
     brDoc = serverAdmin->GetDocument(pszDoc);

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.osgeo.org/pipermail/mapguide-internals/attachments/20070111/7861d1d2/attachment.html


More information about the Mapguide-internals mailing list