[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