[mapguide-commits] r5955 - in sandbox/rfc90.2/MgDev: . Common/Foundation/Data Common/Geometry/GeometryConsoleTest Common/MapGuideCommon/MapLayer Common/MapGuideCommon/Services Common/MapGuideCommon/System Common/Renderers Server/src/Core Server/src/PostBuild Server/src/Services/Rendering Server/src/Services/Tile

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Tue Jun 28 19:45:26 EDT 2011


Author: uvlite
Date: 2011-06-28 16:45:26 -0700 (Tue, 28 Jun 2011)
New Revision: 5955

Modified:
   sandbox/rfc90.2/MgDev/Common/Foundation/Data/MimeType.cpp
   sandbox/rfc90.2/MgDev/Common/Foundation/Data/MimeType.h
   sandbox/rfc90.2/MgDev/Common/Geometry/GeometryConsoleTest/GeometryConsoleTest.vcproj
   sandbox/rfc90.2/MgDev/Common/MapGuideCommon/MapLayer/Map.cpp
   sandbox/rfc90.2/MgDev/Common/MapGuideCommon/MapLayer/Map.h
   sandbox/rfc90.2/MgDev/Common/MapGuideCommon/Services/ImageFormats.cpp
   sandbox/rfc90.2/MgDev/Common/MapGuideCommon/Services/ImageFormats.h
   sandbox/rfc90.2/MgDev/Common/MapGuideCommon/System/ConfigProperties.cpp
   sandbox/rfc90.2/MgDev/Common/MapGuideCommon/System/ConfigProperties.h
   sandbox/rfc90.2/MgDev/Common/Renderers/AGGRenderer.cpp
   sandbox/rfc90.2/MgDev/Common/Renderers/AGGRenderer.h
   sandbox/rfc90.2/MgDev/Server/src/Core/serverconfig.ini
   sandbox/rfc90.2/MgDev/Server/src/PostBuild/PostBuild.mak
   sandbox/rfc90.2/MgDev/Server/src/Services/Rendering/ServerRenderingService.cpp
   sandbox/rfc90.2/MgDev/Server/src/Services/Rendering/ServerRenderingService.h
   sandbox/rfc90.2/MgDev/Server/src/Services/Tile/ServerTileService.cpp
   sandbox/rfc90.2/MgDev/Server/src/Services/Tile/ServerTileService.h
   sandbox/rfc90.2/MgDev/Server/src/Services/Tile/ServerTileService.vcproj
   sandbox/rfc90.2/MgDev/Server/src/Services/Tile/TileCache.cpp
   sandbox/rfc90.2/MgDev/Server/src/Services/Tile/TileCache.h
   sandbox/rfc90.2/MgDev/build.bat
Log:
rfc90 merged with trunk

Modified: sandbox/rfc90.2/MgDev/Common/Foundation/Data/MimeType.cpp
===================================================================
--- sandbox/rfc90.2/MgDev/Common/Foundation/Data/MimeType.cpp	2011-06-28 17:05:29 UTC (rev 5954)
+++ sandbox/rfc90.2/MgDev/Common/Foundation/Data/MimeType.cpp	2011-06-28 23:45:26 UTC (rev 5955)
@@ -36,4 +36,5 @@
 const STRING MgMimeType::Json            = L"application/json";
 const STRING MgMimeType::Kml             = L"application/vnd.google-earth.kml+xml";
 const STRING MgMimeType::Kmz             = L"application/vnd.google-earth.kmz";
+const STRING MgMimeType::Meta            = L"application/metatile";
 

Modified: sandbox/rfc90.2/MgDev/Common/Foundation/Data/MimeType.h
===================================================================
--- sandbox/rfc90.2/MgDev/Common/Foundation/Data/MimeType.h	2011-06-28 17:05:29 UTC (rev 5954)
+++ sandbox/rfc90.2/MgDev/Common/Foundation/Data/MimeType.h	2011-06-28 23:45:26 UTC (rev 5955)
@@ -70,6 +70,9 @@
 
     /// application/vnd.google-earth.kmz
     static const STRING Kmz;      ///\if INTERNAL value("application/vnd.google-earth.kmz") \endif
+
+    /// application/metatile
+    static const STRING Meta;      ///\if INTERNAL value("application/metatile") \endif
 };
 /// \}
 

Modified: sandbox/rfc90.2/MgDev/Common/Geometry/GeometryConsoleTest/GeometryConsoleTest.vcproj
===================================================================
--- sandbox/rfc90.2/MgDev/Common/Geometry/GeometryConsoleTest/GeometryConsoleTest.vcproj	2011-06-28 17:05:29 UTC (rev 5954)
+++ sandbox/rfc90.2/MgDev/Common/Geometry/GeometryConsoleTest/GeometryConsoleTest.vcproj	2011-06-28 23:45:26 UTC (rev 5955)
@@ -63,7 +63,7 @@
 				Name="VCLinkerTool"
 				AdditionalDependencies="MgGeometryd.lib MgFoundationd.lib CsMapd.lib ACEd.lib"
 				LinkIncremental="1"
-				AdditionalLibraryDirectories=""$(ProjectDir)$(ConfigurationName)";"..\..\..\Common\lib\$(ConfigurationName)";"..\..\..\Oem\CsMap\lib80\$(ConfigurationName)";"..\..\..\Oem\ACE\ACE_wrappers\lib""
+				AdditionalLibraryDirectories=""$(ProjectDir)$(ConfigurationName)";"..\..\..\Common\lib\$(ConfigurationName)";"..\..\..\Oem\CsMap\lib90\$(ConfigurationName)";..\..\..\Oem\ACE\ACE_wrappers\lib"
 				GenerateDebugInformation="true"
 				SubSystem="1"
 				TargetMachine="1"
@@ -137,7 +137,7 @@
 				Name="VCLinkerTool"
 				AdditionalDependencies="MgGeometry.lib MgFoundation.lib CsMap.lib ACE.lib"
 				LinkIncremental="1"
-				AdditionalLibraryDirectories=""$(ProjectDir)$(ConfigurationName)";"..\..\..\Common\lib\$(ConfigurationName)";"..\..\..\Oem\CsMap\lib80\$(ConfigurationName)";"..\..\..\Oem\ACE\ACE_wrappers\lib""
+				AdditionalLibraryDirectories=""$(ProjectDir)$(ConfigurationName)";"..\..\..\Common\lib\$(ConfigurationName)";"..\..\..\Oem\CsMap\lib90\$(ConfigurationName)";..\..\..\Oem\ACE\ACE_wrappers\lib"
 				GenerateDebugInformation="true"
 				SubSystem="1"
 				OptimizeReferences="2"

Modified: sandbox/rfc90.2/MgDev/Common/MapGuideCommon/MapLayer/Map.cpp
===================================================================
--- sandbox/rfc90.2/MgDev/Common/MapGuideCommon/MapLayer/Map.cpp	2011-06-28 17:05:29 UTC (rev 5954)
+++ sandbox/rfc90.2/MgDev/Common/MapGuideCommon/MapLayer/Map.cpp	2011-06-28 23:45:26 UTC (rev 5955)
@@ -20,6 +20,12 @@
 #include "SAX2Parser.h"
 #include <map>
 
+/// rfc90 instead of a dependency on Common/Stylization/Bounds.h
+#define rs_max(a,b)     (((a) > (b)) ? (a) : (b))
+#define rs_min(a,b)     (((a) < (b)) ? (a) : (b))
+/// rfc90 instead of a dependency on Common/Stylization/StylizationDefs.h
+#define _METERS_PER_INCH 0.0254
+
 using namespace std;
 
 MG_IMPL_DYNCREATE(MgMap)
@@ -1169,3 +1175,27 @@
 {
     m_watermarkUsage = watermarkUsage;
 }
+/////////////////////////////////////////////////////////////////////
+// compute the tile coordinates from the x y index of the tiles and the meta tiling factor
+void MgMap::GetTileCoords(int metaTileFactor, int tileColumn, int tileRow,
+    double &tileMinX, double &tileMaxX , double &tileMinY ,double & tileMaxY)
+{
+    Ptr<MgEnvelope> mapExtent = this->GetMapExtent();
+    Ptr<MgCoordinate> pt00 = mapExtent->GetLowerLeftCoordinate();
+    Ptr<MgCoordinate> pt11 = mapExtent->GetUpperRightCoordinate();
+    double mapMinX = rs_min(pt00->GetX(), pt11->GetX());
+    double mapMaxX = rs_max(pt00->GetX(), pt11->GetX());
+    double mapMinY = rs_min(pt00->GetY(), pt11->GetY());
+    double mapMaxY = rs_max(pt00->GetY(), pt11->GetY());
+
+    double scale = this->GetViewScale();
+    double metersPerUnit  = this->GetMetersPerUnit();
+    double metersPerPixel = _METERS_PER_INCH / MgTileParameters::tileDPI;
+    double tileWidthMCS   = (double)MgTileParameters::tileWidth  * metersPerPixel * scale / metersPerUnit;
+    double tileHeightMCS  = (double)MgTileParameters::tileHeight * metersPerPixel * scale / metersPerUnit;
+
+    tileMinX = mapMinX + (double)(tileColumn  ) * tileWidthMCS;  // left edge
+    tileMaxX = mapMinX + (double)(tileColumn+ metaTileFactor) * tileWidthMCS;  // right edge
+    tileMinY = mapMaxY - (double)(tileRow   + metaTileFactor) * tileHeightMCS; // bottom edge
+    tileMaxY = mapMaxY - (double)(tileRow     ) * tileHeightMCS; // top edge
+}

Modified: sandbox/rfc90.2/MgDev/Common/MapGuideCommon/MapLayer/Map.h
===================================================================
--- sandbox/rfc90.2/MgDev/Common/MapGuideCommon/MapLayer/Map.h	2011-06-28 17:05:29 UTC (rev 5954)
+++ sandbox/rfc90.2/MgDev/Common/MapGuideCommon/MapLayer/Map.h	2011-06-28 23:45:26 UTC (rev 5955)
@@ -613,6 +613,16 @@
     ///
     virtual void SetWatermarkUsage(INT32 watermarkUsage);
 
+    /// \brief
+    /// compute the coordinates of a tile, increase size by meta tiling Factor sm_useMetaTiles
+    ///
+    /// \param in metaTileFactor, tileColumn, tileRow
+    /// \param out tileMinX,tileMinY. tileMaxX , tileMaxY
+    /// min,max corners of the tile
+    ///
+    virtual void GetTileCoords(int metaTileFactor, int tileColumn, int tileRow, 
+        double &tileMinX, double &tileMaxX , double &tileMinY ,double & tileMaxY);
+    
 protected:
 
     //////////////////////////////////////////////////////////////////

Modified: sandbox/rfc90.2/MgDev/Common/MapGuideCommon/Services/ImageFormats.cpp
===================================================================
--- sandbox/rfc90.2/MgDev/Common/MapGuideCommon/Services/ImageFormats.cpp	2011-06-28 17:05:29 UTC (rev 5954)
+++ sandbox/rfc90.2/MgDev/Common/MapGuideCommon/Services/ImageFormats.cpp	2011-06-28 23:45:26 UTC (rev 5955)
@@ -30,3 +30,4 @@
 const STRING MgImageFormats::Png8   = L"PNG8";
 const STRING MgImageFormats::Tiff   = L"TIF";
 const STRING MgImageFormats::Raw    = L"RAW";
+const STRING MgImageFormats::Meta   = L"META";

Modified: sandbox/rfc90.2/MgDev/Common/MapGuideCommon/Services/ImageFormats.h
===================================================================
--- sandbox/rfc90.2/MgDev/Common/MapGuideCommon/Services/ImageFormats.h	2011-06-28 17:05:29 UTC (rev 5954)
+++ sandbox/rfc90.2/MgDev/Common/MapGuideCommon/Services/ImageFormats.h	2011-06-28 23:45:26 UTC (rev 5955)
@@ -47,6 +47,9 @@
 
     /// Raw format
     static const STRING Raw;    /// \if INTERNAL value("RAW") \endif
+
+    /// Meta format for rfc90 meta tiling
+    static const STRING Meta;   /// \if INTERNAL value("META") \endif
 };
 
 #endif

Modified: sandbox/rfc90.2/MgDev/Common/MapGuideCommon/System/ConfigProperties.cpp
===================================================================
--- sandbox/rfc90.2/MgDev/Common/MapGuideCommon/System/ConfigProperties.cpp	2011-06-28 17:05:29 UTC (rev 5954)
+++ sandbox/rfc90.2/MgDev/Common/MapGuideCommon/System/ConfigProperties.cpp	2011-06-28 23:45:26 UTC (rev 5955)
@@ -110,6 +110,8 @@
 #define MG_CONFIG_MIN_FS_CP_EXCLUDED_LENGTH             0
 #define MG_CONFIG_MAX_FS_CP_EXCLUDED_LENGTH             1024
 
+#define MG_CONFIG_MAX_METATILE_DIM                      8
+
 // Default configuration filenames
 const STRING MgConfigProperties::DefaultConfigurationFilename                               = L"webconfig.ini";
 const STRING MgConfigProperties::ServerConfigurationFilename                                = L"serverconfig.ini";
@@ -390,6 +392,10 @@
 const INT32 MgConfigProperties::DefaultTileServicePropertyTileSizeY                         = 300;
 const STRING MgConfigProperties::TileServicePropertyImageFormat                             = L"ImageFormat";
 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
@@ -682,6 +688,8 @@
     { MgConfigProperties::TileServicePropertyTileSizeX                              , MgPropertyType::Int32     , 50                                    , 10000                                 , L""                                       },
     { MgConfigProperties::TileServicePropertyTileSizeY                              , MgPropertyType::Int32     , 50                                    , 10000                                 , L""                                       },
     { MgConfigProperties::TileServicePropertyImageFormat                            , MgPropertyType::String    , 2                                     , 4                                     , L""                                       },
+    { MgConfigProperties::TileServicePropertyUseMetaTiles                           , MgPropertyType::Int32    , 0                                     , MG_CONFIG_MAX_METATILE_DIM            , L""                                       },
+    { MgConfigProperties::TileServicePropertyLockMethod                             , MgPropertyType::Int32    , 1                                       , 3                                     , L""                                       },
     { L""                                                                           , 0                         , 0.0                                   , 0.0                                   , L""                                       }
 };
 

Modified: sandbox/rfc90.2/MgDev/Common/MapGuideCommon/System/ConfigProperties.h
===================================================================
--- sandbox/rfc90.2/MgDev/Common/MapGuideCommon/System/ConfigProperties.h	2011-06-28 17:05:29 UTC (rev 5954)
+++ sandbox/rfc90.2/MgDev/Common/MapGuideCommon/System/ConfigProperties.h	2011-06-28 23:45:26 UTC (rev 5955)
@@ -534,7 +534,14 @@
     /// Sets the limit on the number of cached MgMap objects used for tile generation
     static const STRING TileServicePropertyTiledMapCacheSize;           /// value("TiledMapCacheSize")
     static const INT32 DefaultTileServicePropertyTiledMapCacheSize;     /// value(10)
+    /// Sets the number of metatiles used for tile generation
+    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.2/MgDev/Common/Renderers/AGGRenderer.cpp
===================================================================
--- sandbox/rfc90.2/MgDev/Common/Renderers/AGGRenderer.cpp	2011-06-28 17:05:29 UTC (rev 5954)
+++ sandbox/rfc90.2/MgDev/Common/Renderers/AGGRenderer.cpp	2011-06-28 23:45:26 UTC (rev 5955)
@@ -63,6 +63,8 @@
 #include "RSDWFInputStream.h"
 
 #include "RenderUtil.h"
+// simple define to avoid dependency cycles
+#define MgImageFormats_Meta L"META"
 
 using namespace DWFToolkit;
 using namespace DWFCore;
@@ -258,9 +260,20 @@
 // a bytestream in the given image format using the provided colorPalette
 // if given.
 RS_ByteData* AGGRenderer::Save(const RS_String& format, int width, int height,
-                               RS_ColorVector* baseColorPalette)
+                               RS_ColorVector* baseColorPalette, unsigned int* imagebuffer)
 {
-    return AGGImageIO::Save(format, m_rows, m_width, m_height, width, height, m_bgcolor, baseColorPalette);
+    if (format == MgImageFormats_Meta)
+    {
+//        if (imagebuffer == NULL)  // this musnt happen
+//            return NULL;
+        int imagebufferByteSize = width*height*4; // multiply 32 bit pixel by 4 bytes
+        return new RS_ByteData((unsigned char*) m_rows, imagebufferByteSize);
+    } else {
+        if (imagebuffer)       // use imagebuffer from previous meta tiling pass
+            return AGGImageIO::Save(format, imagebuffer, m_width, m_height, width, height, m_bgcolor, baseColorPalette);
+        else
+            return AGGImageIO::Save(format, m_rows, m_width, m_height, width, height, m_bgcolor, baseColorPalette);
+    }
 }
 
 

Modified: sandbox/rfc90.2/MgDev/Common/Renderers/AGGRenderer.h
===================================================================
--- sandbox/rfc90.2/MgDev/Common/Renderers/AGGRenderer.h	2011-06-28 17:05:29 UTC (rev 5954)
+++ sandbox/rfc90.2/MgDev/Common/Renderers/AGGRenderer.h	2011-06-28 23:45:26 UTC (rev 5955)
@@ -152,7 +152,7 @@
     RENDERERS_API void Save(const RS_String& filename, const RS_String& format);
     RENDERERS_API void Save(const RS_String& filename, const RS_String& format, int width, int height);
     RENDERERS_API RS_ByteData* Save(const RS_String& format, int width, int height,
-                                    RS_ColorVector* baseColorPalette = NULL);
+                                    RS_ColorVector* baseColorPalette = NULL, unsigned int * framebuf = NULL);
 
     RENDERERS_API void Combine(const RS_String& fileIn1, const RS_String& fileIn2, const RS_String& fileOut);
     RENDERERS_API void SetWorldToScreenTransform(SE_Matrix& xform);

Modified: sandbox/rfc90.2/MgDev/Server/src/Core/serverconfig.ini
===================================================================
--- sandbox/rfc90.2/MgDev/Server/src/Core/serverconfig.ini	2011-06-28 17:05:29 UTC (rev 5954)
+++ sandbox/rfc90.2/MgDev/Server/src/Core/serverconfig.ini	2011-06-28 23:45:26 UTC (rev 5955)
@@ -86,23 +86,29 @@
 ConnectionTimerInterval            = 60
 DefaultMessageLocale               = en
 DisplayName                        =
-FdoPath                            = FDO/
+#FdoPath                            = FDO/
+FdoPath                            =C:\Program Files\OSGeo\MapGuide\Server\Fdo\
 LicenseServerPath                  = @localhost
 Locale                             =
 LogsDelimiter                      = \t
 LogsDetail                         =
-LogsPath                           = Logs/
+#LogsPath                           = Logs/
+LogsPath                           =C:\Program Files\OSGeo\MapGuide\Server\Logs\
 MachineIp                          = 127.0.0.1
 MaxLogFileSize                     = 1024
 MaxLogFileSizeEnabled              = 0
 PreCacheMaps                       =
 Renderer                           = AGG
-ResourcesPath                      = Resources/
+#ResourcesPath                      = Resources/
+ResourcesPath                      =C:\Program Files\OSGeo\MapGuide\Server\Resources\
 SerialNumber                       =
 TcpIpMtu                           = 1460
-TempPath                           = Temp/
-WfsDocumentPath                    = Wfs/
-WmsDocumentPath                    = Wms/
+#TempPath                           = Temp/
+#WfsDocumentPath                    = Wfs/
+#WmsDocumentPath                    = Wms/
+TempPath                           =C:\Program Files\OSGeo\MapGuide\Server\Temp\
+WfsDocumentPath                    =C:\Program Files\OSGeo\MapGuide\Server\Wfs\
+WmsDocumentPath                    =C:\Program Files\OSGeo\MapGuide\Server\Wms\
 
 [AdministrativeConnectionProperties]
 # *****************************************************************************
@@ -383,14 +389,24 @@
 #                                  are stored
 # SiteRepositoryPath               Path where the Site repository is stored
 # *****************************************************************************
-LibraryRepositoryPath              = Repositories/Library/
-LibraryResourceDataFilePath        = Repositories/Library/DataFiles/
-PackagesPath                       = Packages/
+#LibraryRepositoryPath              =C:\Program Files\OSGeo\MapGuide\Server\Repositories\Library\
+#LibraryResourceDataFilePath        =C:\Program Files\OSGeo\MapGuide\Server\Repositories\Library\DataFiles\
+#LibraryRepositoryPath              = Repositories/Library/
+#LibraryResourceDataFilePath        = Repositories/Library/DataFiles/
+LibraryRepositoryPath              =C:\Program Files\OSGeo\MapGuide\BigLibrary
+LibraryResourceDataFilePath        =C:\Program Files\OSGeo\MapGuide\BigLibrary\DataFiles
+
+
+#LibraryRepositoryPath              = E:/MapGuide/Library
+#LibraryResourceDataFilePath        = E:/MapGuide/Library/DataFiles/
+#PackagesPath                       = Packages/
+PackagesPath                       =C:\Program Files\OSGeo\MapGuide\Server\Packages\
 RepositoryCheckpointsTimerInterval = 600
 ResourceChangeTimerInterval        = 5
 ResourceDataFileTrashFolderName    = Trash
 ResourcePermissionCacheSize        = 1000
-ResourceSchemaFilePath             = Schema/
+ResourceSchemaFilePath             = C:\Program Files\OSGeo\MapGuide\Server\Schema
+#ResourceSchemaFilePath             = Schema/
 SessionRepositoriesConfig          = FilePerSession
 SessionRepositoriesLimit           = 200
 SessionRepositoryPath              = Repositories/Session/
@@ -432,14 +448,18 @@
 #                                       50 < value <= 10000
 # ImageFormat                      Image format for generated tiles
 #                                       PNG, PNG8, GIF or JPG
+# UseMetaTiles										 set the meta tile factor used for rendering the tiles
+#																				0 is off, 1 is not changing the tilesize
 # *****************************************************************************
 RenderOnly                         = 0
-TileCachePath                      = Repositories/TileCache/
+#TileCachePath                      = Repositories/TileCache/
+TileCachePath                      =C:\Program Files\OSGeo\MapGuide\Server\Repositories\TileCache\
 TileColumnsPerFolder               = 30
 TileRowsPerFolder                  = 30
 DefaultTileSizeX                   = 300
 DefaultTileSizeY                   = 300
-ImageFormat                        = PNG
+ImageFormat                        = PNG8
+UseMetaTiles											 = 3
 
 [AccessLogProperties]
 # *****************************************************************************

Modified: sandbox/rfc90.2/MgDev/Server/src/PostBuild/PostBuild.mak
===================================================================
--- sandbox/rfc90.2/MgDev/Server/src/PostBuild/PostBuild.mak	2011-06-28 17:05:29 UTC (rev 5954)
+++ sandbox/rfc90.2/MgDev/Server/src/PostBuild/PostBuild.mak	2011-06-28 23:45:26 UTC (rev 5955)
@@ -93,7 +93,8 @@
 
 CopyFdoComponentsDebug : ..\..\..\Oem\FDO\*.*
     if NOT EXIST ..\..\bin\debug\FDO\nul mkdir ..\..\bin\debug\FDO
-    xcopy /r /d /y /s ..\..\..\Oem\FDO\bin\Release ..\..\bin\debug\FDO\
+    if EXIST ..\..\..\Oem\FDO\bin\Release xcopy /r /d /y /s ..\..\..\Oem\FDO\bin\Release ..\..\bin\debug\FDO\  
+    if EXIST ..\..\..\Oem\FDO\bin\Debug xcopy /r /d /y /s ..\..\..\Oem\FDO\bin\Debug ..\..\bin\debug\FDO\  
 
 CopyFdoProvidersDebug : ..\..\..\Oem\FDO\ProviderList\ServerCommunity\providers.xml
     xcopy /r /d /y "..\..\..\Oem\FDO\ProviderList\ServerCommunity\providers.xml" ..\..\bin\debug\FDO\

Modified: sandbox/rfc90.2/MgDev/Server/src/Services/Rendering/ServerRenderingService.cpp
===================================================================
--- sandbox/rfc90.2/MgDev/Server/src/Services/Rendering/ServerRenderingService.cpp	2011-06-28 17:05:29 UTC (rev 5954)
+++ sandbox/rfc90.2/MgDev/Server/src/Services/Rendering/ServerRenderingService.cpp	2011-06-28 23:45:26 UTC (rev 5955)
@@ -36,6 +36,7 @@
 static const INT32 FILTER_SELECTABLE = 2;
 static const INT32 FILTER_HASTOOLTIPS = 4;
 
+INT32 MgServerRenderingService::sm_useMetaTiles = 0;     // 0 = no metatiling
 inline bool hasColorMap (STRING format)
 {
     return format == L"PNG8" || format == L"GIF";
@@ -126,6 +127,13 @@
                           MgConfigProperties::DefaultRenderingServicePropertyGeneralizeData);
     AGGRenderer::s_bGeneralizeData = bGeneralizeData;
     GDRenderer::s_bGeneralizeData = bGeneralizeData;
+
+    pConf->GetIntValue(
+    MgConfigProperties::TileServicePropertiesSection,
+    MgConfigProperties::TileServicePropertyUseMetaTiles,
+    sm_useMetaTiles,
+    MgConfigProperties::DefaultTileServicePropertyUseMetaTiles);
+
 }
 
 
@@ -180,27 +188,20 @@
     // upper left corner of the map extent
     // ------------------------------------------------------
 
-    Ptr<MgEnvelope> mapExtent = map->GetMapExtent();
-    Ptr<MgCoordinate> pt00 = mapExtent->GetLowerLeftCoordinate();
-    Ptr<MgCoordinate> pt11 = mapExtent->GetUpperRightCoordinate();
-    double mapMinX = rs_min(pt00->GetX(), pt11->GetX());
-    double mapMaxX = rs_max(pt00->GetX(), pt11->GetX());
-    double mapMinY = rs_min(pt00->GetY(), pt11->GetY());
-    double mapMaxY = rs_max(pt00->GetY(), pt11->GetY());
+    double tileMinX,tileMaxX ,tileMinY ,tileMaxY;
+    if (sm_useMetaTiles) // compute the coordinates of the meta tile
+        map->GetTileCoords(sm_useMetaTiles, tileColumn, tileRow, tileMinX,tileMaxX ,tileMinY ,tileMaxY);
+    else // meta tile factor zero (off) means we compute with a factor 1 
+        map->GetTileCoords(1, tileColumn, tileRow, tileMinX,tileMaxX ,tileMinY ,tileMaxY); 
 
-    double metersPerUnit  = map->GetMetersPerUnit();
-    double metersPerPixel = METERS_PER_INCH / MgTileParameters::tileDPI;
-    double tileWidthMCS   = (double)MgTileParameters::tileWidth  * metersPerPixel * scale / metersPerUnit;
-    double tileHeightMCS  = (double)MgTileParameters::tileHeight * metersPerPixel * scale / metersPerUnit;
-
-    double tileMinX = mapMinX + (double)(tileColumn  ) * tileWidthMCS;  // left edge
-    double tileMaxX = mapMinX + (double)(tileColumn+1) * tileWidthMCS;  // right edge
-    double tileMinY = mapMaxY - (double)(tileRow   +1) * tileHeightMCS; // bottom edge
-    double tileMaxY = mapMaxY - (double)(tileRow     ) * tileHeightMCS; // top edge
-
+    // METATILING dont forget to increase the bitmap for the larger tile and set the format
+    int metaFactor = sm_useMetaTiles?sm_useMetaTiles:1;
     // make the call to render the tile
-    ret = RenderTile(map, baseGroup, scaleIndex, MgTileParameters::tileWidth, MgTileParameters::tileHeight, scale,
-                     tileMinX, tileMaxX, tileMinY, tileMaxY, MgTileParameters::tileFormat);
+    ret = RenderTile(map, baseGroup, scaleIndex, MgTileParameters::tileWidth * metaFactor, 
+                                                 MgTileParameters::tileHeight * metaFactor, 
+                                                 scale, tileMinX, tileMaxX, tileMinY, tileMaxY, 
+                                                 sm_useMetaTiles?     MgImageFormats::Meta
+                                                                    : MgTileParameters::tileFormat);
 
     MG_CATCH_AND_THROW(L"MgServerRenderingService.RenderTile")
 
@@ -276,8 +277,71 @@
 
     return ret.Detach();
 }
+///////////////////////////////////////////////////////////////////////////////
+// gets called with a bitmap in the bytereader to be split up into 4 images
+MgByteReader* MgServerRenderingService::RenderTileFromMetaTile(MgMap* map, MgByteReader* metaTile, 
+                                                           int subTileX, int subTileY)
+{
+    MgByteSource* bs = metaTile->GetByteSource();
+    ByteSourceImpl* bsimp = bs->GetSourceImpl();
+    assert (bs->GetMimeType() == MgImageFormats::Meta);
+    int size = (int) bsimp->GetLength();
+    class MyByteSource {
+    public:
+        virtual ~MyByteSource() {} ;        // needed to get the correct sizeof for object
+        MgByte* Bytes() { return m_data; }
+        Ptr<MgByte> m_data;
+        INT32   m_pos;
+    } *source = (MyByteSource *) bsimp;
 
+    // some checking: the complete meta tile should be in the framebuffer handed over
+    int expectedSize = 4 * (sm_useMetaTiles * MgTileParameters::tileWidth) 
+            * (sm_useMetaTiles * MgTileParameters::tileHeight);
+    if (size != expectedSize) {
+        throw new MgInvalidArgumentException(L"MgServerRenderingService.RenderTileFromMetaTile",
+          __LINE__, __WFILE__, NULL, L"MgWrongSizeOfMetaTile", NULL);
+    }
 
+    MgByte* byteBuffer = source->Bytes();
+    unsigned char* byteBuf = byteBuffer->Bytes();
+    assert(size == byteBuffer->GetLength());            // double check the buffers
+
+    // use the map's background color, but always make it fully transparent
+    RS_Color bgColor;
+    StylizationUtil::ParseColor(map->GetBackgroundColor(), bgColor);
+    bgColor.alpha() = 0;    
+    auto_ptr<SE_Renderer> dr(CreateRenderer(MgTileParameters::tileWidth,MgTileParameters::tileHeight, bgColor, true));
+    RS_ColorVector tileColorPalette;
+    if (m_rendererName == L"AGG" && hasColorMap(MgTileParameters::tileFormat))
+    {
+        MgMappingUtil::ParseColorStrings(&tileColorPalette, map);
+    }
+
+    // copy tile from meta framebuffer to new one...
+    // use unsigned int pointer arithmetic for pixels!
+
+    // get pointer to metatile framebuf
+    unsigned int *framebuf = (unsigned int*) byteBuf; 
+
+    // allocate subtile buffer to copy new framebuf with changed dimensions
+    // place buffer in None allocated MgByte auto_ptr object for later destruction
+    auto_ptr<MgByte> subTileBytes (new MgByte((unsigned char*)new unsigned int[MgTileParameters::tileWidth * MgTileParameters::tileHeight],
+                                                MgTileParameters::tileWidth * MgTileParameters::tileHeight * sizeof(int) , MgByte::New));
+    // get the pointer to the internal target buffer
+    unsigned int* subTileBuf = (unsigned int*) subTileBytes->Bytes();    
+    for (int y=0; y < MgTileParameters::tileHeight; y++)    // rows
+      for (int x=0; x < MgTileParameters::tileWidth; x++)    // columns innerloop
+     {
+         *(subTileBuf   + x 
+                        + y * MgTileParameters::tileWidth)                 // target address in small tile
+             = *(framebuf + (x + (subTileX * MgTileParameters::tileWidth))   // X address in meta tile
+                          + (y + (subTileY * MgTileParameters::tileHeight)) 
+                             * MgTileParameters::tileWidth * sm_useMetaTiles);  // use width of metaTile here
+     }
+    // we need to pass the optional colortable param to satisfy the overloaded call
+    return SaveBitmap(map, dr.get(), MgTileParameters::tileWidth,MgTileParameters::tileHeight,MgTileParameters::tileFormat, subTileBuf);
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // default arg bKeepSelection = true
 MgByteReader* MgServerRenderingService::RenderDynamicOverlay(MgMap* map,
@@ -1177,6 +1241,18 @@
     dr->ProcessPolyline(&lb, ls);
     //-------------------------------------------------------
 */
+    return SaveBitmap(map, dr, saveWidth, saveHeight, format);
+}
+///////////////////////////////////////////////////////////////////////////////
+/// take the framebuffer/bitmap after rendering - another method extraction
+/// and turn it into the image of given format
+MgByteReader* MgServerRenderingService::SaveBitmap(MgMap* map,
+                                                   SE_Renderer* dr,
+                                                   INT32 saveWidth,
+                                                   INT32 saveHeight,
+                                                   CREFSTRING format,
+                                                   unsigned int* framebuf)
+{
     Ptr<MgByteReader> ret;
 
     // get a byte representation of the image
@@ -1187,24 +1263,30 @@
         // call the image renderer to create the image
         if (wcscmp(m_rendererName.c_str(), L"AGG") == 0)
         {
-            //-------------------------------------------------------
-            /// RFC60 code to correct colormaps by UV
-            //-------------------------------------------------------
-            // We examine the expressions collected from xml definitions of all layers.
-            // The map object has a list from all color entries found in the most recent
-            // layer stylization.
-            // * TODO - currently they are interpreted as ffffffff 32-bit RGBA string values
-            // * adding expresssions and other interpretations should be done in ParseColorStrings
-            // * the color Palette for the renderer is a vector<RS_Color>
-            if (hasColorMap(format))
+            if (format == MgImageFormats::Meta)  // we dont use the colorPalette here for meta tiling
+            {                       // as this call only returns the framebuffer
+                 data.reset(((AGGRenderer*)dr)->Save(format, saveWidth, saveHeight, NULL, NULL));
+                 // copy the framebuffer into the reader TODO: find a way to pass the pointer
+            } else
             {
-                RS_ColorVector tileColorPalette;
-                MgMappingUtil::ParseColorStrings(&tileColorPalette, map);
-//              printf("<<<<<<<<<<<<<<<<<<<<< MgServerRenderingService::ColorPalette->size(): %d\n", tileColorPalette.size());
-                data.reset(((AGGRenderer*)dr)->Save(format, saveWidth, saveHeight, &tileColorPalette));
+                //-------------------------------------------------------
+                /// RFC60 code to correct colormaps by UV
+                //-------------------------------------------------------
+                // We examine the expressions collected from xml definitions of all layers.
+                // The map object has a list from all color entries found in the most recent
+                // layer stylization.
+                // * TODO - currently they are interpreted as ffffffff 32-bit RGBA string values
+                // * adding expresssions and other interpretations should be done in ParseColorStrings
+                // * the color Palette for the renderer is a vector<RS_Color>
+                if (hasColorMap(format))
+                {
+                    RS_ColorVector tileColorPalette;
+                    MgMappingUtil::ParseColorStrings(&tileColorPalette, map);
+                    data.reset(((AGGRenderer*)dr)->Save(format, saveWidth, saveHeight, &tileColorPalette, framebuf));
+                }
+                else
+                    data.reset(((AGGRenderer*)dr)->Save(format, saveWidth, saveHeight, NULL, framebuf));
             }
-            else
-                data.reset(((AGGRenderer*)dr)->Save(format, saveWidth, saveHeight, NULL));
         }
         else
             data.reset(((GDRenderer*)dr)->Save(format, saveWidth, saveHeight));
@@ -1228,6 +1310,8 @@
             bs->SetMimeType(MgMimeType::Png);
         else if (format == MgImageFormats::Tiff)
             bs->SetMimeType(MgMimeType::Tiff);
+        else if (format == MgImageFormats::Meta)         // add a mimetype for our metatile
+            bs->SetMimeType(MgMimeType::Meta);
 
         ret = bs->GetReader();
     }

Modified: sandbox/rfc90.2/MgDev/Server/src/Services/Rendering/ServerRenderingService.h
===================================================================
--- sandbox/rfc90.2/MgDev/Server/src/Services/Rendering/ServerRenderingService.h	2011-06-28 17:05:29 UTC (rev 5954)
+++ sandbox/rfc90.2/MgDev/Server/src/Services/Rendering/ServerRenderingService.h	2011-06-28 23:45:26 UTC (rev 5955)
@@ -41,6 +41,11 @@
                                      INT32 tileColumn,
                                      INT32 tileRow);
 
+    virtual MgByteReader* RenderTileFromMetaTile(MgMap* map,
+                                             MgByteReader* metaTile,
+                                             INT32 subTileX,
+                                             INT32 subTileY);
+
     virtual MgByteReader* RenderDynamicOverlay(MgMap* map,
                                                MgSelection* selection,
                                                CREFSTRING format);
@@ -163,6 +168,13 @@
                              double mcsMinY,
                              double mcsMaxY,
                              CREFSTRING format);
+    // extracted method to save bitmap into image for reuse
+    MgByteReader* SaveBitmap(MgMap* map,
+                             SE_Renderer* dr,
+                             INT32 saveWidth,
+                             INT32 saveHeight,
+                             CREFSTRING format,
+                             unsigned int* framebuf = 0);
 
     // helper used by other methods
     MgByteReader* RenderMapInternal(MgMap* map,
@@ -223,6 +235,7 @@
     INT32 m_minRasterGridSize;
     double m_rasterGridSizeOverrideRatio;
     INT32 m_renderSelectionBatchSize;
+    static INT32 sm_useMetaTiles;
     INT32 m_maxRasterImageWidth;
     INT32 m_maxRasterImageHeight;
 };

Modified: sandbox/rfc90.2/MgDev/Server/src/Services/Tile/ServerTileService.cpp
===================================================================
--- sandbox/rfc90.2/MgDev/Server/src/Services/Tile/ServerTileService.cpp	2011-06-28 17:05:29 UTC (rev 5954)
+++ sandbox/rfc90.2/MgDev/Server/src/Services/Tile/ServerTileService.cpp	2011-06-28 23:45:26 UTC (rev 5955)
@@ -17,6 +17,8 @@
 
 #include "MapGuideCommon.h"
 #include "ServerTileService.h"
+#include "ServerRenderingService.h"
+//#include <sstream>
 
 IMPLEMENT_CREATE_SERVICE(MgServerTileService)
 
@@ -27,6 +29,8 @@
 INT32 MgServerTileService::sm_creationCutoffTime = 120;     // in seconds
 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()
 {
@@ -63,12 +67,36 @@
                 sm_mapCacheSize,
                 MgConfigProperties::DefaultTileServicePropertyTiledMapCacheSize);
 
+            configuration->GetIntValue(
+                MgConfigProperties::TileServicePropertiesSection,
+                MgConfigProperties::TileServicePropertyUseMetaTiles,
+                sm_useMetaTiles,
+                MgConfigProperties::DefaultTileServicePropertyUseMetaTiles);
+
+             configuration->GetIntValue(
+                MgConfigProperties::TileServicePropertiesSection,
+                MgConfigProperties::TileServicePropertyLockMethod,
+                sm_lockMethod,
+                MgConfigProperties::DefaultTileServicePropertyLockMethod);
+
             MgTileCache::Initialize();
             sm_initialized = true;
         }
     }
+    m_tileCache = new MgTileCache(this);
+    
+    // bail out if metatile factor to large (allocation problem)
+    if (sm_useMetaTiles > 7)
+    {
+        std::wstringstream text;
+        text << L"MetaTiling Config: " << sm_useMetaTiles << L" is larger than maximum " << MgConfigProperties::sm_cviTileServiceProperties->m_maximumValue;
 
-    m_tileCache = new MgTileCache();
+        MgStringCollection arguments;
+        arguments.Add(text.str().c_str());
+
+        throw new MgConfigurationException(L"MgServerTileService.CTOR",
+            __LINE__, __WFILE__, &arguments, L"MgTooLargeMetaTilingFactor", NULL);
+    }
 }
 
 
@@ -91,11 +119,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
+        //(found = m_tileCache->GetLockMap().count(tilePathname)) 
+        for (INT32 diffTime=0;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))
     {
@@ -105,7 +152,10 @@
 
         if (diffTime < sm_creationCutoffTime)
         {
-            ACE_OS::sleep(sm_pollingInterval);
+            // sm_pollingInterval om milliseconds
+            int sec = sm_pollingInterval/1000;
+            ACE_Time_Value polInt (sec, (sm_pollingInterval - (sec*1000))*1000);
+            ACE_OS::sleep(polInt);
         }
         else
         {
@@ -121,13 +171,48 @@
 ///////////////////////////////////////////////////////////////////////////////
 // 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.
+// lockfile and look for map in mapcache. APIVERSION 1.2
 MgByteReader* MgServerTileService::GetTile(MgResourceIdentifier* mapDefinition,
                                            CREFSTRING baseMapLayerGroupName,
                                            INT32 tileColumn,
                                            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);
+    }
+    // 0 is default == defaut tiling mode
+    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;
@@ -161,7 +246,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);
@@ -188,13 +273,13 @@
             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);
 
                 throw new MgFileIoException(L"MgServerTileService.GetTile",
-                    __LINE__, __WFILE__, &arguments, L"MgUnableToLockTileFile", NULL);
+                    __LINE__, __WFILE__, &arguments, L"MgFoundBlockingLockFile", NULL);
             }
 
             // try getting the tile from the cache
@@ -269,7 +354,329 @@
     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);
+
+    //  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)
+    {
+    case 3:    // use ace conditions no files
+        m_tileCache->WaitForLock(metaTilePathname);
+        break;
+    case 2:
+        if (DetectTileLockFile(lockPathname, tilePathname))
+        {
+#ifdef _DEBUG
+            std::wstringstream text;
+            text << L"(" << ACE_OS::thr_self() << L") METATILE: DeletedDanglingLockfile(" << tileRow  
+                << L", " <<  tileColumn << L") " << lockPathname << L")\n" ;
+            ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
+#endif
+            // TODO: Handle the exception by displaying a tile with an error message?
+            MgFileUtil::DeleteFile(lockPathname, true);
+        }        
+        break;
+    default:
+    case 1: // default
+        if (DetectTileLockFile(metaTileLockPathname, metaTilePathname))
+        {
+#ifdef _DEBUG
+            std::wstringstream text;
+            text << L"(" << ACE_OS::thr_self() << L") METATILE: DeletedDanglingLockfile(" << metaTileRow  
+                << L", " <<  metaTileColumn << L") " << metaTileLockPathname << L")\n" ;
+            ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
+#endif
+            // 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);
+#ifdef _DEBUG
+        std::wstringstream text;
+        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()));
+#endif
+    // 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;
+
+        // 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.
+        { // ------------------------ 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?
+                m_tileCache->LockTile(metaTilePathname);
+                break;
+            case 2: // 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"MgUnableToLockMetaTileFile", NULL);
+                }        
+                break;
+            default:
+            case 1:
+                if (DetectTileLockFile(metaTileLockPathname, metaTilePathname))
+                {
+                    MgStringCollection arguments;
+                    arguments.Add(metaTileLockPathname);
+                    throw new MgFileIoException(L"MgServerTileService.GetTile",
+                        __LINE__, __WFILE__, &arguments, L"MgUnableToLockMetaTileFile", NULL);
+                }        
+            } // end switch  ------------------------ LLLLOOOOOOCCCCCKKKKKIIIIINNNGGGG
+            
+            // try getting the tile from the cache second time ???????????????????????????????????????????
+            cacheHit = ret = m_tileCache->Get(tilePathname);
+
+            if (NULL != ret)
+            {
+#ifdef _DEBUG
+                std::wstringstream text;
+                text << L"(" << ACE_OS::thr_self() << L") CACHEHIT2: GetTile(" << tileRow  << L", " <<  tileColumn << L") " << tilePathname << L"\n";
+                ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
+#endif
+        /////////////////////////////////// tile was in tileCache .. done.
+                break;  
+            } else {
+#ifdef _DEBUG
+                std::wstringstream text;
+                text << L"(" << ACE_OS::thr_self() << L") CACHEMISS2: GetTile(" << tileRow  << L", " <<  tileColumn << L") " << tilePathname << L"\n";
+                ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
+#endif
+            }
+    
+            // ============================================================================ LOCKING
+            switch(sm_lockMethod) 
+            {
+            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);
+                }
+                m_tileCache->LockTile(metaTilePathname);
+                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])
+                    {
+                        MgStringCollection arguments;
+                        arguments.Add(subTilePathname[x][y]);
+
+                        throw new MgFileIoException(L"MgServerTileService.GetTile",
+                            __LINE__, __WFILE__, &arguments, L"MgUnableToCreateLockFile", NULL);
+                    }
+                    else
+                    {
+                        ACE_OS::fclose(subTileLockFile[x][y]);
+#ifdef _DEBUG
+                        std::wstringstream text;
+                        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
+                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);
+#ifdef _DEBUG
+                        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()));
+#endif
+                    }
+                } // end meta tiling loop for lockfiles
+
+            } // end switch
+            //=========================================================================
+            GetMapFromDefinition(mapDefinition, scaleIndex, map);
+        }   // end of mutex scope
+
+        // Render the larger meta tile but do not cache it yet! (sm_useMetaTiles [prohibits caching in GetTile)
+        STRING metaTileName = L"META" + metaTilePathname;
+#ifdef _DEBUG
+            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()));
+#endif
+        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)
+            {
+#ifdef _DEBUG
+                std::wstringstream text;
+                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()));
+#endif
+            }
+            // rewind the reader since setting the tile advances it to the end
+            if (img)
+            {
+                img->Rewind();
+            }
+        }
+        break;
+    }   // end of gettile loop end MgMap scope
+
+    MG_CATCH(L"MgServerTileService.GetTile")
+
+    // remove all lockfiles
+    switch(sm_lockMethod) // do the locking now
+    {
+    case 3:
+        m_tileCache->ClearLock(metaTilePathname);
+        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);
+                {
+#ifdef _DEBUG
+                    std::wstringstream text;
+                    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()));
+#endif
+                }
+            }
+        break;
+    case 1:
+    default:
+        if (NULL != lockFile)
+        {
+            MgFileUtil::DeleteFile(metaTileLockPathname, false);
+            {
+#ifdef _DEBUG
+                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()));
+#endif
+            }
+        }
+    } // end switch
+
+    MG_THROW()
+
+    if (!cacheHit) 
+    {
+#ifdef _DEBUG
+        std::wstringstream text;
+        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()));
+#endif
+    }
+
+    return ret.Detach();
+}
+
+
 ///////////////////////////////////////////////////////////////////////////////
 // look for the tile in the tilecache first
 MgByteReader* MgServerTileService::GetTile(MgMap* map,
@@ -305,7 +712,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);
@@ -323,7 +730,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);
@@ -396,7 +803,7 @@
         img = svcRendering->RenderTile(map, baseMapLayerGroupName, tileColumn, tileRow);
 
         // cache the tile
-        if (!sm_renderOnly)
+        if (!sm_renderOnly && !sm_useMetaTiles)
         {
             m_tileCache->Set(img, tilePathname);
 
@@ -453,7 +860,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);
@@ -651,3 +1058,43 @@
 {
     return MgTileParameters::tileHeight;
 }
+///////////////////////////////////////////////////////////////////////////////
+/// helper to retrieve map
+///////////////////////////////////////////////////////////////////////////////
+void MgServerTileService::GetMapFromDefinition (MgResourceIdentifier* mapDefinition, INT32 scaleIndex, Ptr<MgMap> &map)
+{
+    // Attempt use a cached & serialized MgMap object
+    Ptr<MgMemoryStreamHelper> cachedMap;
+    STRING mapString = mapDefinition->ToString();
+
+    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
+    {
+        // get the service from our helper method
+        Ptr<MgResourceService> resourceService = GetResourceServiceForMapDef(mapDefinition,
+                                            L"MgServerTileService.GetTile");
+        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);
+    }
+
+    double scale = map->GetFiniteDisplayScaleAt(scaleIndex);
+    map->SetViewScale(scale);
+}

Modified: sandbox/rfc90.2/MgDev/Server/src/Services/Tile/ServerTileService.h
===================================================================
--- sandbox/rfc90.2/MgDev/Server/src/Services/Tile/ServerTileService.h	2011-06-28 17:05:29 UTC (rev 5954)
+++ sandbox/rfc90.2/MgDev/Server/src/Services/Tile/ServerTileService.h	2011-06-28 23:45:26 UTC (rev 5955)
@@ -21,6 +21,13 @@
 #include "ServerTileDllExport.h"
 #include "TileCache.h"
 
+#define METATILES
+// used to define arrays on stack .... too much dependencies to move this into system config
+#define METAMAXDIM 8
+/// forward decl
+//class MgServerRenderingService; 
+struct RS_Bounds;
+class RS_Color;
 class MG_SERVER_TILE_API MgServerTileService : public MgTileService
 {
     DECLARE_CLASSNAME(MgServerTileService)
@@ -60,25 +67,44 @@
 
     void SetConnectionProperties(MgConnectionProperties* connProp);
 
+    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);
 
+    void GetMapFromDefinition (MgResourceIdentifier* mapDefinition, INT32 scaleIndex, Ptr<MgMap> &map);
+
     void ClearMapCache(CREFSTRING mapName);
 
     MgResourceService* GetResourceServiceForMapDef(MgResourceIdentifier* mapDefinition, CREFSTRING funcName);
+//    MgResourceService* m_resourceService;
 
     // member data
     Ptr<MgTileCache> m_tileCache;
 
     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;

Modified: sandbox/rfc90.2/MgDev/Server/src/Services/Tile/ServerTileService.vcproj
===================================================================
--- sandbox/rfc90.2/MgDev/Server/src/Services/Tile/ServerTileService.vcproj	2011-06-28 17:05:29 UTC (rev 5954)
+++ sandbox/rfc90.2/MgDev/Server/src/Services/Tile/ServerTileService.vcproj	2011-06-28 23:45:26 UTC (rev 5955)
@@ -44,7 +44,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..\..\Common\Foundation;..\..\..\..\Common\Geometry;..\..\..\..\Common\PlatformBase;..\..\..\..\Common\MapGuideCommon;..\..\..\..\Common\MdfModel;..\..\Common;..\..\Common\Base;..\..\Common\Manager;..\Mapping;..\..\..\..\Oem\ACE\ACE_wrappers;..\..\..\..\Oem\FDO\inc"
+				AdditionalIncludeDirectories="..\..\..\..\Common\Foundation;..\..\..\..\Common\Geometry;..\..\..\..\Common\PlatformBase;..\..\..\..\Common\MapGuideCommon;..\..\..\..\Common\MdfModel;..\..\Common;..\..\Common\Base;..\..\Common\Manager;..\Mapping;..\..\..\..\Oem\ACE\ACE_wrappers;..\..\..\..\Oem\FDO\inc;..\Rendering"
 				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;MG_SERVER_TILE_EXPORTS"
 				MinimalRebuild="true"
 				ExceptionHandling="2"
@@ -672,6 +672,7 @@
 				>
 				<Tool
 					Name="VCCLCompilerTool"
+					GeneratePreprocessedFile="0"
 				/>
 			</FileConfiguration>
 			<FileConfiguration
@@ -710,6 +711,14 @@
 		<File
 			RelativePath=".\ServerTileServiceBuild.cpp"
 			>
+			<FileConfiguration
+				Name="Debug|Win32"
+				>
+				<Tool
+					Name="VCCLCompilerTool"
+					GeneratePreprocessedFile="0"
+				/>
+			</FileConfiguration>
 		</File>
 		<File
 			RelativePath="..\..\Common\stdafx.h"

Modified: sandbox/rfc90.2/MgDev/Server/src/Services/Tile/TileCache.cpp
===================================================================
--- sandbox/rfc90.2/MgDev/Server/src/Services/Tile/TileCache.cpp	2011-06-28 17:05:29 UTC (rev 5954)
+++ sandbox/rfc90.2/MgDev/Server/src/Services/Tile/TileCache.cpp	2011-06-28 23:45:26 UTC (rev 5955)
@@ -17,18 +17,24 @@
 
 #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;
-
+ACE_Recursive_Thread_Mutex MgTileCache::sm_tileMutex;
+std::map<STRING,ACE_Condition<ACE_Recursive_Thread_Mutex>*> MgTileCache::sm_lockMap;
+////////////////////////////////////////////////////////////////////////////////
 // default constructor
-MgTileCache::MgTileCache()
+MgTileCache::MgTileCache(MgServerTileService* tileService)
 {
+    sm_tileService = tileService;   // keep pointer to parent
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -143,7 +149,8 @@
     GeneratePathnames(mapDef, scaleIndex, group, tileColumn, tileRow,
         tilePathname, lockPathname, createFullPath);
 }
-
+////////////////////////////////////////////////////////////////////////////////
+#define METATILEWAIT 300
 // returns any cached tile for the given pathname
 MgByteReader* MgTileCache::Get(CREFSTRING tilePathname)
 {
@@ -169,6 +176,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()
@@ -184,6 +202,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()));
+
     }
 }
 
@@ -420,4 +443,87 @@
     return name;
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// wait for a previous ace condition 
+void MgTileCache::WaitForLock(CREFSTRING tilePathname)
+{   // 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 (ACE_Recursive_Thread_Mutex, ace_mon, sm_tileMutex));
+    if (wait = sm_lockMap[tilePathname])
+    {   // lock has been found
+#ifdef _DEBUG
+        std::wstringstream text;
+        text << L"(" << ACE_OS::thr_self() << L") METATILE: WaitForLock1(" 
+            << tilePathname << L")\n" ;
+        ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
+#endif
+        //                ACE_Time_Value waitTime(METATILEWAIT);
+        if (-1 == wait->wait()) // wait forever
+        {
+#ifdef _DEBUG
+            std::wstringstream text;
+            text << L"(" << ACE_OS::thr_self() << L") METATILE: WaitForLockTimedOut1(" 
+                << tilePathname << L")\n" ;
+            ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
+#endif
+            MgStringCollection arguments;
+            arguments.Add(tilePathname);
+            throw new MgFileIoException(L"MgServerTileService.GetTile",
+                __LINE__, __WFILE__, &arguments, L"MgWaitForLockTimedOut", NULL);
+        } else {
+#ifdef _DEBUG
+            std::wstringstream text;
+            text << L"(" << ACE_OS::thr_self() << L") METATILE: WaitForLockCAUGHTSIGNAL1(" 
+                << tilePathname << L")\n" ;
+            ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
+#endif
+        }
+    }        
+}
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// locktile by creating ace condition 
+void MgTileCache::LockTile(CREFSTRING tilePathname)
+{
+    // 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 our map
+    sm_lockMap[tilePathname] = wait;
 
+#ifdef _DEBUG
+    std::wstringstream text;
+    text << L"(" << ACE_OS::thr_self() << L") METATILE: CreateLock(" << tilePathname << L"\n" ;
+    ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
+#endif
+} 
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// clear the ace condition
+void MgTileCache::ClearLock(CREFSTRING tilePathname)
+{
+    try 
+    {   // synchronize access to map
+        ACE_MT(ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon, sm_tileMutex));
+        ACE_Condition<ACE_Recursive_Thread_Mutex> *lock = sm_lockMap[tilePathname];  
+        if (lock) 
+        {   
+            int result = lock->broadcast();    // notify waiters of finished tile
+#ifdef _DEBUG
+            std::wstringstream text;
+            text << L"(" << ACE_OS::thr_self() << L") METATILE: Broadcast(" << tilePathname 
+                << L") returns: " << result << L"\n";
+            ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
+#endif
+        }
+        sm_lockMap.erase(tilePathname); // erase: this destroys the ace condition
+    } 
+    catch (MgException* e) 
+    {
+#ifdef _DEBUG
+        std::wstringstream text;
+        text << L"(" << ACE_OS::thr_self() << L") METATILE: Broadcastcrash (" << tilePathname 
+            << L")\n" << e->GetExceptionMessage() << L")\n";
+        ACE_DEBUG ((LM_DEBUG, text.str().c_str()));
+#endif
+        throw e;
+    }
+}

Modified: sandbox/rfc90.2/MgDev/Server/src/Services/Tile/TileCache.h
===================================================================
--- sandbox/rfc90.2/MgDev/Server/src/Services/Tile/TileCache.h	2011-06-28 17:05:29 UTC (rev 5954)
+++ sandbox/rfc90.2/MgDev/Server/src/Services/Tile/TileCache.h	2011-06-28 23:45:26 UTC (rev 5955)
@@ -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,11 @@
     void Clear(MgMap* map);
     void Clear(MgResourceIdentifier* mapDef);
 
+    static ACE_Recursive_Thread_Mutex sm_tileMutex;
+    void WaitForLock(CREFSTRING tilePathname);
+    void ClearLock(CREFSTRING tilePathname);
+    void LockTile(CREFSTRING tilePathname);
+
 protected:
     virtual void Dispose()
     {
@@ -75,6 +82,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

Modified: sandbox/rfc90.2/MgDev/build.bat
===================================================================
--- sandbox/rfc90.2/MgDev/build.bat	2011-06-28 17:05:29 UTC (rev 5954)
+++ sandbox/rfc90.2/MgDev/build.bat	2011-06-28 23:45:26 UTC (rev 5955)
@@ -76,7 +76,7 @@
 SET MG_OUTPUT_CSMAP=%MG_OUTPUT%\CS-Map
 SET MG_BUILD_COMPONENT=
 
-SET MG_DEFAULT_INSTALLDIR=C:\Program Files\MapGuideOpenSource2.0
+SET MG_DEFAULT_INSTALLDIR=C:\Program Files\OSGeo\MapGuide
 SET MG_ERROR=0
 
 rem ==================================================
@@ -336,9 +336,9 @@
 
 :build_doc
 echo [build]: Building Doc
-pushd %MG_DOC%
-call MgOpenSource_run_doxygen.bat
-popd
+rem pushd %MG_DOC%
+rem call MgOpenSource_run_doxygen.bat
+rem popd
 goto quit
 
 rem =======================================================



More information about the mapguide-commits mailing list