[mapguide-commits] r1090 - in trunk/MgDev: Common/Foundation/System
Common/MapGuideCommon/Resources Common/MapGuideCommon/System
Server/src/Common/Manager Server/src/Services/Rendering
Server/src/Services/Resource Server/src/Services/Tile
Server/src/UnitTesting
svn_mapguide at osgeo.org
svn_mapguide at osgeo.org
Fri Feb 2 20:06:40 EST 2007
Author: stevedang
Date: 2007-02-02 20:06:39 -0500 (Fri, 02 Feb 2007)
New Revision: 1090
Modified:
trunk/MgDev/Common/Foundation/System/FileUtil.cpp
trunk/MgDev/Common/MapGuideCommon/Resources/mapguide_en.res
trunk/MgDev/Common/MapGuideCommon/System/ConfigProperties.cpp
trunk/MgDev/Common/MapGuideCommon/System/ConfigProperties.h
trunk/MgDev/Server/src/Common/Manager/FdoConnectionManager.cpp
trunk/MgDev/Server/src/Services/Rendering/ServerRenderingService.cpp
trunk/MgDev/Server/src/Services/Resource/ServerResourceService.cpp
trunk/MgDev/Server/src/Services/Tile/ServerTileService.cpp
trunk/MgDev/Server/src/Services/Tile/ServerTileService.h
trunk/MgDev/Server/src/Services/Tile/TileCache.cpp
trunk/MgDev/Server/src/Services/Tile/TileCache.h
trunk/MgDev/Server/src/UnitTesting/TestTileService.cpp
Log:
Stability ?\226?\128?\147 Miscellaneous code cleanups and fixes:
- Fixed some threading problems in File Util.
- Fixed Tile Service unit tests (there were some codes previously commented out due to failures).
- Got rid of some compiling warnings in FDO Connection Manager.
- Implemented tile file locking mechanism to address some threading/file access problems.
Modified: trunk/MgDev/Common/Foundation/System/FileUtil.cpp
===================================================================
--- trunk/MgDev/Common/Foundation/System/FileUtil.cpp 2007-02-02 17:55:19 UTC (rev 1089)
+++ trunk/MgDev/Common/Foundation/System/FileUtil.cpp 2007-02-03 01:06:39 UTC (rev 1090)
@@ -219,13 +219,15 @@
RemoveSlashFromEndOfPath(path); // This must be done.
- ACE_MT(ACE_GUARD_RETURN(ACE_Recursive_Thread_Mutex, ace_mon, sm_mutex, false));
+ { // Begin guarding.
+ ACE_MT(ACE_GUARD_RETURN(ACE_Recursive_Thread_Mutex, ace_mon, sm_mutex, false));
#ifdef _WIN32
- success = ::_wstat(path.c_str(), &statInfo) == 0;
+ success = ::_wstat(path.c_str(), &statInfo) == 0;
#else
- success = ::stat(MgUtil::WideCharToMultiByte(path).c_str(), &statInfo) == 0;
+ success = ::stat(MgUtil::WideCharToMultiByte(path).c_str(), &statInfo) == 0;
#endif
+ } // End guarding.
if (!success && strict)
{
@@ -297,6 +299,8 @@
{
MG_TRY()
+ ACE_MT(ACE_GUARD(ACE_Recursive_Thread_Mutex, ace_mon, sm_mutex));
+
if (PathnameExists(path))
{
if (strict)
@@ -311,7 +315,6 @@
return;
}
- ACE_MT(ACE_GUARD(ACE_Recursive_Thread_Mutex, ace_mon, sm_mutex));
int errCode = ACE_OS::mkdir(MG_WCHAR_TO_TCHAR(path));
if (0 != errCode)
@@ -400,6 +403,8 @@
MG_TRY()
+ ACE_MT(ACE_GUARD_RETURN(ACE_Recursive_Thread_Mutex, ace_mon, sm_mutex, false));
+
if (!PathnameExists(path))
{
if (strict)
@@ -414,7 +419,6 @@
return false;
}
- ACE_MT(ACE_GUARD_RETURN(ACE_Recursive_Thread_Mutex, ace_mon, sm_mutex, false));
numEntries = ACE_OS::scandir(MG_WCHAR_TO_TCHAR(path), &dirEntries,
MgDirEntrySelector, MgDirEntryComparator);
@@ -487,11 +491,11 @@
STRING MgFileUtil::ChangeDirectory(CREFSTRING path)
{
- ACE_MT(ACE_GUARD_RETURN(ACE_Recursive_Thread_Mutex, ace_mon, sm_mutex, L""));
-
STRING currDir;
ACE_TCHAR buffer[MAXPATHLEN];
+ ACE_MT(ACE_GUARD_RETURN(ACE_Recursive_Thread_Mutex, ace_mon, sm_mutex, L""));
+
if (ACE_OS::getcwd(buffer, MAXPATHLEN) == NULL)
{
MgStringCollection arguments;
@@ -550,6 +554,8 @@
{
MG_TRY()
+ ACE_MT(ACE_GUARD(ACE_Recursive_Thread_Mutex, ace_mon, sm_mutex));
+
if (!PathnameExists(pathname))
{
if (strict)
@@ -564,7 +570,6 @@
return;
}
- ACE_MT(ACE_GUARD(ACE_Recursive_Thread_Mutex, ace_mon, sm_mutex));
int errCode = ACE_OS::unlink(MG_WCHAR_TO_TCHAR(pathname));
if (0 != errCode)
@@ -711,6 +716,8 @@
__LINE__, __WFILE__, &arguments, L"", NULL);
}
+ ACE_MT(ACE_GUARD(ACE_Recursive_Thread_Mutex, ace_mon, sm_mutex));
+
if (overwrite)
{
DeleteFile(newPathname);
@@ -724,8 +731,6 @@
__LINE__, __WFILE__, &arguments, L"", NULL);
}
- ACE_MT(ACE_GUARD(ACE_Recursive_Thread_Mutex, ace_mon, sm_mutex));
-
#ifdef WIN32
int errCode = ::_wrename(oldPathname.c_str(), newPathname.c_str());
#else
@@ -992,9 +997,9 @@
{
bool bResult = true;
+#ifndef WIN32
ACE_MT(ACE_GUARD_RETURN(ACE_Recursive_Thread_Mutex, ace_mon, sm_mutex, false));
-#ifndef WIN32
FILE* file = ACE_OS::fopen(MG_WCHAR_TO_TCHAR(pathname), ACE_TEXT("r+"));
if (file)
{
Modified: trunk/MgDev/Common/MapGuideCommon/Resources/mapguide_en.res
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/Resources/mapguide_en.res 2007-02-02 17:55:19 UTC (rev 1089)
+++ trunk/MgDev/Common/MapGuideCommon/Resources/mapguide_en.res 2007-02-03 01:06:39 UTC (rev 1090)
@@ -210,6 +210,7 @@
MgInvalidPropertyType = The property type is invalid because it is not recognized.
MgInvalidPropertyTypeForCommand = The property type is invalid for the command because it was of a different type then expected.
MgInvalidResourceCannotBeRoot = The resource is invalid because it cannot be the root.
+MgInvalidScaleIndex = Scale index is out of range.
MgInvalidSecond = The second is invalid because it must be between 0 and 59.
MgInvalidServiceType = The service type is invalid because it is not recognized.
MgInvalidSessionsId = The session ID is invalid because the session separator character was not found.
@@ -225,6 +226,7 @@
MgInvalidWebWidgetType = The web widget type is invalid because it is not recognized.
MgInvalidXmlDateTime = The Xml date time is invalid because not all of the fields were found.
MgInvalidYear = The year is invalid because it must be between 1 and 9999.
+MgMapCacheCleared = The Tile Service map cache has been cleared. Please increase TiledMapCacheSize in serverconfig.ini.
MgMapLayerGroupNameNotFound = The map layer group name was not found.
MgMissingClassDef = No class definition specified.
MgMissingSchema = No schema specified.
@@ -244,6 +246,8 @@
MgStringEmpty = The string cannot be empty.
MgStringTooLong = The string is too long.
MgTagFieldNotFound = The tag contained no fields.
+MgUnableToLockTileFile = Unable to lock the tile file.
+MgUnableToOpenTileFile = Unable to open the tile file.
MgUnsupportedService = The site/resource services cannot be enabled/disabled.
MgUserAndGroupNotEmpty = Both the user and group are not empty.
MgUserAndRoleNotEmpty = Both the user and role are not empty.
Modified: trunk/MgDev/Common/MapGuideCommon/System/ConfigProperties.cpp
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/System/ConfigProperties.cpp 2007-02-02 17:55:19 UTC (rev 1089)
+++ trunk/MgDev/Common/MapGuideCommon/System/ConfigProperties.cpp 2007-02-03 01:06:39 UTC (rev 1090)
@@ -308,10 +308,16 @@
const STRING MgConfigProperties::TileServicePropertiesSection = L"TileServiceProperties";
const STRING MgConfigProperties::TileServicePropertyTileCachePath = L"TileCachePath";
const STRING MgConfigProperties::DefaultTileServicePropertyTileCachePath = L"Repositories/TileCache/";
+const STRING MgConfigProperties::TileServicePropertyCreationCutoffTime = L"CreationCutoffTime";
+const INT32 MgConfigProperties::DefaultTileServicePropertyCreationCutoffTime = 120;
+const STRING MgConfigProperties::TileServicePropertyLockFolderName = L"LockFolderName";
+const STRING MgConfigProperties::DefaultTileServicePropertyLockFolderName = L"Lock";
+const STRING MgConfigProperties::TileServicePropertyPollingInterval = L"PollingInterval";
+const INT32 MgConfigProperties::DefaultTileServicePropertyPollingInterval = 1;
+const STRING MgConfigProperties::TileServicePropertyRenderOnly = L"RenderOnly";
+const bool MgConfigProperties::DefaultTileServicePropertyRenderOnly = false;
const STRING MgConfigProperties::TileServicePropertyTiledMapCacheSize = L"TiledMapCacheSize";
const INT32 MgConfigProperties::DefaultTileServicePropertyTiledMapCacheSize = 10;
-const STRING MgConfigProperties::TileServicePropertyRenderOnly = L"RenderOnly";
-const bool MgConfigProperties::DefaultTileServicePropertyRenderOnly = false;
// ******************************************************************
// Access Log Properties
@@ -541,8 +547,11 @@
const MgConfigValidationInfo MgConfigProperties::sm_cviTileServiceProperties[] =
{
{ MgConfigProperties::TileServicePropertyTileCachePath , MgPropertyType::String , MG_CONFIG_MIN_PATH_LENGTH , MG_CONFIG_MAX_PATH_LENGTH , MG_CONFIG_PATH_RESERVED_CHARACTERS },
+ { MgConfigProperties::TileServicePropertyCreationCutoffTime , MgPropertyType::Int32 , 1 , 600 , L"" },
+ { MgConfigProperties::TileServicePropertyLockFolderName , MgPropertyType::String , MG_CONFIG_MIN_FOLDER_NAME_LENGTH , MG_CONFIG_MAX_FOLDER_NAME_LENGTH , MG_CONFIG_FOLDER_NAME_RESERVED_CHARACTERS },
+ { MgConfigProperties::TileServicePropertyPollingInterval , MgPropertyType::Int32 , 1 , 60 , L"" },
+ { MgConfigProperties::TileServicePropertyRenderOnly , MgPropertyType::Boolean , 0 , 1 , L"" },
{ MgConfigProperties::TileServicePropertyTiledMapCacheSize , MgPropertyType::Int32 , MG_CONFIG_MIN_CACHE_SIZE , MG_CONFIG_MAX_CACHE_SIZE , L"" },
- { MgConfigProperties::TileServicePropertyRenderOnly , MgPropertyType::Boolean , 0 , 1 , L"" },
{ L"" , 0 , 0.0 , 0.0 , L"" }
};
Modified: trunk/MgDev/Common/MapGuideCommon/System/ConfigProperties.h
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/System/ConfigProperties.h 2007-02-02 17:55:19 UTC (rev 1089)
+++ trunk/MgDev/Common/MapGuideCommon/System/ConfigProperties.h 2007-02-03 01:06:39 UTC (rev 1090)
@@ -396,12 +396,29 @@
static const STRING TileServicePropertyTileCachePath; /// value("TileCachePath")
static const STRING DefaultTileServicePropertyTileCachePath; /// value("Repositories/TileCache/")
+INTERNAL_API:
+
+ /// Sets the maximum amount of time (in seconds) to create a tile
+ static const STRING TileServicePropertyCreationCutoffTime; /// value("CreationCutoffTime")
+ static const INT32 DefaultTileServicePropertyCreationCutoffTime; /// value(120)
+
+ /// Sets the folder name for locks
+ static const STRING TileServicePropertyLockFolderName; /// value("LockFolderName")
+ static const STRING DefaultTileServicePropertyLockFolderName; /// value("Lock")
+
+ /// Sets the time duration (in seconds) between lock checks
+ static const STRING TileServicePropertyPollingInterval; /// value("PollingInterval")
+ static const INT32 DefaultTileServicePropertyPollingInterval; /// value(1)
+
+ /// Specifies whether the tile is only rendered
+ static const STRING TileServicePropertyRenderOnly; /// value("RenderOnly")
+ static const bool DefaultTileServicePropertyRenderOnly; /// value(true)
+
/// 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)
- static const STRING TileServicePropertyRenderOnly; /// value("RenderOnly")
- static const bool DefaultTileServicePropertyRenderOnly; /// value(true)
+EXTERNAL_API:
//////////////////////////////////////////////////////////////////
/// \brief
Modified: trunk/MgDev/Server/src/Common/Manager/FdoConnectionManager.cpp
===================================================================
--- trunk/MgDev/Server/src/Common/Manager/FdoConnectionManager.cpp 2007-02-02 17:55:19 UTC (rev 1089)
+++ trunk/MgDev/Server/src/Common/Manager/FdoConnectionManager.cpp 2007-02-03 01:06:39 UTC (rev 1090)
@@ -1234,7 +1234,8 @@
RetrieveFeatureSource(resId, featureSourceXmlContent);
MdfParser::FSDSAX2Parser parser;
- parser.ParseString(featureSourceXmlContent.c_str(), featureSourceXmlContent.length()*sizeof(char));
+ parser.ParseString(featureSourceXmlContent.c_str(),
+ (unsigned int)(featureSourceXmlContent.length()*sizeof(char)));
assert(parser.GetSucceeded());
Modified: trunk/MgDev/Server/src/Services/Rendering/ServerRenderingService.cpp
===================================================================
--- trunk/MgDev/Server/src/Services/Rendering/ServerRenderingService.cpp 2007-02-02 17:55:19 UTC (rev 1089)
+++ trunk/MgDev/Server/src/Services/Rendering/ServerRenderingService.cpp 2007-02-03 01:06:39 UTC (rev 1090)
@@ -140,7 +140,7 @@
MG_CATCH_AND_THROW(L"MgServerRenderingService.RenderTile")
- return SAFE_ADDREF(ret.p);
+ return ret.Detach();
}
@@ -208,7 +208,7 @@
MG_CATCH_AND_THROW(L"MgServerRenderingService.RenderTile")
- return SAFE_ADDREF(ret.p);
+ return ret.Detach();
}
@@ -272,7 +272,7 @@
MG_CATCH_AND_THROW(L"MgServerRenderingService.RenderDynamicOverlay")
- return SAFE_ADDREF(ret.p);
+ return ret.Detach();
}
@@ -301,7 +301,7 @@
MG_CATCH_AND_THROW(L"MgServerRenderingService.RenderMap")
- return SAFE_ADDREF(ret.p);
+ return ret.Detach();
}
@@ -394,7 +394,7 @@
MG_CATCH_AND_THROW(L"MgServerRenderingService.RenderMap")
- return SAFE_ADDREF(ret.p);
+ return ret.Detach();
}
@@ -448,7 +448,7 @@
MG_CATCH_AND_THROW(L"MgServerRenderingService.RenderMap")
- return SAFE_ADDREF(ret.p);
+ return ret.Detach();
}
@@ -488,7 +488,7 @@
MG_CATCH_AND_THROW(L"MgServerRenderingService.QueryFeatures")
- return SAFE_ADDREF(ret.p);
+ return ret.Detach();
}
@@ -516,7 +516,7 @@
MG_CATCH_AND_THROW(L"MgServerRenderingService.QueryFeatures")
- return SAFE_ADDREF(ret.p);
+ return ret.Detach();
}
@@ -638,7 +638,7 @@
dr->ProcessPolyline(&lb, ls);
//-------------------------------------------------------
*/
- MgByteReader* ret = NULL;
+ Ptr<MgByteReader> ret;
// get a byte representation of the image
RS_ByteData* data = dr->Save(format, saveWidth, saveHeight);
@@ -663,7 +663,7 @@
data->Dispose();
}
- return ret;
+ return ret.Detach();
}
@@ -743,7 +743,7 @@
MG_CATCH_AND_THROW(L"MgServerRenderingService.RenderMapLegend")
- return SAFE_ADDREF(ret.p);
+ return ret.Detach();
}
Modified: trunk/MgDev/Server/src/Services/Resource/ServerResourceService.cpp
===================================================================
--- trunk/MgDev/Server/src/Services/Resource/ServerResourceService.cpp 2007-02-02 17:55:19 UTC (rev 1089)
+++ trunk/MgDev/Server/src/Services/Resource/ServerResourceService.cpp 2007-02-03 01:06:39 UTC (rev 1090)
@@ -2035,7 +2035,7 @@
bool MgServerResourceService::HasPermission(MgResourceIdentifier* resource,
CREFSTRING permission)
{
- bool retVal = false;
+ bool permitted = false;
MG_RESOURCE_SERVICE_TRY()
@@ -2056,13 +2056,20 @@
MG_RESOURCE_SERVICE_BEGIN_OPERATION(false)
- retVal = resourceContentMan->CheckPermission(*resource, permission);
+ permitted = resourceContentMan->CheckPermission(*resource, permission);
MG_RESOURCE_SERVICE_END_OPERATION(sm_maxOpRetries)
- MG_RESOURCE_SERVICE_CATCH_AND_THROW(L"MgServerResourceService.HasPermission")
+ MG_RESOURCE_SERVICE_CATCH(L"MgServerResourceService.HasPermission")
- return retVal;
+ if (mgException != NULL
+ && !mgException->IsOfClass(MapGuide_Exception_MgPermissionDeniedException)
+ && !mgException->IsOfClass(MapGuide_Exception_MgUnauthorizedAccessException))
+ {
+ MG_RESOURCE_SERVICE_THROW()
+ }
+
+ return permitted;
}
///----------------------------------------------------------------------------
Modified: trunk/MgDev/Server/src/Services/Tile/ServerTileService.cpp
===================================================================
--- trunk/MgDev/Server/src/Services/Tile/ServerTileService.cpp 2007-02-02 17:55:19 UTC (rev 1089)
+++ trunk/MgDev/Server/src/Services/Tile/ServerTileService.cpp 2007-02-03 01:06:39 UTC (rev 1090)
@@ -22,25 +22,43 @@
ACE_Recursive_Thread_Mutex MgServerTileService::sm_mutex;
MgServerTileService::MapCache MgServerTileService::sm_mapCache;
+INT32 MgServerTileService::sm_creationCutoffTime = 120; // in seconds
+INT32 MgServerTileService::sm_pollingInterval = 1; // in seconds
+bool MgServerTileService::sm_renderOnly = false;
INT32 MgServerTileService::sm_mapCacheSize = -1;
-bool MgServerTileService::sm_renderOnly = false;
MgServerTileService::MgServerTileService() : MgTileService()
{
+ //TODO: It is possible to get a double write on sm_mapCacheSize here. We need
+ //to investigate general mutex use in this class.
if (sm_mapCacheSize < 0)
{
// initialize the tile cache size
MgConfiguration* pConf = MgConfiguration::GetInstance();
- pConf->GetIntValue(MgConfigProperties::TileServicePropertiesSection,
- MgConfigProperties::TileServicePropertyTiledMapCacheSize,
- sm_mapCacheSize,
- MgConfigProperties::DefaultTileServicePropertyTiledMapCacheSize);
+ pConf->GetIntValue(
+ MgConfigProperties::TileServicePropertiesSection,
+ MgConfigProperties::TileServicePropertyCreationCutoffTime,
+ sm_creationCutoffTime,
+ MgConfigProperties::DefaultTileServicePropertyCreationCutoffTime);
- pConf->GetBoolValue(MgConfigProperties::TileServicePropertiesSection,
+ pConf->GetIntValue(
+ MgConfigProperties::TileServicePropertiesSection,
+ MgConfigProperties::TileServicePropertyPollingInterval,
+ sm_pollingInterval,
+ MgConfigProperties::DefaultTileServicePropertyPollingInterval);
+
+ pConf->GetBoolValue(
+ MgConfigProperties::TileServicePropertiesSection,
MgConfigProperties::TileServicePropertyRenderOnly,
sm_renderOnly,
MgConfigProperties::DefaultTileServicePropertyRenderOnly);
+
+ pConf->GetIntValue(
+ MgConfigProperties::TileServicePropertiesSection,
+ MgConfigProperties::TileServicePropertyTiledMapCacheSize,
+ sm_mapCacheSize,
+ MgConfigProperties::DefaultTileServicePropertyTiledMapCacheSize);
}
m_tileCache = new MgTileCache();
@@ -51,6 +69,36 @@
{
}
+///////////////////////////////////////////////////////////////////////////////
+/// \brief
+/// Detect if the tile file has been locked by another thread or process.
+///
+bool MgServerTileService::DetectTileLockFile(CREFSTRING lockPathname)
+{
+ bool found = false;
+ struct _stat lockFileInfo;
+
+ // Check the lock file to see if another thread/process is writing the tile file.
+ while (MgFileUtil::GetFileStatus(lockPathname, lockFileInfo))
+ {
+ time_t currTime;
+ ACE_OS::time(&currTime);
+ INT32 diffTime = (INT32)(currTime - lockFileInfo.st_mtime);
+
+ if (diffTime < sm_creationCutoffTime)
+ {
+ ACE_OS::sleep(sm_pollingInterval);
+ }
+ else
+ {
+ found = true;
+ break;
+ }
+ }
+
+ return found;
+}
+
MgByteReader* MgServerTileService::GetTile(
MgResourceIdentifier* mapDefinition,
CREFSTRING baseMapLayerGroupName,
@@ -59,26 +107,39 @@
INT32 scaleIndex)
{
Ptr<MgByteReader> ret;
+ FILE* lockFile = NULL;
+ STRING tilePathname, lockPathname;
MG_TRY()
if (NULL == mapDefinition || baseMapLayerGroupName.empty())
{
- throw new MgNullArgumentException(
- L"MgServerTileService.GetTile", __LINE__, __WFILE__, NULL, L"", NULL);
+ throw new MgNullArgumentException(L"MgServerTileService.GetTile",
+ __LINE__, __WFILE__, NULL, L"", NULL);
}
+ if (scaleIndex < 0)
+ {
+ STRING buffer;
+ MgUtil::Int32ToString(scaleIndex, buffer);
+
+ MgStringCollection arguments;
+ arguments.Add(L"5");
+ arguments.Add(buffer);
+
+ throw new MgInvalidArgumentException(L"MgServerTileService.GetTile",
+ __LINE__, __WFILE__, &arguments, L"MgInvalidScaleIndex", NULL);
+ }
+
MgServiceManager* serviceMan = MgServiceManager::GetInstance();
assert(NULL != serviceMan);
// Get the service from service manager
Ptr<MgResourceService> resourceService = dynamic_cast<MgResourceService*>(
serviceMan->RequestService(MgServiceType::ResourceService));
- assert(resourceService != NULL);
+ assert(NULL != resourceService);
- bool bAllowed = resourceService->HasPermission(mapDefinition, MgResourcePermission::ReadOnly);
-
- if (!bAllowed)
+ if (!resourceService->HasPermission(mapDefinition, MgResourcePermission::ReadOnly))
{
MG_LOG_AUTHENTICATION_ENTRY(MgResources::PermissionDenied.c_str());
@@ -89,24 +150,72 @@
L"MgServerTileService.GetTile",
__LINE__, __WFILE__, &arguments, L"", NULL);
}
-
- ret = m_tileCache->Get(mapDefinition, scaleIndex, baseMapLayerGroupName, tileColumn, tileRow);
- if (!ret)
+ // 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))
{
+ // 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()
{
+ // Attemp to lock the tile file.
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))
+ {
+ MgStringCollection arguments;
+ arguments.Add(lockPathname);
+
+ throw new MgFileIoException(L"MgServerTileService.GetTile",
+ __LINE__, __WFILE__, &arguments, L"MgUnableToLockTileFile", NULL);
+ }
+
+ // try getting the tile from the cache
+ ret = m_tileCache->Get(tilePathname);
+
+ if (NULL != ret)
+ {
+ break;
+ }
+
+ // Create the lock file and close it right away.
+ m_tileCache->CreateFullPath(mapDefinition, scaleIndex, baseMapLayerGroupName);
+ 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"MgUnableToOpenTileFile", NULL);
+ }
+ else
+ {
+ ACE_OS::fclose(lockFile);
+ }
+
MapCache::const_iterator iter = sm_mapCache.find(mapString);
if (sm_mapCache.end() != iter)
{
@@ -138,11 +247,21 @@
double scale = map->GetFiniteDisplayScaleAt(scaleIndex);
map->SetViewScale(scale);
- ret = GetTile(map, baseMapLayerGroupName, tileColumn, tileRow);
+
+ // Render the tile and cache it.
+ ret = GetTile(tilePathname, map, scaleIndex, baseMapLayerGroupName, tileColumn, tileRow);
+ break;
}
- MG_CATCH_AND_THROW(L"MgServerTileService.GetTile")
+ MG_CATCH(L"MgServerTileService.GetTile")
+ if (NULL != lockFile)
+ {
+ MgFileUtil::DeleteFile(lockPathname, false);
+ }
+
+ MG_THROW()
+
return ret.Detach();
}
@@ -153,11 +272,16 @@
INT32 tileRow)
{
Ptr<MgByteReader> ret;
+ FILE* lockFile = NULL;
+ STRING tilePathname, lockPathname;
MG_TRY()
if (NULL == map || baseMapLayerGroupName.empty())
- throw new MgNullArgumentException(L"MgServerTileService.GetTile", __LINE__, __WFILE__, NULL, L"", NULL);
+ {
+ throw new MgNullArgumentException(L"MgServerTileService.GetTile",
+ __LINE__, __WFILE__, NULL, L"", NULL);
+ }
// find the finite display scale closest to the requested map scale
double scale = map->GetViewScale();
@@ -165,44 +289,119 @@
// if we don't find a nearest scale then something is wrong with the map
if (scaleIndex < 0)
- throw new MgInvalidMapDefinitionException(L"MgServerTileService.GetTile", __LINE__, __WFILE__, NULL, L"", NULL);
+ {
+ throw new MgInvalidMapDefinitionException(L"MgServerTileService.GetTile",
+ __LINE__, __WFILE__, NULL, L"", NULL);
+ }
+ // Detect the lock file to see if another thread is creating the tile file.
+ m_tileCache->GeneratePathnames(map, scaleIndex, baseMapLayerGroupName,
+ tileColumn, tileRow, tilePathname, lockPathname, false);
+
+ // If there is a dangling lock file, then attempt to remove it.
+ if (DetectTileLockFile(lockPathname))
+ {
+ // 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(map, scaleIndex, baseMapLayerGroupName, tileColumn, tileRow);
+ ret = m_tileCache->Get(tilePathname);
// if the reader is NULL then the tile wasn't in the cache and we
// need to generate it
- if (ret == NULL)
+ while (NULL == ret)
{
- // get a rendering service instance
- MgServiceManager* serviceMan = MgServiceManager::GetInstance();
- assert(NULL != serviceMan);
- Ptr<MgRenderingService> svcRendering = dynamic_cast<MgRenderingService*>(
- serviceMan->RequestService(MgServiceType::RenderingService));
-
- if (svcRendering != NULL)
{
- // generate the tile
- ret = svcRendering->RenderTile(map, baseMapLayerGroupName, tileColumn, tileRow);
+ // Attemp to lock the tile file.
+ ACE_MT(ACE_GUARD_RETURN(ACE_Recursive_Thread_Mutex, ace_mon, sm_mutex, NULL));
- // cache the tile
- if (!sm_renderOnly)
+ // Bail out if the tile file has been locked for so long.
+ if (DetectTileLockFile(lockPathname))
{
- SetTile(ret, map, scaleIndex, baseMapLayerGroupName, tileColumn, tileRow);
+ MgStringCollection arguments;
+ arguments.Add(lockPathname);
- // rewind the reader since setting the tile advances it to the end
- if (ret)
- ret->Rewind();
+ throw new MgFileIoException(L"MgServerTileService.GetTile",
+ __LINE__, __WFILE__, &arguments, L"MgUnableToLockTileFile", NULL);
}
+
+ // try getting the tile from the cache
+ ret = m_tileCache->Get(tilePathname);
+
+ if (NULL != ret)
+ {
+ break;
+ }
+
+ // Create the lock file and close it right away.
+ m_tileCache->CreateFullPath(map, scaleIndex, baseMapLayerGroupName);
+ 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"MgUnableToOpenTileFile", NULL);
+ }
+ else
+ {
+ ACE_OS::fclose(lockFile);
+ }
}
+
+ // Render the tile and cache it.
+ ret = GetTile(tilePathname, map, scaleIndex, baseMapLayerGroupName, tileColumn, tileRow);
+ break;
}
- MG_CATCH_AND_THROW(L"MgServerTileService.GetTile")
+ MG_CATCH(L"MgServerTileService.GetTile")
- return SAFE_ADDREF(ret.p);
+ if (NULL != lockFile)
+ {
+ MgFileUtil::DeleteFile(lockPathname, false);
+ }
+
+ MG_THROW()
+
+ return ret.Detach();
}
+MgByteReader* MgServerTileService::GetTile(CREFSTRING tilePathname, MgMap* map, INT32 scaleIndex,
+ CREFSTRING baseMapLayerGroupName, INT32 tileColumn, INT32 tileRow)
+{
+ Ptr<MgByteReader> img;
+ // get a rendering service instance
+ MgServiceManager* serviceMan = MgServiceManager::GetInstance();
+ assert(NULL != serviceMan);
+ Ptr<MgRenderingService> svcRendering = dynamic_cast<MgRenderingService*>(
+ serviceMan->RequestService(MgServiceType::RenderingService));
+ assert(NULL != svcRendering);
+
+ if (svcRendering != NULL)
+ {
+ // generate the tile
+ img = svcRendering->RenderTile(map, baseMapLayerGroupName, tileColumn, tileRow);
+
+ // cache the tile
+ if (!sm_renderOnly)
+ {
+ m_tileCache->Set(img, tilePathname);
+
+ // rewind the reader since setting the tile advances it to the end
+ if (img)
+ {
+ img->Rewind();
+ }
+ }
+ }
+
+ return img.Detach();
+}
+
void MgServerTileService::SetTile(MgByteReader* img,
MgMap* map,
INT32 scaleIndex,
@@ -210,10 +409,16 @@
INT32 tileColumn,
INT32 tileRow)
{
+ FILE* lockFile = NULL;
+ STRING tilePathname, lockPathname;
+
MG_TRY()
if (NULL == img || NULL == map || baseMapLayerGroupName.empty())
- throw new MgNullArgumentException(L"MgServerTileService.SetTile", __LINE__, __WFILE__, NULL, L"", NULL);
+ {
+ throw new MgNullArgumentException(L"MgServerTileService.SetTile",
+ __LINE__, __WFILE__, NULL, L"", NULL);
+ }
if (scaleIndex < 0)
{
@@ -228,10 +433,48 @@
__LINE__, __WFILE__, &arguments, L"MgInvalidScaleIndex", NULL);
}
+ // Generate tile and lock pathnames.
+ m_tileCache->GeneratePathnames(map, scaleIndex, baseMapLayerGroupName,
+ tileColumn, tileRow, tilePathname, lockPathname, true);
+
+ {
+ // Attemp to lock the tile file.
+ ACE_MT(ACE_GUARD(ACE_Recursive_Thread_Mutex, ace_mon, sm_mutex));
+
+ if (DetectTileLockFile(lockPathname))
+ {
+ // Attemp to remove a dangling lock file.
+ MgFileUtil::DeleteFile(lockPathname, true);
+ }
+
+ // Create the lock file and close it right away.
+ 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.SetTile",
+ __LINE__, __WFILE__, &arguments, L"MgUnableToOpenTileFile", NULL);
+ }
+ else
+ {
+ ACE_OS::fclose(lockFile);
+ }
+ }
+
// cache the tile
- m_tileCache->Set(img, map, scaleIndex, baseMapLayerGroupName, tileColumn, tileRow);
+ m_tileCache->Set(img, tilePathname);
- MG_CATCH_AND_THROW(L"MgServerTileService.SetTile")
+ MG_CATCH(L"MgServerTileService.SetTile")
+
+ if (NULL != lockFile)
+ {
+ MgFileUtil::DeleteFile(lockPathname, false);
+ }
+
+ MG_THROW()
}
Modified: trunk/MgDev/Server/src/Services/Tile/ServerTileService.h
===================================================================
--- trunk/MgDev/Server/src/Services/Tile/ServerTileService.h 2007-02-02 17:55:19 UTC (rev 1089)
+++ trunk/MgDev/Server/src/Services/Tile/ServerTileService.h 2007-02-03 01:06:39 UTC (rev 1090)
@@ -56,17 +56,24 @@
private:
+ bool DetectTileLockFile(CREFSTRING lockPathname);
+
+ MgByteReader* GetTile(CREFSTRING tilePathname, MgMap* map, INT32 scaleIndex,
+ CREFSTRING baseMapLayerGroupName, INT32 tileColumn, INT32 tileRow);
+
void ClearMapCache(CREFSTRING mapName);
// member data
Ptr<MgTileCache> m_tileCache;
typedef std::map<STRING, MgMemoryStreamHelper*> MapCache;
+
+ static ACE_Recursive_Thread_Mutex sm_mutex;
static MapCache sm_mapCache;
- static ACE_Recursive_Thread_Mutex sm_mutex;
+ static INT32 sm_creationCutoffTime;
+ static INT32 sm_pollingInterval;
+ static bool sm_renderOnly;
static INT32 sm_mapCacheSize;
- static bool sm_renderOnly;
-
};
#endif
Modified: trunk/MgDev/Server/src/Services/Tile/TileCache.cpp
===================================================================
--- trunk/MgDev/Server/src/Services/Tile/TileCache.cpp 2007-02-02 17:55:19 UTC (rev 1089)
+++ trunk/MgDev/Server/src/Services/Tile/TileCache.cpp 2007-02-03 01:06:39 UTC (rev 1090)
@@ -18,124 +18,133 @@
#include "MapGuideCommon.h"
#include "TileCache.h"
-#define PATH_LEN 512
+STRING MgTileCache::sm_lockFolderName = L"Lock"; // name of file folder for locks
+STRING MgTileCache::sm_path = L"";
-STRING MgTileCache::m_path = L"";
-
// default constructor
MgTileCache::MgTileCache()
{
- //TODO: It is possible to get a double write on m_path here. We need
+ //TODO: It is possible to get a double write on sm_path here. We need
//to investigate general mutex use in this class.
- if (m_path.empty())
+ if (sm_path.empty())
{
// initialize the tile cache path
MgConfiguration* pConf = MgConfiguration::GetInstance();
- pConf->GetStringValue(MgConfigProperties::TileServicePropertiesSection,
- MgConfigProperties::TileServicePropertyTileCachePath,
- m_path,
- MgConfigProperties::DefaultTileServicePropertyTileCachePath);
+ pConf->GetStringValue(
+ MgConfigProperties::TileServicePropertiesSection,
+ MgConfigProperties::TileServicePropertyLockFolderName,
+ sm_lockFolderName,
+ MgConfigProperties::DefaultTileServicePropertyLockFolderName);
+ pConf->GetStringValue(
+ MgConfigProperties::TileServicePropertiesSection,
+ MgConfigProperties::TileServicePropertyTileCachePath,
+ sm_path,
+ MgConfigProperties::DefaultTileServicePropertyTileCachePath);
+
// generate directory location for tile cache
- MgFileUtil::AppendSlashToEndOfPath(m_path);
+ MgFileUtil::AppendSlashToEndOfPath(sm_path);
// create directory if it is not already there
- if (!MgFileUtil::PathnameExists(m_path))
- MgFileUtil::CreateDirectory(m_path, false);
+ if (!MgFileUtil::PathnameExists(sm_path))
+ MgFileUtil::CreateDirectory(sm_path, false);
}
}
-
-// returns any cached tile for the given map / scale index / group / i / j
-MgByteReader* MgTileCache::Get(MgMap* map, int scaleIndex, CREFSTRING group, int i, int j)
+///////////////////////////////////////////////////////////////////////////////
+/// \brief
+/// Generate tile and lock pathnames.
+///
+void MgTileCache::GeneratePathnames(MgResourceIdentifier* mapDef, int scaleIndex,
+ CREFSTRING group, int tileColumn, int tileRow,
+ STRING& tilePathname, STRING& lockPathname, bool createFullPath)
{
- // acquire a read lock - this blocks if a writer holds the lock
- ACE_Read_Guard<ACE_RW_Thread_Mutex> ace_mon(m_mutexRW);
+ wchar_t fileName[MAXPATHLEN] = { 0 };
+ ::swprintf(fileName, MAXPATHLEN, L"/%d_%d.", tileRow, tileColumn);
- Ptr<MgByteReader> ret;
+ lockPathname = GetBasePath(mapDef);
+ tilePathname;
- if (map != NULL)
+ if (createFullPath)
{
- STRING tilePath = MgTileCache::GetFullPath(map, scaleIndex, group);
+ tilePathname = CreateFullPath(lockPathname, scaleIndex, group);
+ }
+ else
+ {
+ tilePathname = GetFullPath(lockPathname, scaleIndex, group);
+ }
- // generate full path to tile file using <row,column> format
- // TODO: handle case where path is > PATH_LEN
- wchar_t tmp[PATH_LEN] = { 0 };
- swprintf(tmp, PATH_LEN, L"%ls/%d_%d.png", tilePath.c_str(), j, i);
+ // Generate the tile pathname using format "%ls/%d_%d.png":
+ // <tilePathname> = <fullPath>/<row>_<column>.png
+ tilePathname += fileName;
+ tilePathname += L"png";
- // check if the tile exists
- if (MgFileUtil::PathnameExists(tmp))
- {
- Ptr<MgByteSource> bs = new MgByteSource(tmp, false);
- bs->SetMimeType(MgMimeType::Png);
- ret = bs->GetReader();
- }
- }
+ // Generate the lock pathname using format "%ls/%d_%d.lck":
+ // <lockPathname> = <basePath>/<row>_<column>.lck
+ lockPathname += L"/";
+ lockPathname += sm_lockFolderName;
+ lockPathname += fileName;
+ lockPathname += L"lck";
+}
- return SAFE_ADDREF(ret.p);
+void MgTileCache::GeneratePathnames(MgMap* map, int scaleIndex,
+ CREFSTRING group, int tileColumn, int tileRow,
+ STRING& tilePathname, STRING& lockPathname, bool createFullPath)
+{
+ assert(NULL != map);
+ Ptr<MgResourceIdentifier> mapDef = map->GetMapDefinition();
+
+ GeneratePathnames(mapDef, scaleIndex, group, tileColumn, tileRow,
+ tilePathname, lockPathname, createFullPath);
}
-MgByteReader* MgTileCache::Get(MgResourceIdentifier* mapDef, int scaleIndex, CREFSTRING group, int i, int j)
+// returns any cached tile for the given pathname
+MgByteReader* MgTileCache::Get(CREFSTRING tilePathname)
{
// acquire a read lock - this blocks if a writer holds the lock
- ACE_Read_Guard<ACE_RW_Thread_Mutex> ace_mon(m_mutexRW);
+ ACE_Read_Guard<ACE_RW_Thread_Mutex> ace_mon(m_rwMutex);
Ptr<MgByteReader> ret;
- if (mapDef != NULL)
+ MG_TRY()
+
+ if (MgFileUtil::PathnameExists(tilePathname))
{
- STRING tilePath = MgTileCache::GetFullPath(mapDef, scaleIndex, group);
+ Ptr<MgByteSource> byteSource = new MgByteSource(tilePathname, false);
- // generate full path to tile file using <row,column> format
- // TODO: handle case where path is > PATH_LEN
- wchar_t tmp[PATH_LEN] = { 0 };
- swprintf(tmp, PATH_LEN, L"%ls/%d_%d.png", tilePath.c_str(), j, i);
+ byteSource->SetMimeType(MgMimeType::Png);
+ ret = byteSource->GetReader();
+ }
- MG_TRY()
+ MG_CATCH_AND_RELEASE()
- Ptr<MgByteSource> bs = new MgByteSource(tmp, false);
- bs->SetMimeType(MgMimeType::Png);
- ret = bs->GetReader();
-
- MG_CATCH_AND_RELEASE()
- }
-
- return SAFE_ADDREF(ret.p);
+ return ret.Detach();
}
-
-// caches a tile for the given map / scale index / group / i / j
-void MgTileCache::Set(MgByteReader* img, MgMap* map, int scaleIndex, CREFSTRING group, int i, int j)
+// caches a tile for the given pathname
+void MgTileCache::Set(MgByteReader* img, CREFSTRING tilePathname)
{
// acquire a write lock - this blocks if any readers or a writer hold the lock
- ACE_Write_Guard<ACE_RW_Thread_Mutex> ace_mon(m_mutexRW);
+ ACE_Write_Guard<ACE_RW_Thread_Mutex> ace_mon(m_rwMutex);
- if (map != NULL && img != NULL)
+ if (img != NULL)
{
- // ensure the necessary directories are created
- STRING tilePath = MgTileCache::CreateFullPath(map, scaleIndex, group);
+ Ptr<MgByteSink> byteSink = new MgByteSink(img);
- // generate full path to tile file using <row,column> format
- // TODO: handle case where path is > PATH_LEN
- wchar_t tmp[PATH_LEN] = { 0 };
- swprintf(tmp, PATH_LEN, L"%ls/%d_%d.png", tilePath.c_str(), j, i);
-
- // save the file
- (MgByteSink(img)).ToFile(tmp);
+ byteSink->ToFile(tilePathname);
}
}
-
// clears the tile cache for the given map
void MgTileCache::Clear(MgMap* map)
{
// acquire a write lock - this blocks if any readers or a writer hold the lock
- ACE_Write_Guard<ACE_RW_Thread_Mutex> ace_mon(m_mutexRW);
+ ACE_Write_Guard<ACE_RW_Thread_Mutex> ace_mon(m_rwMutex);
if (map != NULL)
{
- STRING basePath = MgTileCache::GetBasePath(map);
+ STRING basePath = GetBasePath(map);
// delete main map directory
if (!basePath.empty())
@@ -143,17 +152,16 @@
}
}
-
// clears the tile cache for the given map
-void MgTileCache::Clear(MgResourceIdentifier* resId)
+void MgTileCache::Clear(MgResourceIdentifier* mapDef)
{
// acquire a write lock - this blocks if any readers or a writer hold the lock
- ACE_Write_Guard<ACE_RW_Thread_Mutex> ace_mon(m_mutexRW);
+ ACE_Write_Guard<ACE_RW_Thread_Mutex> ace_mon(m_rwMutex);
// the resource must be a map definition
- if (resId != NULL && resId->GetResourceType() == MgResourceType::MapDefinition)
+ if (mapDef != NULL && mapDef->GetResourceType() == MgResourceType::MapDefinition)
{
- STRING basePath = MgTileCache::GetBasePath(resId);
+ STRING basePath = GetBasePath(mapDef);
// delete main map directory
if (!basePath.empty())
@@ -161,41 +169,35 @@
}
}
-
-// gets the base path to use with the tile cache for the given map
-STRING MgTileCache::GetBasePath(MgMap* map)
-{
- Ptr<MgResourceIdentifier> resId = map->GetMapDefinition();
- return GetBasePath(resId);
-}
-
-
// gets the base path to use with the tile cache for the given map definition resource
-STRING MgTileCache::GetBasePath(MgResourceIdentifier* resId)
+STRING MgTileCache::GetBasePath(MgResourceIdentifier* mapDef)
{
+ assert(mapDef != NULL);
+ assert(mapDef->GetResourceType() == MgResourceType::MapDefinition);
STRING mapPath;
- // safety check
- assert(resId != NULL);
- if (resId == NULL)
- return mapPath;
-
- // we should only be dealing with map definitions
- assert(resId->GetResourceType() == MgResourceType::MapDefinition);
-
- if (resId->GetRepositoryType() == MgRepositoryType::Library)
+ if (mapDef->GetRepositoryType() == MgRepositoryType::Library)
{
// for maps in the library repository the path+name is unique
- mapPath = resId->GetPath();
+ mapPath = mapDef->GetPath();
mapPath += L"_";
- mapPath += resId->GetName();
+ mapPath += mapDef->GetName();
}
- else if (resId->GetRepositoryType() == MgRepositoryType::Session)
+ else if (mapDef->GetRepositoryType() == MgRepositoryType::Session)
{
- // for maps in the session repository we use the session name + map name
- mapPath = resId->GetRepositoryName();
+ // for maps in the session repository we use the session + path + map name
+ mapPath = mapDef->GetRepositoryName();
mapPath += L"_";
- mapPath += resId->GetName();
+
+ STRING resourcePath = mapDef->GetPath();
+
+ if (!resourcePath.empty())
+ {
+ mapPath += resourcePath;
+ mapPath += L"_";
+ }
+
+ mapPath += mapDef->GetName();
}
else
{
@@ -208,56 +210,90 @@
mapPath = MgUtil::ReplaceString(mapPath, L"/", L"_");
mapPath = MgUtil::ReplaceString(mapPath, L":", L"_");
- // build the base path
- wchar_t tmp[PATH_LEN] = { 0 };
- swprintf(tmp, PATH_LEN, L"%ls%ls", m_path.c_str(), mapPath.c_str());
+ // Build the base path using format "%ls%ls":
+ // <basePath> = <tileCachePath><mapPath>
+ STRING basePath = sm_path;
+ basePath += mapPath;
- return STRING(tmp);
+ return basePath;
}
+// gets the base path to use with the tile cache for the given map
+STRING MgTileCache::GetBasePath(MgMap* map)
+{
+ assert(NULL != map);
+ Ptr<MgResourceIdentifier> mapDef = map->GetMapDefinition();
+ return GetBasePath(mapDef);
+}
-// gets the full path to use with the tile cache for the given map / scale index / group
-STRING MgTileCache::GetFullPath(MgMap* map, int scaleIndex, CREFSTRING group)
+// gets the full path to use with the tile cache for the given base path / scale index / group
+STRING MgTileCache::GetFullPath(CREFSTRING basePath, int scaleIndex, CREFSTRING group)
{
- STRING basePath = MgTileCache::GetBasePath(map);
+ // Build full path using format "%ls/%d/%ls":
+ // <fullPath> = <basePath>/<scaleIndex>/<group>
+ assert(!basePath.empty());
+ STRING fullPath = basePath;
+ STRING buffer;
+ MgUtil::Int32ToString(scaleIndex, buffer);
- wchar_t tmp[PATH_LEN] = { 0 };
- swprintf(tmp, PATH_LEN, L"%ls/%d/%ls", basePath.c_str(), scaleIndex, group.c_str());
+ fullPath += L"/";
+ fullPath += buffer;
+ fullPath += L"/";
+ fullPath += group;
- return STRING(tmp);
+ return fullPath;
}
-// gets the full path to use with the tile cache for the given map / scale index / group
+// gets the full path to use with the tile cache for the given map definition / scale index / group
STRING MgTileCache::GetFullPath(MgResourceIdentifier* mapDef, int scaleIndex, CREFSTRING group)
{
- STRING basePath = MgTileCache::GetBasePath(mapDef);
+ return GetFullPath(GetBasePath(mapDef), scaleIndex, group);
+}
- wchar_t tmp[PATH_LEN] = { 0 };
- swprintf(tmp, PATH_LEN, L"%ls/%d/%ls", basePath.c_str(), scaleIndex, group.c_str());
-
- return STRING(tmp);
+// gets the full path to use with the tile cache for the given map / scale index / group
+STRING MgTileCache::GetFullPath(MgMap* map, int scaleIndex, CREFSTRING group)
+{
+ assert(NULL != map);
+ Ptr<MgResourceIdentifier> mapDef = map->GetMapDefinition();
+ return GetFullPath(mapDef, scaleIndex, group);
}
-
-STRING MgTileCache::CreateFullPath(MgMap* map, int scaleIndex, CREFSTRING group)
+STRING MgTileCache::CreateFullPath(CREFSTRING basePath, int scaleIndex, CREFSTRING group)
{
- wchar_t tmp[PATH_LEN] = { 0 };
+ assert(!basePath.empty());
+ STRING fullPath = basePath;
- if (map != NULL)
- {
- STRING basePath = MgTileCache::GetBasePath(map);
+ // Create base directory if it does not exist.
+ MgFileUtil::CreateDirectory(fullPath, false);
+ fullPath += L"/";
- // check main map directory
- MgFileUtil::CreateDirectory(basePath, false);
+ // Create lock directory if it does not exist.
+ STRING lockPath = fullPath;
- // check scale directory
- swprintf(tmp, PATH_LEN, L"%ls/%d", basePath.c_str(), scaleIndex);
- MgFileUtil::CreateDirectory(tmp, false);
+ lockPath += sm_lockFolderName;
+ MgFileUtil::CreateDirectory(lockPath, false);
- // check group directory
- swprintf(tmp, PATH_LEN, L"%ls/%d/%ls", basePath.c_str(), scaleIndex, group.c_str());
- MgFileUtil::CreateDirectory(tmp, false);
- }
+ // Create scale directory if it does not exist.
+ STRING buffer;
+ MgUtil::Int32ToString(scaleIndex, buffer);
- return STRING(tmp);
+ fullPath += buffer;
+ MgFileUtil::CreateDirectory(fullPath, false);
+
+ // Create group directory if it does not exist.
+ fullPath += L"/";
+ fullPath += group;
+ MgFileUtil::CreateDirectory(fullPath, false);
+
+ return fullPath;
}
+
+STRING MgTileCache::CreateFullPath(MgResourceIdentifier* mapDef, int scaleIndex, CREFSTRING group)
+{
+ return CreateFullPath(GetBasePath(mapDef), scaleIndex, group);
+}
+
+STRING MgTileCache::CreateFullPath(MgMap* map, int scaleIndex, CREFSTRING group)
+{
+ return CreateFullPath(GetBasePath(map), scaleIndex, group);
+}
Modified: trunk/MgDev/Server/src/Services/Tile/TileCache.h
===================================================================
--- trunk/MgDev/Server/src/Services/Tile/TileCache.h 2007-02-02 17:55:19 UTC (rev 1089)
+++ trunk/MgDev/Server/src/Services/Tile/TileCache.h 2007-02-03 01:06:39 UTC (rev 1090)
@@ -26,11 +26,21 @@
public:
MgTileCache();
- MgByteReader* Get(MgMap* map, int scaleIndex, CREFSTRING group, int i, int j);
- MgByteReader* Get(MgResourceIdentifier* mapDef, int scaleIndex, CREFSTRING group, int i, int j);
- void Set(MgByteReader* img, MgMap* map, int scaleIndex, CREFSTRING group, int i, int j);
+ void GeneratePathnames(MgResourceIdentifier* mapDef, int scaleIndex,
+ CREFSTRING group, int tileColumn, int tileRow,
+ STRING& tilePathname, STRING& lockPathname, bool createFullPath);
+ void GeneratePathnames(MgMap* map, int scaleIndex,
+ CREFSTRING group, int tileColumn, int tileRow,
+ STRING& tilePathname, STRING& lockPathname, bool createFullPath);
+
+ STRING CreateFullPath(MgResourceIdentifier* mapDef, int scaleIndex, CREFSTRING group);
+ STRING CreateFullPath(MgMap* map, int scaleIndex, CREFSTRING group);
+
+ MgByteReader* Get(CREFSTRING tilePathname);
+ void Set(MgByteReader* img, CREFSTRING tilePathname);
+
void Clear(MgMap* map);
- void Clear(MgResourceIdentifier* resId);
+ void Clear(MgResourceIdentifier* mapDef);
protected:
virtual void Dispose()
@@ -39,17 +49,22 @@
}
private:
+ // Unimplemented Constructors/Methods
+ MgTileCache(const MgTileCache&);
+ MgTileCache& operator=(const MgTileCache&);
+
+ STRING GetBasePath(MgResourceIdentifier* mapDef);
STRING GetBasePath(MgMap* map);
- STRING GetBasePath(MgResourceIdentifier* resId);
+
+ STRING GetFullPath(CREFSTRING basePath, int scaleIndex, CREFSTRING group);
+ STRING GetFullPath(MgResourceIdentifier* mapDef, int scaleIndex, CREFSTRING group);
STRING GetFullPath(MgMap* map, int scaleIndex, CREFSTRING group);
- STRING GetFullPath(MgResourceIdentifier* mapDef, int scaleIndex, CREFSTRING group);
- STRING CreateFullPath(MgMap* map, int scaleIndex, CREFSTRING group);
- // TODO: Investigate this mutex. It may fail if
- // we have more than one tile service and could reduce
- // multi-threaded performance. File locks would be better.
- ACE_RW_Thread_Mutex m_mutexRW;
- static STRING m_path;
+ STRING CreateFullPath(CREFSTRING basePath, int scaleIndex, CREFSTRING group);
+
+ ACE_RW_Thread_Mutex m_rwMutex;
+ static STRING sm_path;
+ static STRING sm_lockFolderName;
};
#endif
Modified: trunk/MgDev/Server/src/UnitTesting/TestTileService.cpp
===================================================================
--- trunk/MgDev/Server/src/UnitTesting/TestTileService.cpp 2007-02-02 17:55:19 UTC (rev 1089)
+++ trunk/MgDev/Server/src/UnitTesting/TestTileService.cpp 2007-02-03 01:06:39 UTC (rev 1090)
@@ -280,6 +280,7 @@
{
STRING message = e->GetDetails(TEST_LOCALE);
SAFE_RELEASE(e);
+ CPPUNIT_FAIL(MG_WCHAR_TO_CHAR(message.c_str()));
}
catch (...)
{
@@ -702,14 +703,7 @@
void TestTileService::TestCase_GetSetTile()
{
// specify the number of threads to use
-#ifdef _WIN32
- // TODO: Investigate threading problem on Windows 2003 (dual core CPU).
- // There may be some issue with ByteSourceFileImpl::LoadFile (i.e. Is errno thread safe?).
- const INT32 numThreads = 1;
-#else
const INT32 numThreads = MG_TEST_THREADS;
-#endif
-
ThreadData threadData[numThreads];
// define the range of tiles to get and set
More information about the mapguide-commits
mailing list