[mapguide-commits] r4731 - in sandbox/rfc90/MgDev: Common/MapGuideCommon/System Server/src/Core Server/src/Services/Tile

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Thu Apr 1 01:05:30 EDT 2010


Author: uvlite
Date: 2010-04-01 01:05:29 -0400 (Thu, 01 Apr 2010)
New Revision: 4731

Modified:
   sandbox/rfc90/MgDev/Common/MapGuideCommon/System/ConfigProperties.cpp
   sandbox/rfc90/MgDev/Common/MapGuideCommon/System/ConfigProperties.h
   sandbox/rfc90/MgDev/Server/src/Core/ServerCore.vcproj
   sandbox/rfc90/MgDev/Server/src/Core/serverconfig.ini
   sandbox/rfc90/MgDev/Server/src/Services/Tile/ServerTileService.cpp
   sandbox/rfc90/MgDev/Server/src/Services/Tile/ServerTileService.h
   sandbox/rfc90/MgDev/Server/src/Services/Tile/TileCache.cpp
   sandbox/rfc90/MgDev/Server/src/Services/Tile/TileCache.h
Log:
rfc90 added lock strategy 3 using ace_condition to synchronize subtiles & metatiles

Modified: sandbox/rfc90/MgDev/Common/MapGuideCommon/System/ConfigProperties.cpp
===================================================================
--- sandbox/rfc90/MgDev/Common/MapGuideCommon/System/ConfigProperties.cpp	2010-03-31 23:00:45 UTC (rev 4730)
+++ sandbox/rfc90/MgDev/Common/MapGuideCommon/System/ConfigProperties.cpp	2010-04-01 05:05:29 UTC (rev 4731)
@@ -377,6 +377,8 @@
 const STRING MgConfigProperties::DefaultTileServicePropertyImageFormat                      = L"PNG";
 const STRING MgConfigProperties::TileServicePropertyUseMetaTiles                            = L"UseMetaTiles";
 const INT32 MgConfigProperties::DefaultTileServicePropertyUseMetaTiles                      = 0;
+const STRING MgConfigProperties::TileServicePropertyLockMethod                              = L"LockMethod";
+const INT32 MgConfigProperties::DefaultTileServicePropertyLockMethod                        = 0;
 
 // ******************************************************************
 // Access Log Properties

Modified: sandbox/rfc90/MgDev/Common/MapGuideCommon/System/ConfigProperties.h
===================================================================
--- sandbox/rfc90/MgDev/Common/MapGuideCommon/System/ConfigProperties.h	2010-03-31 23:00:45 UTC (rev 4730)
+++ sandbox/rfc90/MgDev/Common/MapGuideCommon/System/ConfigProperties.h	2010-04-01 05:05:29 UTC (rev 4731)
@@ -514,6 +514,10 @@
     static const STRING TileServicePropertyUseMetaTiles;                /// value("UseMetaTiles")
     static const INT32 DefaultTileServicePropertyUseMetaTiles;          /// value(0)
 
+        /// Sets the lock strategy  for metatiles 
+    static const STRING TileServicePropertyLockMethod;                /// value("LockMethod")
+    static const INT32 DefaultTileServicePropertyLockMethod;          /// value(0)
+
 EXTERNAL_API:
 
     //////////////////////////////////////////////////////////////////

Modified: sandbox/rfc90/MgDev/Server/src/Core/ServerCore.vcproj
===================================================================
--- sandbox/rfc90/MgDev/Server/src/Core/ServerCore.vcproj	2010-03-31 23:00:45 UTC (rev 4730)
+++ sandbox/rfc90/MgDev/Server/src/Core/ServerCore.vcproj	2010-04-01 05:05:29 UTC (rev 4731)
@@ -1031,6 +1031,10 @@
 			>
 		</File>
 		<File
+			RelativePath=".\serverconfig.ini"
+			>
+		</File>
+		<File
 			RelativePath=".\ServerCore.rc"
 			>
 		</File>

Modified: sandbox/rfc90/MgDev/Server/src/Core/serverconfig.ini
===================================================================
--- sandbox/rfc90/MgDev/Server/src/Core/serverconfig.ini	2010-03-31 23:00:45 UTC (rev 4730)
+++ sandbox/rfc90/MgDev/Server/src/Core/serverconfig.ini	2010-04-01 05:05:29 UTC (rev 4731)
@@ -1,4 +1,4 @@
-# *****************************************************************************
+# *****************************************************************************
 # MapGuide Server Configuration File
 #
 # The following configuration is based on a single CPU with a single core.
@@ -367,8 +367,8 @@
 # *****************************************************************************
 #LibraryRepositoryPath              = Repositories/Library/
 #LibraryResourceDataFilePath        = Repositories/Library/DataFiles/
-LibraryRepositoryPath              = C:\Program Files\MapGuideOpenSource2.0\Server\Repositories\BigLibrary\
-LibraryResourceDataFilePath        = C:\Program Files\MapGuideOpenSource2.0\Server\Repositories\BigLibrary\DataFiles\
+LibraryRepositoryPath              =C:\Program Files\OSGeo\MapGuide\Server\Repositories\BigLibrary\
+LibraryResourceDataFilePath        =C:\Program Files\OSGeo\MapGuide\Server\Repositories\BigLibrary\DataFiles\
 PackagesPath                       = Packages/
 RepositoryCheckpointsTimerInterval = 600
 ResourceChangeTimerInterval        = 5
@@ -414,13 +414,16 @@
 #                                       50 < value <= 10000
 # ImageFormat                      Image format for generated tiles
 #                                       PNG, PNG8, GIF or JPG
-# PollingInterval									 sleep in milliseconds before rechecking the lockfile
-# CreationCutoffTime							 seconds after which abort the lockfile test
+# PollingInterval                  sleep in milliseconds before rechecking the lockfile
+# CreationCutoffTime               seconds after which abort the lockfile test
+# LockMethod                       0/1=use lockfile/tile 2=lockfile/metatile 
+#                                  3=ace_condition/metatile
 # *****************************************************************************
-RenderOnly                         = 1
+RenderOnly                         = 0
 PollingInterval                    = 500
 CreationCutoffTime                 = 120
-UseMetaTiles                       = 0
+UseMetaTiles                       = 4
+LockMethod                         = 3
 TileCachePath                      = Repositories/TileCache/
 TileColumnsPerFolder               = 30
 TileRowsPerFolder                  = 30

Modified: sandbox/rfc90/MgDev/Server/src/Services/Tile/ServerTileService.cpp
===================================================================
--- sandbox/rfc90/MgDev/Server/src/Services/Tile/ServerTileService.cpp	2010-03-31 23:00:45 UTC (rev 4730)
+++ sandbox/rfc90/MgDev/Server/src/Services/Tile/ServerTileService.cpp	2010-04-01 05:05:29 UTC (rev 4731)
@@ -19,9 +19,11 @@
 #include "ServerTileService.h"
 #include "ServerRenderingService.h"
 #include <sstream>
+
 IMPLEMENT_CREATE_SERVICE(MgServerTileService)
 
 ACE_Recursive_Thread_Mutex MgServerTileService::sm_mutex;
+ACE_Recursive_Thread_Mutex MgServerTileService::sm_tileMutex;
 bool MgServerTileService::sm_initialized = false;
 MgServerTileService::MapCache MgServerTileService::sm_mapCache;
 bool MgServerTileService::sm_renderOnly = false;
@@ -29,6 +31,7 @@
 INT32 MgServerTileService::sm_pollingInterval = 1;          // in seconds
 INT32 MgServerTileService::sm_mapCacheSize = 10;
 INT32 MgServerTileService::sm_useMetaTiles = 0;
+INT32 MgServerTileService::sm_lockMethod = 0;
 
 MgServerTileService::MgServerTileService() : MgTileService()
 {
@@ -71,24 +74,30 @@
                 sm_useMetaTiles,
                 MgConfigProperties::DefaultTileServicePropertyUseMetaTiles);
 
+             configuration->GetIntValue(
+                MgConfigProperties::TileServicePropertiesSection,
+                MgConfigProperties::TileServicePropertyLockMethod,
+                sm_lockMethod,
+                MgConfigProperties::DefaultTileServicePropertyLockMethod);
+
             MgTileCache::Initialize();
             sm_initialized = true;
         }
     }
     m_resourceService = NULL;
-    m_tileCache = new MgTileCache();
+    m_tileCache = new MgTileCache(this);
     
     // bail out if metatile factor to large (allocation problem)
     if (METAMAXDIM < sm_useMetaTiles)
     {
-        STRING buffer;
-        MgUtil::Int32ToString(sm_initialized, buffer);
+        std::wstringstream text;
+        text << L"MetaTiling Config: " << sm_useMetaTiles << L" is larger than maximum " << METAMAXDIM;
 
         MgStringCollection arguments;
-        arguments.Add(buffer);
+        arguments.Add(text.str().c_str());
 
         throw new MgConfigurationException(L"MgServerTileService.CTOR",
-            __LINE__, __WFILE__, &arguments, L"TooLargeMetaTilingFactor", NULL);
+            __LINE__, __WFILE__, &arguments, L"MgTooLargeMetaTilingFactor", NULL);
     }
 }
 
@@ -112,11 +121,30 @@
 /// \brief
 /// Detect if the tile file has been locked by another thread or process.
 ///
-bool MgServerTileService::DetectTileLockFile(CREFSTRING lockPathname)
+bool MgServerTileService::DetectTileLockFile(CREFSTRING lockPathname, CREFSTRING tilePathname)
 {
     bool found = false;
     struct _stat lockFileInfo;
 
+    if (sm_lockMethod == 2) // simple collection of paths
+    {
+        int sec = sm_pollingInterval/1000;
+        ACE_Time_Value polInt (sec, (sm_pollingInterval - (sec*1000))*1000);
+        time_t startTime;
+        ACE_OS::time(&startTime);
+        time_t diffTime = 0;
+        time_t currTime;
+        // sm_creationCutoffTime times or found 
+        // TODO think about multithreaded lockmap access
+        for  (INT32 diffTime=0;(found = m_tileCache->GetLockMap().count(tilePathname)) 
+                               && diffTime < sm_creationCutoffTime; 
+                               ACE_OS::time(&currTime),diffTime = (INT32)(currTime - startTime))
+        {   
+            // sm_pollingInterval om milliseconds
+            ACE_OS::sleep(polInt);
+        }
+    }
+
     // Check the lock file to see if another thread/process is writing the tile file.
     while (MgFileUtil::GetFileStatus(lockPathname, lockFileInfo))
     {
@@ -152,17 +180,46 @@
                                            INT32 tileRow,
                                            INT32 scaleIndex)
 {
+    // check args first
+    if (NULL == mapDefinition || baseMapLayerGroupName.empty())
+    {
+        throw new MgNullArgumentException(L"MgServerTileService.GetTile",
+            __LINE__, __WFILE__, NULL, L"", NULL);
+    }
+    if (scaleIndex < 0)
+    {
+        STRING buffer;
+        MgUtil::Int32ToString(scaleIndex, buffer);
+
+        MgStringCollection arguments;
+        arguments.Add(buffer);
+
+        throw new MgInvalidArgumentException(L"MgServerTileService.GetTile",
+            __LINE__, __WFILE__, &arguments, L"MgInvalidScaleIndex", NULL);
+    }
+
+    if (sm_useMetaTiles)
+        return GetMetaTile(mapDefinition, baseMapLayerGroupName, tileColumn, tileRow, scaleIndex);
+    else
+        return GetSingleTile(mapDefinition, baseMapLayerGroupName, tileColumn, tileRow, scaleIndex);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Create tilename from mapDefinition, scaleIndex, row, and column.
+// Remove lockfile, look for the tile in the cache, if not in cache create
+// lockfile and look for map in mapcache.
+MgByteReader* MgServerTileService::GetSingleTile(MgResourceIdentifier* mapDefinition,
+                                                 CREFSTRING baseMapLayerGroupName,
+                                                 INT32 tileColumn,
+                                                 INT32 tileRow,
+                                                 INT32 scaleIndex)
+{
     Ptr<MgByteReader> ret;
     FILE* lockFile = NULL;
     STRING tilePathname, lockPathname;
-    // metatiling vars
-    FILE* subTileLockFile[METAMAXDIM][METAMAXDIM];
-    STRING subTileLockPathname[METAMAXDIM][METAMAXDIM], subTilePathname[METAMAXDIM][METAMAXDIM];
-    STRING metaTileLockPathname, metaTilePathname;
-    int maxX,maxY, subTileX,subTileY, metaTileColumn, metaTileRow;
-    int cacheHit = 0;
 
-   MG_TRY()
+    MG_TRY()
 
     if (NULL == mapDefinition || baseMapLayerGroupName.empty())
     {
@@ -183,74 +240,236 @@
             __LINE__, __WFILE__, &arguments, L"MgInvalidScaleIndex", NULL);
     }
 
-    if (sm_useMetaTiles)    //  additional names and control variables for meta tiles
+    // get the service from our helper method
+    Ptr<MgResourceService> resourceService = GetResourceServiceForMapDef(mapDefinition,
+                                            L"MgServerTileService.GetTile");
+    // Generate tile and lock pathnames.
+    m_tileCache->GeneratePathnames(mapDefinition, scaleIndex, baseMapLayerGroupName,
+        tileColumn, tileRow, tilePathname, lockPathname, false);
+
+    // If there is a dangling lock file, then attempt to remove it.
+    if (DetectTileLockFile(lockPathname, tilePathname))
     {
-        // which subTile from sm_useMetaTiles^2 larger tile
-        subTileX = abs(tileColumn % sm_useMetaTiles);
-        subTileY = abs(tileRow % sm_useMetaTiles);
-        // determine left top corner of metaTile having sm_useMetaTiles**2 subtiles
-        metaTileColumn = tileColumn - subTileX;
-        metaTileRow = tileRow - subTileY;
-        // Generate tile and lock pathnames for meta tile in the mod xx grid
-        m_tileCache->GeneratePathnames(mapDefinition, scaleIndex, baseMapLayerGroupName,
-            metaTileColumn, metaTileRow, metaTilePathname, metaTileLockPathname, false);
-        // init control vars
-        maxX = maxY = sm_useMetaTiles;
-        for (int y=0; y < maxY; y++)    // rows
-        for (int x=0; x < maxX; x++)     // columns
+        // TODO: Handle the exception by displaying a tile with an error message?
+        MgFileUtil::DeleteFile(lockPathname, true);
+    }
+
+    // try getting the tile from the cache
+    ret = m_tileCache->Get(tilePathname);
+
+    // if the reader is NULL then the tile wasn't in the cache and we
+    // need to generate it
+    while (NULL == ret)
+    {
+        // Attempt use a cached & serialized MgMap object
+        Ptr<MgMemoryStreamHelper> cachedMap;
+        STRING mapString = mapDefinition->ToString();
+        Ptr<MgMap> map;
+
+        // Protect the serialized MgMap cache with a mutex.  Stream reading is not
+        // thread safe so we need to deserialize the map within the mutex to ensure
+        // that a Rewind() is not called in the middle of a Deserialize().
+        // Lockfile test and creation is in same protected scope.
         {
-            subTileLockFile[x][y] = NULL;
-            // Generate tile and lock pathnames.
-            m_tileCache->GeneratePathnames(mapDefinition, scaleIndex, baseMapLayerGroupName,
-                metaTileColumn + x, metaTileRow + y, subTilePathname[x][y], subTileLockPathname[x][y], false);
-        }
+            // Attempt to lock the tile file.
+            ACE_MT(ACE_GUARD_RETURN(ACE_Recursive_Thread_Mutex, ace_mon, sm_mutex, NULL));
 
-    }    
-    // Generate tile and lock pathnames.
+            // Bail out if the tile file has been locked for so long.
+            if (DetectTileLockFile(lockPathname, tilePathname))
+            {
+                MgStringCollection arguments;
+                arguments.Add(lockPathname);
+
+                throw new MgFileIoException(L"MgServerTileService.GetTile",
+                    __LINE__, __WFILE__, &arguments, L"MgFoundBlockingLockFile", NULL);
+            }
+
+            // try getting the tile from the cache
+            ret = m_tileCache->Get(tilePathname);
+
+            if (NULL != ret)
+            {
+                break;  // tile was in tileCache .. done.
+            }
+
+            // Create the lock file and close it right away.
+            m_tileCache->CreateFullPath(mapDefinition, scaleIndex, baseMapLayerGroupName, tileColumn, tileRow);
+            lockFile = ACE_OS::fopen(MG_WCHAR_TO_TCHAR(lockPathname), ACE_TEXT("wb"));
+
+            if (NULL == lockFile)
+            {
+                MgStringCollection arguments;
+                arguments.Add(lockPathname);
+
+                throw new MgFileIoException(L"MgServerTileService.GetTile",
+                    __LINE__, __WFILE__, &arguments, L"MgUnableToOpenLockFile", NULL);
+            }
+            else
+            {
+                ACE_OS::fclose(lockFile);
+            }
+
+            MapCache::const_iterator iter = sm_mapCache.find(mapString);
+            if (sm_mapCache.end() != iter)
+            {
+                cachedMap = SAFE_ADDREF((*iter).second);
+                cachedMap->Rewind();
+                Ptr<MgStream> stream = new MgStream(cachedMap);
+                map = new MgMap();
+                map->Deserialize(stream);
+            }
+            else
+            {
+                Ptr<MgSiteConnection> siteConn = new MgSiteConnection();
+                siteConn->Open(MgUserInformation::GetCurrentUserInfo());
+                map = new MgMap(siteConn);
+                map->Create(resourceService, mapDefinition, mapString);
+                cachedMap = new MgMemoryStreamHelper();
+                Ptr<MgStream> stream = new MgStream(cachedMap);
+                map->Serialize(stream);
+                if ((INT32)sm_mapCache.size() >= sm_mapCacheSize)
+                {
+                    ClearMapCache(L"");
+                }
+                sm_mapCache[mapString] = SAFE_ADDREF((MgMemoryStreamHelper*)cachedMap);
+            }
+        }   // end of mutex scope
+
+        double scale = map->GetFiniteDisplayScaleAt(scaleIndex);
+        map->SetViewScale(scale);
+
+        // Render the tile and cache it.
+        ret = GetTile(tilePathname, map, scaleIndex, baseMapLayerGroupName, tileColumn, tileRow);
+        break;
+    }
+
+    MG_CATCH(L"MgServerTileService.GetTile")
+
+    if (NULL != lockFile)
+    {
+        MgFileUtil::DeleteFile(lockPathname, false);
+    }
+
+    MG_THROW()
+
+    return ret.Detach();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Create tilename from mapDefinition, scaleIndex, row, and column USING METATILES
+/// APIVERSION 1.2 use locking method specified in sm_lockMethod
+MgByteReader* MgServerTileService::GetMetaTile(MgResourceIdentifier* mapDefinition,
+                                           CREFSTRING baseMapLayerGroupName,
+                                           INT32 tileColumn,
+                                           INT32 tileRow,
+                                           INT32 scaleIndex)
+{
+    Ptr<MgByteReader> ret;
+    FILE* lockFile = NULL;
+    STRING tilePathname, lockPathname;
+    // metatiling vars
+    FILE* subTileLockFile[METAMAXDIM][METAMAXDIM];
+    STRING subTileLockPathname[METAMAXDIM][METAMAXDIM], subTilePathname[METAMAXDIM][METAMAXDIM];
+    STRING metaTileLockPathname, metaTilePathname;
+    int maxX,maxY, subTileX,subTileY, metaTileColumn, metaTileRow;
+    bool cacheHit = false;
+
+   MG_TRY()
+
+    // Generate tile and lock pathnames for later use
     m_tileCache->GeneratePathnames(mapDefinition, scaleIndex, baseMapLayerGroupName,
         tileColumn, tileRow, tilePathname, lockPathname, false);
 
-    if (sm_useMetaTiles)
+    //  additional names and control variables for meta tiles
+    // which subTile from sm_useMetaTiles^2 larger tile
+    subTileX = abs(tileColumn % sm_useMetaTiles);
+    subTileY = abs(tileRow % sm_useMetaTiles);
+    // determine left top corner of metaTile having sm_useMetaTiles**2 subtiles
+    metaTileColumn = tileColumn - subTileX;
+    metaTileRow = tileRow - subTileY;
+
+    maxX = maxY = sm_useMetaTiles;  // init control vars
+    // iterate subtiles
+    for (int y=0; y < maxY; y++)    // subtile rows
+    for (int x=0; x < maxX; x++)    // subtile columns
+    {   // Generate tile and lock pathnames.
+        subTileLockFile[x][y] = NULL;
+        m_tileCache->GeneratePathnames(mapDefinition, scaleIndex, baseMapLayerGroupName,
+            metaTileColumn + x, metaTileRow + y, subTilePathname[x][y], subTileLockPathname[x][y], false);
+    }
+
+    // Generate tile and lock pathnames for meta tile in the mod xx grid
+    m_tileCache->GeneratePathnames(mapDefinition, scaleIndex, baseMapLayerGroupName,
+        metaTileColumn, metaTileRow, metaTilePathname, metaTileLockPathname, false);
+
+    // sm_lockMethod == 1 using 1 remapped metalockfile for all subtiles
+    // sm_lockMethod == 2 using 1 lockfile for each subtiles
+    // sm_lockMethod == 3 using 1 ace condition per metatile
+    switch (sm_lockMethod)
     {
-        if (DetectTileLockFile(metaTileLockPathname))
+    case 3:    // use ace conditions no files
+        {   // protect test of lockmap entry with a guard
+            ACE_Condition<ACE_Recursive_Thread_Mutex> *wait = 0;
+            // look for lock and wait if found
+            ACE_MT(ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, sm_tileMutex, 0));
+            if (wait = m_tileCache->GetLockMap()[metaTilePathname])
+            {   // lock has been found
+                std::wstringstream text;
+                text << L"(" << ACE_OS::thr_self() << L") METATILE: WaitForLock1(" << metaTilePathname << L")\n" ;
+                ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
+
+                ACE_Time_Value waitTime(METATILEWAIT);
+                if (-1 == wait->wait()) // wait forever
+                {
+                    std::wstringstream text;
+                    text << L"(" << ACE_OS::thr_self() << L") METATILE: WaitForLockTimedOut1(" << metaTilePathname << L")\n" ;
+                    ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
+
+                    MgStringCollection arguments;
+                    arguments.Add(metaTilePathname);
+                    throw new MgFileIoException(L"MgServerTileService.GetTile",
+                        __LINE__, __WFILE__, &arguments, L"MgWaitForLockTimedOut", NULL);
+                } else {
+                    std::wstringstream text;
+                    text << L"(" << ACE_OS::thr_self() << L") METATILE: WaitForLockCAUGHTSIGNAL1(" << metaTilePathname << L")\n" ;
+                    ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
+                }
+            }
+        } 
+        break;
+    case 2:
+        if (DetectTileLockFile(lockPathname, tilePathname))
         {
-            // TODO: Handle the exception by displaying a tile with an error message?
-            MgFileUtil::DeleteFile(metaTileLockPathname, true);
             std::wstringstream text;
-            text << L"METATILE: DeletedDanglingLockfile(" << metaTileRow  << L", " <<  metaTileColumn << L") " 
-                << metaTileLockPathname << L")\n" ;
+            text << L"(" << ACE_OS::thr_self() << L") METATILE: DeletedDanglingLockfile(" << tileRow  << L", " <<  tileColumn << L") " 
+                << lockPathname << L")\n" ;
             ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
+            // TODO: Handle the exception by displaying a tile with an error message?
+            MgFileUtil::DeleteFile(lockPathname, true);
         }        
-    } else
-        // If there is a dangling lock file, then attempt to remove it.
-        if (DetectTileLockFile(lockPathname))
+        break;
+    default:
+    case 1: // default
+        if (DetectTileLockFile(metaTileLockPathname, metaTilePathname))
         {
-            // TODO: Handle the exception by displaying a tile with an error message?
-            MgFileUtil::DeleteFile(lockPathname, true);
             std::wstringstream text;
-            text << L"METATILE: DeletedDanglingLockfile(" << tileRow  << L", " <<  tileColumn << L") " 
-                << lockPathname << L")\n" ;
+            text << L"(" << ACE_OS::thr_self() << L") METATILE: DeletedDanglingLockfile(" << metaTileRow  << L", " <<  metaTileColumn << L") " 
+                << metaTileLockPathname << L")\n" ;
             ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
-        }
-
-    // try getting the tile from the cache
-    ret = m_tileCache->Get(tilePathname);
-
-    if (ret)
+            // TODO: Handle the exception by displaying a tile with an error message?
+            MgFileUtil::DeleteFile(metaTileLockPathname, true);
+        }     
+    } /// end switch
+    // try getting the tile from the cache first time
+    cacheHit = ret = m_tileCache->Get(tilePathname);
     {
-        cacheHit = 1;
         std::wstringstream text;
-        text << L"CACHEHIT: GetTile(" << tileRow  << L", " <<  tileColumn << L") " << tilePathname << L"\n";
+        text << L"(" << ACE_OS::thr_self() << (cacheHit?L") CACHEHIT":L") CACHEMISS") << L": GetTile(" 
+            << tileRow  << L", " <<  tileColumn << L") " << tilePathname << L"\n";
         ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
-    } else {
-        std::wstringstream text;
-        text << L"CACHEMISS: GetTile(" << tileRow  << L", " <<  tileColumn << L") " << tilePathname << L"\n";
-        ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
     }
-
-    // if the reader is NULL then the tile wasn't in the cache and we
-    // need to generate it
-    while (NULL == ret) //=======================================================================
+    // if the reader is NULL then the tile wasn't in the cache and we need to generate it
+    while (NULL == ret) // while is needed to use break; =========================================
     {
         Ptr<MgMap> map;
 
@@ -258,74 +477,105 @@
         // thread safe so we need to deserialize the map within the mutex to ensure
         // that a Rewind() is not called in the middle of a Deserialize().
         // Lockfile test and creation is in same protected scope.
-        {
+        { // ------------------------ LLLLOOOOOOCCCCCKKKKKIIIIINNNGGGG
             // Attempt to get the mapcache mutex .
             ACE_MT(ACE_GUARD_RETURN(ACE_Recursive_Thread_Mutex, ace_mon, sm_mutex, NULL));
+            switch(sm_lockMethod) 
+            {
+            case 3:// TODO do we need the second lock test here in a signal/wait algorithm?
+            {  // use ace conditions no files
+                ACE_Condition<ACE_Recursive_Thread_Mutex> *wait = 0;  // protect test of lockmap entry with a guard
+                // look for lock and wait if found
+                ACE_MT(ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, sm_tileMutex, 0));
+                if (wait = m_tileCache->GetLockMap()[metaTilePathname])
+                {   // lock has been found
+                    std::wstringstream text;
+                    text << L"(" << ACE_OS::thr_self() << L") METATILE: WaitForLock2(" << metaTilePathname << L")\n" ;
+                    ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
 
-            // Bail out if the tile file has been locked for so long.
-            if (sm_useMetaTiles)
-            {
-                if (DetectTileLockFile(metaTileLockPathname))
+                    ACE_Time_Value finalTime = ACE_OS::gettimeofday() + ACE_Time_Value(METATILEWAIT);
+                    int out = wait->wait(); // ->wait(&finalTime);
+                    if (-1 == out) // wait forever
+                    {
+                        std::wstringstream text;
+                        text << L"(" << ACE_OS::thr_self() << L") METATILE: WaitForLockTimedOut2(" << metaTilePathname << L")\n" ;
+                        ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
+
+                        MgStringCollection arguments;
+                        arguments.Add(metaTilePathname);
+                        throw new MgFileIoException(L"MgServerTileService.GetTile",
+                            __LINE__, __WFILE__, &arguments, L"MgWaitForLockTimedOut", NULL);
+                    } else {
+                        std::wstringstream text;
+                        text << L"(" << ACE_OS::thr_self() << L") METATILE: WaitForLockCAUGHTSIGNAL2(" << metaTilePathname << L")\n" ;
+                        ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
+                    }
+                } // if found in map
+              } // END ace_guard context
+               break;
+            case 2: // Bail out if the tile file has been locked for so long.
+                if (DetectTileLockFile(lockPathname, tilePathname))
                 {
                     MgStringCollection arguments;
-                    arguments.Add(metaTileLockPathname);
-
+                    arguments.Add(lockPathname);
                     throw new MgFileIoException(L"MgServerTileService.GetTile",
                         __LINE__, __WFILE__, &arguments, L"MgUnableToLockMetaTileFile", NULL);
                 }        
-            } else
-                if (DetectTileLockFile(lockPathname))
+                break;
+            default:
+            case 1:
+                if (DetectTileLockFile(metaTileLockPathname, metaTilePathname))
                 {
                     MgStringCollection arguments;
-                    arguments.Add(lockPathname);
-
+                    arguments.Add(metaTileLockPathname);
                     throw new MgFileIoException(L"MgServerTileService.GetTile",
-                        __LINE__, __WFILE__, &arguments, L"MgUnableToLockTileFile", NULL);
-                }
+                        __LINE__, __WFILE__, &arguments, L"MgUnableToLockMetaTileFile", NULL);
+                }        
+            } // end switch  ------------------------ LLLLOOOOOOCCCCCKKKKKIIIIINNNGGGG
+            
+            // try getting the tile from the cache second time ???????????????????????????????????????????
+            cacheHit = ret = m_tileCache->Get(tilePathname);
 
-            // try getting the tile from the cache
-            ret = m_tileCache->Get(tilePathname);
-
             if (NULL != ret)
             {
                 std::wstringstream text;
-                text << L"CACHEHIT2: GetTile(" << tileRow  << L", " <<  tileColumn << L") " << tilePathname << L"\n";
+                text << L"(" << ACE_OS::thr_self() << L") CACHEHIT2: GetTile(" << tileRow  << L", " <<  tileColumn << L") " << tilePathname << L"\n";
                 ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
-                break;  // tile was in tileCache .. done.
+        /////////////////////////////////// tile was in tileCache .. done.
+                break;  
             } else {
                 std::wstringstream text;
-                text << L"CACHEMISS2: GetTile(" << tileRow  << L", " <<  tileColumn << L") " << tilePathname << L"\n";
+                text << L"(" << ACE_OS::thr_self() << L") CACHEMISS2: GetTile(" << tileRow  << L", " <<  tileColumn << L") " << tilePathname << L"\n";
                 ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
             }
-
-            //=========================================================================
-            if (!sm_useMetaTiles)        // create sm_useMetaTiles lockfiles
+    
+            // ============================================================================ LOCKING
+            switch(sm_lockMethod) 
             {
-                // Create the lock file and close it right away.
-                m_tileCache->CreateFullPath(mapDefinition, scaleIndex, baseMapLayerGroupName, tileColumn, tileRow);
-                lockFile = ACE_OS::fopen(MG_WCHAR_TO_TCHAR(lockPathname), ACE_TEXT("wb"));
-
-                if (NULL == lockFile)
-                {
-                    MgStringCollection arguments;
-                    arguments.Add(lockPathname);
-
-                    throw new MgFileIoException(L"MgServerTileService.GetTile",
-                        __LINE__, __WFILE__, &arguments, L"MgUnableToOpenLockFile", NULL);
-                }
-                else
-                {
-                    ACE_OS::fclose(lockFile);
-                }
-            } else 
-            //=========================================================================
-            {
-                for (int y=0; y < 1; y++)    // rows                   ---- JUST ONCE THE LOCKFILE
-                for (int x=0; x < 1; x++)    // columns
-                {
-                    // per array element Create the lock file and close it right away.
+            case 3:
+                {   // Create the directory structure for each subtile!
+                    for (int y=0; y < maxY; y++)    // rows  
+                        for (int x=0; x < maxX; x++)    // columns
+                        {   
+                            m_tileCache->CreateFullPath(mapDefinition, scaleIndex, baseMapLayerGroupName, 
+                                metaTileColumn + x, metaTileRow + y);
+                        }
+                    // create ace condition for this tile as we are going to make it
+                    ACE_Condition<ACE_Recursive_Thread_Mutex> *wait = new ACE_Condition<ACE_Recursive_Thread_Mutex>(sm_tileMutex);
+                    // keep reference to lock (ace condition) in map
+                    m_tileCache->GetLockMap()[metaTilePathname] = wait;  
+                    std::wstringstream text;
+                    text << L"(" << ACE_OS::thr_self() << L") METATILE: CreateLock(" << metaTilePathname << L"\n" ;
+                    ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
+                } 
+               break;
+            case 2: 
+                for (int y=0; y < maxY; y++)    // rows  
+                for (int x=0; x < maxX; x++)    // columns
+                {   // Create the directory structure for each subtile
                     m_tileCache->CreateFullPath(mapDefinition, scaleIndex, baseMapLayerGroupName, 
                         metaTileColumn + x, metaTileRow + y);
+                    // Create a lock file per sub tile and close it right away.
                     subTileLockFile[x][y] = ACE_OS::fopen(MG_WCHAR_TO_TCHAR(subTileLockPathname[x][y]), ACE_TEXT("wb"));
 
                     if (NULL == subTileLockFile[x][y])
@@ -334,101 +584,156 @@
                         arguments.Add(subTilePathname[x][y]);
 
                         throw new MgFileIoException(L"MgServerTileService.GetTile",
-                            __LINE__, __WFILE__, &arguments, L"MgUnableToOpenLockFile", NULL);
+                            __LINE__, __WFILE__, &arguments, L"MgUnableToCreateLockFile", NULL);
                     }
                     else
                     {
                         ACE_OS::fclose(subTileLockFile[x][y]);
+#ifdef _DEBUG
                         std::wstringstream text;
-                        text << L"METATILE: CreatedLockfile(" << metaTileRow + y << L", " <<  metaTileColumn + x << L") " 
+                        text << L"(" << ACE_OS::thr_self() << L") METATILE: CreatedLockfile(" << metaTileRow + y << L", " <<  metaTileColumn + x << L") " 
                             << L" S(" << x << L", " << y << L") " << subTileLockPathname[x][y] << L")\n";
                         ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
+#endif
                     }
                 } // end meta tiling loop for lockfiles
-            } // if sm_useMetatiles
+                break;
+            default:
+            case 1:
+                {   // Create the directory structure for each subtile
+                    m_tileCache->CreateFullPath(mapDefinition, scaleIndex, baseMapLayerGroupName, 
+                        metaTileColumn, metaTileRow);
+                    // per array element Create the lock file and close it right away.
+                    lockFile = ACE_OS::fopen(MG_WCHAR_TO_TCHAR(metaTileLockPathname), ACE_TEXT("wb"));
+
+                    if (NULL == lockFile)
+                    {
+                        MgStringCollection arguments;
+                        arguments.Add(metaTileLockPathname);
+
+                        throw new MgFileIoException(L"MgServerTileService.GetTile",
+                            __LINE__, __WFILE__, &arguments, L"MgUnableToOpenLockFile", NULL);
+                    }
+                    else
+                    {
+                        ACE_OS::fclose(lockFile);
+                        std::wstringstream text;
+                        text << L"(" << ACE_OS::thr_self() << L") METATILE: CreatedLockfile(" << metaTileRow << L", " <<  metaTileColumn<< L") " 
+                             << metaTileLockPathname << L")\n";
+                        ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
+                    }
+                } // end meta tiling loop for lockfiles
+
+            } // end switch
             //=========================================================================
             GetMapFromDefinition(mapDefinition, scaleIndex, map);
         }   // end of mutex scope
 
-        // Get the tile
-         if (sm_useMetaTiles)
-         {
-            // Render the larger meta tile but do not cache it yet! (sm_useMetaTiles [prohibits caching in GetTile)
-            STRING metaTileName = L"META" + metaTilePathname;
+        // Render the larger meta tile but do not cache it yet! (sm_useMetaTiles [prohibits caching in GetTile)
+        STRING metaTileName = L"META" + metaTilePathname;
+        {
+            std::wstringstream text;
+            text << L"(" << ACE_OS::thr_self() << L") METATILE: RenderMetaTile(" << metaTileRow << L", " <<   metaTileColumn << L") " << metaTileName << L"\n";
+            ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
+        }
+        Ptr<MgByteReader> metaTile = GetTile(metaTileName, map, scaleIndex, baseMapLayerGroupName, metaTileColumn, metaTileRow);
+
+        // Get a ServerSide rendering Service only...
+        MgServiceManager* serviceMan = MgServiceManager::GetInstance();
+        assert(NULL != serviceMan);
+        Ptr<MgServerRenderingService> svcRendering = dynamic_cast<MgServerRenderingService*>(
+            serviceMan->RequestService(MgServiceType::RenderingService));
+        assert(NULL != svcRendering);
+
+        // splitup the meta tiles
+        for (int y=0; y < maxY; y++)    // rows
+        for (int x=0; x < maxX; x++)    // columns
+        {
+            // generate the tile
+            Ptr<MgByteReader> img = svcRendering->RenderTileFromMetaTile(map, metaTile, x,y);
+            if ((subTileX == x) && (subTileY == y)) 
+                ret = img;       // keep pointer for requested subtile
+            assert (x < maxX && y < maxY);
+            m_tileCache->Set(img, subTilePathname[x][y]);   // store all subtiles in tile cache
+
+            if (img)
             {
                 std::wstringstream text;
-                text << L"METATILE: RenderMetaTile(" << metaTileRow << L", " <<   metaTileColumn << L") " << metaTileName << L"\n";
+                text << L"(" << ACE_OS::thr_self() << L") METATILE: SetTileFromMetaTile(" << tileRow  << L", " <<  tileColumn << L") " << subTilePathname[x][y]
+                                            << L" S(" << x << L", " << y << L")\n";
                 ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
             }
-            Ptr<MgByteReader> metaTile = GetTile(metaTileName, map, scaleIndex, baseMapLayerGroupName, metaTileColumn, metaTileRow);
-
-            // Get a ServerSide rendering Service only...
-            MgServiceManager* serviceMan = MgServiceManager::GetInstance();
-            assert(NULL != serviceMan);
-            Ptr<MgServerRenderingService> svcRendering = dynamic_cast<MgServerRenderingService*>(
-                serviceMan->RequestService(MgServiceType::RenderingService));
-            assert(NULL != svcRendering);
-
-            // splitup the meta tiles up
-            for (int y=0; y < maxY; y++)    // rows
-            for (int x=0; x < maxX; x++)    // columns
+            // rewind the reader since setting the tile advances it to the end
+            if (img)
             {
-                // generate the tile
-                Ptr<MgByteReader> img = svcRendering->RenderTileFromMetaTile(map, metaTile, x,y);
-                if ((subTileX == x) && (subTileY == y)) 
-                    ret = img;       // keep pointer for requested subtile
-                m_tileCache->Set(img, subTilePathname[x][y]);   // store all of them intile cache
-
-                if (img)
-                {
-                    std::wstringstream text;
-                    text << L"METATILE: SetTileFromMetaTile(" << tileRow  << L", " <<  tileColumn << L") " << subTilePathname[x][y]
-                                                << L" S(" << x << L", " << y << L")\n";
-                    ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
-                }
-                // rewind the reader since setting the tile advances it to the end
-                if (img)
-                {
-                    img->Rewind();
-                }
+                img->Rewind();
             }
-         } else 
-         {
-            // Render the tile and cache it. 
-            ret = GetTile(tilePathname, map, scaleIndex, baseMapLayerGroupName, tileColumn, tileRow);
-         }
+        }
         break;
     }   // end of gettile loop end MgMap scope
 
-     MG_CATCH(L"MgServerTileService.GetTile")
+    MG_CATCH(L"MgServerTileService.GetTile")
 
-    if (sm_useMetaTiles)        // remove sm_useMetaTiles lockfiles
+    // remove all lockfiles
+    switch(sm_lockMethod) // do the locking now
     {
-        for (int y=0; y < 1; y++)    // rows                        --  JUST ONE LOCKFILE
-        for (int x=0; x < 1; x++)    // columns
+    case 3:
+        try 
+        {   // synchronize access to map
+            ACE_MT(ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, sm_tileMutex, 0));
+            ACE_Condition<ACE_Recursive_Thread_Mutex> *lock = m_tileCache->GetLockMap()[metaTilePathname];            
+            if (lock) 
+            {   
+                int result = lock->broadcast();    // notify waiters of finished tile
+                std::wstringstream text;
+                text << L"(" << ACE_OS::thr_self() << L") METATILE: Broadcast(" << metaTilePathname 
+                    << L") returns: " << result << L"\n";
+                ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
+            }
+            m_tileCache->GetLockMap().erase(metaTilePathname); // erase: this destroys the ace condition
+        } 
+        catch (MgException* e) 
         {
+                std::wstringstream text;
+                text << L"(" << ACE_OS::thr_self() << L") METATILE: Broadcastcrash (" << metaTilePathname 
+                    << L")\n" << e->GetMessage() << L")\n";
+                ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
+        }
+        break;
+    case 2:
+        for (int y=0; y < maxY; y++)    // rows  
+        for (int x=0; x < maxX; x++)    // columns
             if (NULL != subTileLockFile[x][y])
             {
                 MgFileUtil::DeleteFile(subTileLockPathname[x][y], false);
                 {
                     std::wstringstream text;
-                    text << L"METATILE: DeletedLockfile(" << tileRow  << L", " <<  tileColumn << L") " 
-                        << L" S(" << x << L", " << y << subTileLockPathname[x][y] << L")\n";
+                    text << L"(" << ACE_OS::thr_self() << L") METATILE: DeletedLockfile(" << metaTileRow + y  << L", " <<  metaTileColumn + x 
+                        << L") S(" << x << L", " << y << subTileLockPathname[x][y] << L")\n";
                     ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
                 }
             }
-        }
-    } else {
+        break;
+    case 1:
+    default:
         if (NULL != lockFile)
         {
-            MgFileUtil::DeleteFile(lockPathname, false);
+            MgFileUtil::DeleteFile(metaTileLockPathname, false);
+            {
+                std::wstringstream text;
+                text << L"(" << ACE_OS::thr_self() << L") METATILE: DeletedLockfile(" << metaTileRow   << L", " <<  metaTileColumn  << L") " 
+                    << metaTileLockPathname << L"\n";
+                ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
+            }
         }
-    }
+    } // end switch
+
     MG_THROW()
+
     if (!cacheHit) 
     {
         std::wstringstream text;
-        text << L"Rendered: GetTILE(" << tileRow  << L", " <<  tileColumn << L") " 
+        text << L"(" << ACE_OS::thr_self() << L") Rendered: GetTILE(" << tileRow  << L", " <<  tileColumn << L") " 
             << L" S(" << subTileX << L", " << subTileY << tilePathname << L")\n";
         ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
     }
@@ -472,7 +777,7 @@
         tileColumn, tileRow, tilePathname, lockPathname, false);
 
     // If there is a dangling lock file, then attempt to remove it.
-    if (DetectTileLockFile(lockPathname))
+    if (DetectTileLockFile(lockPathname, tilePathname))
     {
         // TODO: Handle the exception by displaying a tile with an error message?
         MgFileUtil::DeleteFile(lockPathname, true);
@@ -490,7 +795,7 @@
             ACE_MT(ACE_GUARD_RETURN(ACE_Recursive_Thread_Mutex, ace_mon, sm_mutex, NULL));
 
             // Bail out if the tile file has been locked for so long.
-            if (DetectTileLockFile(lockPathname))
+            if (DetectTileLockFile(lockPathname, tilePathname))
             {
                 MgStringCollection arguments;
                 arguments.Add(lockPathname);
@@ -620,7 +925,7 @@
         // Attemp to lock the tile file.
         ACE_MT(ACE_GUARD(ACE_Recursive_Thread_Mutex, ace_mon, sm_mutex));
 
-        if (DetectTileLockFile(lockPathname))
+        if (DetectTileLockFile(lockPathname, tilePathname))
         {
             // Attemp to remove a dangling lock file.
             MgFileUtil::DeleteFile(lockPathname, true);

Modified: sandbox/rfc90/MgDev/Server/src/Services/Tile/ServerTileService.h
===================================================================
--- sandbox/rfc90/MgDev/Server/src/Services/Tile/ServerTileService.h	2010-03-31 23:00:45 UTC (rev 4730)
+++ sandbox/rfc90/MgDev/Server/src/Services/Tile/ServerTileService.h	2010-04-01 05:05:29 UTC (rev 4731)
@@ -25,7 +25,7 @@
 #define METAMAXDIM 8
 /// forward decl
 class MgServerRenderingService; 
-class RS_Bounds;
+struct RS_Bounds;
 class RS_Color;
 class MG_SERVER_TILE_API MgServerTileService : public MgTileService
 {
@@ -65,11 +65,27 @@
         bool strict = true);
 
     void SetConnectionProperties(MgConnectionProperties* connProp);
+    static ACE_Recursive_Thread_Mutex sm_tileMutex;
+    static INT32 sm_lockMethod;
+    static INT32 sm_useMetaTiles;
 
 private:
 
-    bool DetectTileLockFile(CREFSTRING lockPathname);
+    virtual MgByteReader* GetMetaTile(MgResourceIdentifier* mapDefinition,
+                                  CREFSTRING baseMapLayerGroupName,
+                                  INT32 tileColumn,
+                                  INT32 tileRow,
+                                  INT32 scaleIndex);
 
+    virtual MgByteReader* GetSingleTile(MgResourceIdentifier* mapDefinition,
+                                  CREFSTRING baseMapLayerGroupName,
+                                  INT32 tileColumn,
+                                  INT32 tileRow,
+                                  INT32 scaleIndex);
+
+
+    bool DetectTileLockFile(CREFSTRING lockPathname, CREFSTRING tilePathname);
+
     MgByteReader* GetTile(CREFSTRING tilePathname, MgMap* map, INT32 scaleIndex,
         CREFSTRING baseMapLayerGroupName, INT32 tileColumn, INT32 tileRow);
 
@@ -85,14 +101,13 @@
 
     typedef std::map<STRING, MgMemoryStreamHelper*> MapCache;
 
-    static ACE_Recursive_Thread_Mutex sm_mutex;
     static bool sm_initialized;
     static MapCache sm_mapCache;
+    static ACE_Recursive_Thread_Mutex sm_mutex;
     static bool sm_renderOnly;
     static INT32 sm_creationCutoffTime;
     static INT32 sm_pollingInterval;
     static INT32 sm_mapCacheSize;
-    static INT32 sm_useMetaTiles;
 };
 
 #endif

Modified: sandbox/rfc90/MgDev/Server/src/Services/Tile/TileCache.cpp
===================================================================
--- sandbox/rfc90/MgDev/Server/src/Services/Tile/TileCache.cpp	2010-03-31 23:00:45 UTC (rev 4730)
+++ sandbox/rfc90/MgDev/Server/src/Services/Tile/TileCache.cpp	2010-04-01 05:05:29 UTC (rev 4731)
@@ -17,18 +17,25 @@
 
 #include "MapGuideCommon.h"
 #include "TileCache.h"
+#include "ServerTileService.h"
+#include <sstream>
 
 const STRING SCALE_INDEX_PREFIX = L"S";
 const STRING ROW_PREFIX = L"R";
 const STRING COLUMN_PREFIX = L"C";
 
 STRING MgTileCache::sm_path = L"";
+MgServerTileService* MgTileCache::sm_tileService = 0;
 INT32 MgTileCache::sm_tileColumnsPerFolder = 30;
 INT32 MgTileCache::sm_tileRowsPerFolder = 30;
+std::map<STRING,ACE_Condition<ACE_Recursive_Thread_Mutex>*> MgTileCache::sm_lockMap;
 
+std::map<STRING,ACE_Condition<ACE_Recursive_Thread_Mutex>*>& MgTileCache::GetLockMap() { return sm_lockMap; }
+
 // default constructor
-MgTileCache::MgTileCache()
+MgTileCache::MgTileCache(MgServerTileService* tileService)
 {
+    sm_tileService = tileService;   // keep pointer to parent
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -89,6 +96,7 @@
         {
             MgTileParameters::tileFormat = MgImageFormats::Png;
         }
+
     }
 }
 
@@ -140,13 +148,31 @@
         tilePathname, lockPathname, createFullPath);
 }
 
+#define METATILEWAIT 300
 // returns any cached tile for the given pathname
 MgByteReader* MgTileCache::Get(CREFSTRING tilePathname)
 {
     Ptr<MgByteReader> ret;
 
     MG_TRY()
+        /// uses wrong filename for metatiling
+    //ACE_Condition<ACE_Recursive_Thread_Mutex> *wait = 0;
+    //// look for lock and wait if found
+    //if (sm_tileService->sm_lockMethod==3 && sm_tileService->sm_useMetaTiles)
+    //{   // protect test of lockmap entry with a guard
+    //    ACE_MT(ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, sm_tileService->sm_mutex, 0));
+    //    if (wait = GetLockMap()[tilePathname])
+    //    {
+    //        std::wstringstream text;
+    //        text << L"METATILE: WaitForLock(" << tilePathname << L")\n" ;
+    //        ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
 
+    //        ACE_Time_Value waitTime(METATILEWAIT);
+    //        wait->wait(&waitTime);      // TODO is this a recursive deadlock?
+    //    }
+    //}
+
+    // now check for tile
     if (MgFileUtil::PathnameExists(tilePathname))
     {
         Ptr<MgByteSource> byteSource = new MgByteSource(tilePathname, false);
@@ -161,6 +187,17 @@
         }
 
         ret = byteSource->GetReader();
+    } else 
+    {
+        //if (sm_tileService->sm_lockMethod==3 && sm_tileService->sm_useMetaTiles)
+        //{   // protect creation of lockmap entry with a guard
+        //    ACE_MT(ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, sm_tileService->sm_mutex, 0));
+        //    // create ace condition for this tile as we are going to make it
+        //    ACE_Condition<ACE_Recursive_Thread_Mutex> *wait = 
+        //        new ACE_Condition<ACE_Recursive_Thread_Mutex>(sm_tileService->sm_mutex);
+        //    // keep lock (ace condition) in map
+        //    GetLockMap()[tilePathname] = wait;  
+        //}
     }
 
     MG_CATCH_AND_RELEASE()
@@ -176,6 +213,11 @@
         Ptr<MgByteSink> byteSink = new MgByteSink(img);
 
         byteSink->ToFile(tilePathname);
+
+        std::wstringstream text;
+        text << L"METATILE: WriteSubTile(" << tilePathname << L")\n" ;
+        ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
+
     }
 }
 

Modified: sandbox/rfc90/MgDev/Server/src/Services/Tile/TileCache.h
===================================================================
--- sandbox/rfc90/MgDev/Server/src/Services/Tile/TileCache.h	2010-03-31 23:00:45 UTC (rev 4730)
+++ sandbox/rfc90/MgDev/Server/src/Services/Tile/TileCache.h	2010-04-01 05:05:29 UTC (rev 4731)
@@ -19,12 +19,14 @@
 #define _MG_TILE_CACHE_H_
 
 #include "ServerTileDllExport.h"
+#include <set>
 
+class MgServerTileService;
 // File-system-based cache for base map layer group tiles generated by the rendering service.
 class MG_SERVER_TILE_API MgTileCache : public MgDisposable
 {
 public:
-    MgTileCache();
+    MgTileCache(MgServerTileService* sm_tileService);
 
     static void Initialize();
 
@@ -44,6 +46,9 @@
     void Clear(MgMap* map);
     void Clear(MgResourceIdentifier* mapDef);
 
+    static std::map<STRING,ACE_Condition<ACE_Recursive_Thread_Mutex>*> &GetLockMap();
+
+
 protected:
     virtual void Dispose()
     {
@@ -75,6 +80,11 @@
     static STRING sm_path;
     static INT32 sm_tileColumnsPerFolder;
     static INT32 sm_tileRowsPerFolder;
+    // use a memory based locking scheme
+    static std::map<STRING,ACE_Condition<ACE_Recursive_Thread_Mutex>*> sm_lockMap;
+
+    static MgServerTileService* sm_tileService; // pointer to owner
+
 };
 
 #endif



More information about the mapguide-commits mailing list