[mapguide-trac] #1119: MgSpatialContextReader shouldn't clear
internal data when close
MapGuide Open Source
trac_mapguide at osgeo.org
Sun Oct 18 23:13:52 EDT 2009
#1119: MgSpatialContextReader shouldn't clear internal data when close
--------------------------+-------------------------------------------------
Reporter: christinebao | Owner: Christine Bao
Type: defect | Status: new
Priority: medium | Milestone: 2.2
Component: General | Version: 2.0.2
Severity: trivial | Resolution:
Keywords: | External_id: 1262439
--------------------------+-------------------------------------------------
Comment (by christinebao):
Tech diagnosis:
== The relationship of the classes ==
[[BR]]
[[Image(ClassDiagram.JPG)]]
== Brief code snippet to demo how they work ==
[[BR]]
1. MgSpatialContextReader*
MgServerFeatureService::GetSpatialContexts( MgResourceIdentifier*
resource, bool bActiveOnly) calles MgServerGetSpatialContexts to get the
reader actually. And MgServerGetSpatialContexts has a cache
(m_featureServiceCache) inside. This cache is based on resource id and its
cache entry. If the cache contains the resource id, get its spatial
context reader and return directly; if not a FDO command is executed to
get the spatial context reader, and added to the cache. So later when
requiring the spatial context reader again, the cached one will be
returned directly.[[BR]]
{{{
MgSpatialContextReader*
MgServerGetSpatialContexts::GetSpatialContexts(MgResourceIdentifier*
resId)
{
Ptr<MgSpatialContextReader> mgSpatialContextReader;
MG_FEATURE_SERVICE_TRY()
mgSpatialContextReader =
m_featureServiceCache->GetSpatialContextReader(resId);
if (NULL == mgSpatialContextReader.p)
{
// Connect to provider
Ptr<MgServerFeatureConnection> msfc = new
MgServerFeatureConnection(resId);
// Connection must be open to retrieve a list of available
contexts.
if ((NULL != msfc.p) && ( msfc->IsConnectionOpen() ))
{
// The reference to the FDO connection from the
MgServerFeatureConnection object must be cleaned up before the parent
object
// otherwise it leaves the FDO connection marked as still in
use.
FdoPtr<FdoIConnection> fdoConn = msfc->GetConnection();
m_providerName = msfc->GetProviderName();
Ptr<MgSpatialContextCacheItem> cacheItem =
MgCacheManager::GetInstance()->GetSpatialContextCacheItem(resId);
MgSpatialContextInfo* spatialContextInfo = cacheItem->Get();
// Check whether command is supported by provider
if
(!msfc->SupportsCommand((INT32)FdoCommandType_GetSpatialContexts))
{
// TODO: specify which argument and message, once we have
the mechanism
STRING message =
MgServerFeatureUtil::GetMessage(L"MgCommandNotSupported");
throw new
MgInvalidOperationException(L"MgServerGetSpatialContexts.GetSpatialContexts",
__LINE__, __WFILE__, NULL, L"", NULL);
}
FdoPtr<FdoIGetSpatialContexts> fdoCommand =
(FdoIGetSpatialContexts*)fdoConn->CreateCommand(FdoCommandType_GetSpatialContexts);
CHECKNULL((FdoIGetSpatialContexts*)fdoCommand,
L"MgServerGetSpatialContexts.GetSpatialContexts");
// Execute the command
FdoPtr<FdoISpatialContextReader> spatialReader =
fdoCommand->Execute();
CHECKNULL((FdoISpatialContextReader*)spatialReader,
L"MgServerGetSpatialContexts.GetSpatialContexts");
mgSpatialContextReader = new MgSpatialContextReader();
while (spatialReader->ReadNext())
{
// Set providername for which spatial reader is executed
mgSpatialContextReader->SetProviderName(m_providerName);
Ptr<MgSpatialContextData> spatialData =
GetSpatialContextData(spatialReader, spatialContextInfo);
CHECKNULL((MgSpatialContextData*)spatialData,
L"MgServerGetSpatialContexts.GetSpatialContexts");
// Add spatial data to the spatialcontext reader
mgSpatialContextReader->AddSpatialData(spatialData);
}
m_featureServiceCache->SetSpatialContextReader(resId,
mgSpatialContextReader.p);
}
else
{
throw new
MgConnectionFailedException(L"MgServerGetSpatialContexts.GetSpatialContexts()",
__LINE__, __WFILE__, NULL, L"", NULL);
}
}
else
{
MgCacheManager::GetInstance()->CheckPermission(resId,
MgResourcePermission::ReadOnly);
}
MG_FEATURE_SERVICE_CHECK_CONNECTION_CATCH_AND_THROW(resId,
L"MgServerGetSpatialContexts.GetSpatialContexts")
return mgSpatialContextReader.Detach();
}
}}}
2. MgFeatureServiceCacheEntry is a cache entry which contains
MgSpatialContextReader, and its Get/SetSpatialContextReader is simply a
wrapper.[[BR]]
{{{
void
MgFeatureServiceCacheEntry::SetSpatialContextReader(MgSpatialContextReader*
spatialContextReader)
{
m_spatialContextReader = SAFE_ADDREF(spatialContextReader);
}
MgSpatialContextReader*
MgFeatureServiceCacheEntry::GetSpatialContextReader()
{
return SAFE_ADDREF(m_spatialContextReader.p);
}
}}}
3. MgSpatialContextReader, which we can get from API, contains a
collection of MgSpatialContextData, and the reader will go through the
data one by one when read next. It has AddSpatialData(…) function to
initialize the MgSpatialContextData, which is called in
MgServerGetSpatialContexts when first time added to cache. And it has a
Close() function to clear the data.[[BR]]
{{{
void MgSpatialContextReader::Close()
{
m_spatialContextCol.Clear();
}
INT32 MgSpatialContextReader::AddSpatialData(MgSpatialContextData* data)
{
m_spatialContextCol.Add(data);
return m_spatialContextCol.GetCount();
}
}}}
== How the defect happens ==
[[BR]]
1. Open a Flexible web layout, and the function TransformCache*
TransformCache::GetLayerToMapTransform(…) is called. It gets the
MgSpatialContextReader. This is the first time when MgSpatialContextReader
is required, and the FDO command is executed to initialize it. Then it’s
added to the cache. However the reader is closed, making the internal data
clear.
2. Later another code in
$MgDev\OS\Oem\fusion\widgets\Query\classes\query.php try to get the
MgSpatialContextReader again. The cache contains the resource id and
entry, then it returns a MgSpatialContextReader. However the internal data
is empty, causing not able to get the spatial context any more.
--
Ticket URL: <https://trac.osgeo.org/mapguide/ticket/1119#comment:1>
MapGuide Open Source <http://mapguide.osgeo.org/>
MapGuide Open Source Internals
More information about the mapguide-trac
mailing list