Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "SyncML_DM_Archiver.H"
     18 #include "SyncML_DM_WBXMLArchive.H"
     19 #include "xpl_Logger.h"
     20 #include "dm_tree_class.H"
     21 #include "dm_uri_utils.h"
     22 #include "dm_tree_plugin_util.H"  //for Util function defns
     23 #include "dmprofile.h"
     24 #include "dmLockingHelper.h"
     25 #include "dmtTreeImpl.hpp"
     26 
     27 #ifdef TEST_DM_RECOVERY
     28 char power_fail_point[20] = {0};
     29 #endif
     30 
     31 SyncML_DM_Archiver::SyncML_DM_Archiver()
     32   : m_numArchives( 0 ),
     33     m_pTree( NULL ),
     34     m_pEnv( NULL )
     35 {
     36   // [0] is always root archive
     37 
     38   for( int i = 0; i < MAX_ARCHIVES; ++i )
     39   {
     40     m_pArchives[ i ] = NULL;
     41   }
     42 }
     43 
     44 SYNCML_DM_RET_STATUS_T SyncML_DM_Archiver::initArchives( CEnv* env, DMTree* tree )
     45 {
     46     SYNCML_DM_RET_STATUS_T retStat=SYNCML_DM_SUCCESS;
     47 
     48     if( !tree || !env ) return SYNCML_DM_FAIL;
     49     m_pTree = tree;
     50     m_pEnv  = env;
     51 
     52     //Load All the archives
     53     m_numArchives=0;
     54     m_pArchives[0]=NULL;
     55 
     56    //Load from TreeMountList and new all the Archives
     57     const char *pEntryTreePath     = NULL;
     58     const char *pEntryURI          = NULL;
     59 
     60     INT32 i = 0;  //tree mount start from 0
     61 
     62     // Get the first mount list entry
     63     m_pTree->GetTreeMountEntry(pEntryURI, pEntryTreePath, i);
     64 
     65     while(pEntryURI != NULL && pEntryTreePath != NULL)
     66     {
     67         /* Create the archive if it exists in the mount list */
     68         m_pArchives[m_numArchives]=NULL;
     69 
     70         if ( DmStrlen(pEntryTreePath) )
     71         {
     72 	        m_pArchives[m_numArchives]=new SyncML_DM_WBXMLArchive(env, pEntryURI, pEntryTreePath);
     73 
     74 	        if ( !m_pArchives[m_numArchives] )
     75 	          return SYNCML_DM_DEVICE_FULL;
     76 
     77               if ( m_pArchives[m_numArchives]->Init(tree) != SYNCML_DM_SUCCESS )
     78                 return SYNCML_DM_FAIL;
     79 
     80               // XPL_LOG_DM_TMN_Debug(("pEntryURI=%s, archive=%x\n", pEntryURI, m_pArchives[m_numArchives]));
     81 
     82 	        INT32 parentindex=-1;
     83 	        INT32 parentlen=0;
     84 	        for (INT32 j=0; j< m_numArchives; j++)
     85 	        {
     86 	            if ( DmStrstr(pEntryURI, m_pArchives[j]->getURI())== pEntryURI)
     87 	            {
     88 	                INT32 len=DmStrlen(m_pArchives[j]->getURI());
     89 
     90 	                if (parentlen < len)
     91 	                {
     92 	                    parentlen=len;
     93 	                    parentindex=j;
     94 	                }
     95 	            }
     96 	        }
     97 
     98 	        if (parentindex >=0)
     99 	            m_pArchives[m_numArchives]->setParentArchive(m_pArchives[parentindex]);
    100 
    101 	        m_numArchives++;
    102 	        //Does not support More than 32 archives...
    103 	        if (m_numArchives >=32)
    104 	            break;
    105         }
    106 
    107         /* In case the GetTreeMountEntry service has an error,
    108         * Ensure these are sensible values going in
    109         */
    110         pEntryURI = NULL;
    111         pEntryTreePath = NULL;
    112         m_pTree->GetTreeMountEntry(pEntryURI, pEntryTreePath, ++i);
    113     }
    114 
    115     if (m_numArchives ==0)
    116         retStat=SYNCML_DM_FAIL;
    117 
    118     XPL_LOG_DM_TMN_Debug(("m_numArchives=%d\n", m_numArchives));
    119 
    120 #ifdef TEST_DM_RECOVERY
    121   if(XPL_DM_GetEnv(SYNCML_DM_POWER_FAIL_IJECTION) != NULL) {
    122     strcpy((char *)power_fail_point, (const char *)XPL_DM_GetEnv(SYNCML_DM_POWER_FAIL_IJECTION));
    123     XPL_LOG_DM_TMN_Debug(("Power Fail Injected at: %s\n", power_fail_point));
    124   }
    125 #endif
    126 
    127   return retStat;
    128 }
    129 
    130 // A helper method for making sure that ALL archives is freed
    131 SYNCML_DM_RET_STATUS_T SyncML_DM_Archiver::deinitArchives()
    132 {
    133     SYNCML_DM_RET_STATUS_T retStat=SYNCML_DM_SUCCESS;
    134 
    135     //serialize if needed, Do we need to do so ? The lock manager should have already do it.
    136 
    137     //delete the archives
    138     for (int i=0; i<m_numArchives; i++)
    139     {
    140        if ( m_pArchives[i] !=NULL)
    141        {
    142           delete m_pArchives[i];
    143           m_pArchives[i]=NULL;
    144        }
    145     }
    146 
    147     m_numArchives = 0;
    148     m_pTree = NULL;
    149     m_pEnv = NULL;
    150 
    151     return retStat;
    152 }
    153 
    154 
    155 /*==================================================================================================
    156 
    157 Function:    SyncML_DM_Archiver::serialize
    158 
    159 Description: Distributes a serialization request to the proper archive(s).  A search is performed
    160              for the right archive relative to the root archive.  All tree data will be serialized
    161              to the point possible.
    162 
    163 Returns:     SYNCML_DM_FAIL         - tree or archive objects are NULL or an unspecified error occurred
    164              SYNCML_DM_SUCCESS      - tree was successfully serialized to proper files
    165              SYNCML_DM_TREE_CORRUPT - tree storage entity was corrupt to the point where
    166                                       serialization was partially or completely impossible
    167              SYNCML_DM_IO_FAILURE   - I/O failure occured while trying to write to the file handle
    168 
    169 ==================================================================================================*/
    170 SYNCML_DM_RET_STATUS_T
    171 SyncML_DM_Archiver::serialize(FILESETTYPE nFileSet, CPCHAR szURI)
    172 {
    173     DMGlobalLockHelper oGlobalLock;  // protect serialize/recovery from multi process access
    174     FILESETTYPE set=1;
    175     SYNCML_DM_RET_STATUS_T retStat=SYNCML_DM_SUCCESS;
    176     INT32 i=0;
    177 
    178     if( !m_pTree ) return SYNCML_DM_FAIL;
    179 
    180     XPL_LOG_DM_TMN_Debug(("Enter to serialize\n"));
    181 
    182     for (i=0; i< m_numArchives && m_pArchives[i] !=NULL; i++)
    183     {
    184         if (  (nFileSet & set) !=0 ) {
    185             if (m_pArchives[i]->isDirty()) {
    186 #ifdef TEST_DM_RECOVERY
    187                 if ((power_fail_point != NULL) && (DmStrcmp(power_fail_point, "DMTR_PF1") == 0)) {
    188                     printf("Type Ctrl-C to simulate Power Fail ...\n");
    189                     sleep(30);
    190                 }
    191 #endif
    192                 XPL_LOG_DM_TMN_Debug(("m_pArchives[%d] %s is dirty, to be serialized", i, m_pArchives[i]->getURI()));
    193                 retStat=m_pArchives[i]->serialize(m_pTree);
    194                 XPL_LOG_DM_TMN_Debug(("serialize retStat = %d", retStat));
    195                 if (retStat != SYNCML_DM_SUCCESS )
    196                     break;
    197             }
    198         }
    199         set = set <<1;
    200     }
    201 
    202     XPL_LOG_DM_TMN_Debug(("serialize retStat = %d", retStat));
    203     if (retStat != SYNCML_DM_SUCCESS )
    204         return retStat;
    205 
    206     /* Begin the power loss-tolerant steps to protect against a partially written Archive file:
    207     * 1. Rename the original file by adding ".bak" to the name; this indicates the .temp file
    208     *    was completely written
    209     * 2. Rename the .temp file to the original name (i.e., without the .temp extention)
    210     * 3. Delete the .bak file
    211     */
    212     DMString strOrgFilePathBuffer, strTmpFilePathBuffer, strBakFilePathBuffer;
    213 
    214     char *orgFilePath = strOrgFilePathBuffer.AllocateBuffer(XPL_FS_MAX_FILE_NAME_LENGTH);
    215     char *tmpFilePath =strTmpFilePathBuffer.AllocateBuffer(XPL_FS_MAX_FILE_NAME_LENGTH);
    216     char *bakFilePath = strBakFilePathBuffer.AllocateBuffer(XPL_FS_MAX_FILE_NAME_LENGTH);
    217     XPL_FS_RET_STATUS_T ret=0;
    218     BOOLEAN   bAtLeastOneDirty = FALSE; // check if at least one change exist to invoke commit plug-in
    219 
    220     if ( !orgFilePath || !tmpFilePath || !bakFilePath)
    221       return SYNCML_DM_DEVICE_FULL;
    222 
    223 
    224     // 2nd Change File names, orig->bak
    225     for (i=0, set=1; i< m_numArchives && m_pArchives[i] !=NULL; i++, set = set <<1)
    226     {
    227         if ( (nFileSet & set) !=0  && m_pArchives[i]->isDirty() && m_pArchives[i]->isWritableExist() )
    228         {
    229 #ifdef TEST_DM_RECOVERY
    230             if ((power_fail_point != NULL) && (DmStrcmp(power_fail_point, "DMTR_PF2") == 0)) {
    231                 printf("Type Ctrl-C to simulate Power Fail ...\n");
    232                 sleep(30);
    233             }
    234 #endif
    235 #ifdef LOB_SUPPORT
    236 		retStat = m_pArchives[i]->CloseCommitLog();
    237 		if (retStat != SYNCML_DM_SUCCESS )
    238 			return retStat;
    239 #endif
    240             m_pArchives[i]->getFilePath(orgFilePath, "");
    241             m_pArchives[i]->getFilePath(bakFilePath, ".bak");
    242             ret=XPL_FS_Rename(  orgFilePath, bakFilePath );
    243             if (ret != XPL_FS_RET_SUCCESS)
    244             {
    245                 ret=XPL_FS_Rename(  orgFilePath, bakFilePath );
    246                 retStat=SYNCML_DM_IO_FAILURE;
    247                 break;
    248             }
    249         }
    250     }
    251 
    252     for (i=0, set=1; i< m_numArchives && m_pArchives[i] !=NULL; i++, set = set <<1)
    253     {
    254         if ( (nFileSet & set) !=0  && m_pArchives[i]->isDirty() )
    255         {
    256 #ifdef TEST_DM_RECOVERY
    257             if ((power_fail_point != NULL) && (DmStrcmp(power_fail_point, "DMTR_PF3") == 0)) {
    258                 printf("Type Ctrl-C to simulate Power Fail ...\n");
    259                 sleep(30);
    260             }
    261 #endif
    262 
    263             bAtLeastOneDirty = TRUE;
    264 
    265             m_pArchives[i]->getFilePath(tmpFilePath, ".temp");
    266             m_pArchives[i]->getFilePath(orgFilePath, "");
    267             m_pArchives[i]->getFilePath(bakFilePath, ".bak");
    268             ret=XPL_FS_Rename(tmpFilePath, orgFilePath);
    269             if (ret != XPL_FS_RET_SUCCESS)
    270             {
    271                 ret=XPL_FS_Rename(bakFilePath, orgFilePath);
    272                 retStat=SYNCML_DM_IO_FAILURE;
    273                 break;
    274             }
    275         }
    276     }
    277 
    278     // commit plug-in support - invoke it only when some changes were done
    279     if ( bAtLeastOneDirty )
    280       InvokeCommitPlugins( nFileSet, szURI );
    281 
    282     for (i=0, set=1; i< m_numArchives && m_pArchives[i] !=NULL; i++, set = set <<1)
    283     {
    284         //set dirty to false
    285         if ( (nFileSet & set) !=0  && m_pArchives[i]->isDirty() )
    286         {
    287 #ifdef TEST_DM_RECOVERY
    288             if ((power_fail_point != NULL) && (DmStrcmp(power_fail_point, "DMTR_PF4") == 0)) {
    289                 printf("Type Ctrl-C to simulate Power Fail ...\n");
    290                 sleep(30);
    291             }
    292 #endif
    293 #ifdef LOB_SUPPORT
    294 		// Commit changes for ESN
    295 		retStat=m_pArchives[i]->commitESN(m_pTree);
    296 #endif
    297             m_pArchives[i]->setDirty(false);
    298 
    299             //Let each archive finished its own task, reset timestamp etc.
    300             m_pArchives[i]->serializeDone();
    301             XPL_LOG_DM_TMN_Debug(("serializeDone for %s\n", orgFilePath));
    302 
    303             if ( m_pArchives[i]->isWritableExist() )
    304             {
    305                 m_pArchives[i]->getFilePath(bakFilePath, ".bak");
    306 
    307 #ifndef DM_NO_LOCKING
    308                 ret=XPL_FS_Unlink(bakFilePath);
    309 #else
    310                 ret=XPL_FS_Remove(bakFilePath);
    311 #endif
    312                 XPL_LOG_DM_TMN_Debug(("delete archives[%d] %s ret=%d\n", i, bakFilePath, ret));
    313                 if (ret != XPL_FS_RET_SUCCESS)
    314                 {
    315                     retStat = SYNCML_DM_IO_FAILURE;
    316                     break;
    317                 }
    318             }
    319         }
    320         if ( (nFileSet & set) !=0  && m_pArchives[i]->isDirty() )
    321             m_pArchives[i]->setWritableExist(TRUE);
    322 
    323    }
    324 
    325     return retStat;
    326 }
    327 
    328 /*==================================================================================================
    329 
    330 Function:    SyncML_DM_Archiver::deserialize
    331 
    332 Description: Distributes a deserialization request to the proper archive(s).  Each archive (starting
    333              with the root archive) will deserialize into the DM T/N Manager using the AddNode
    334              method for passing nodes.
    335 
    336 Returns:     SYNCML_DM_FAIL         - tree or archive objects are NULL or an unspecified error occured
    337              SYNCML_DM_SUCCESS      - tree was successfully deserialized from proper files
    338              SYNCML_DM_TREE_CORRUPT - tree storage entity was corrupt to the point where
    339                                 deserialization was partially or completely impossible
    340              SYNCML_DM_FILE_NOT_FOUND - file was unavailable for deserialization
    341              SYNCML_DM_IO_FAILURE   - I/O failure occured while trying to read from the file handle
    342 
    343 ==================================================================================================*/
    344 SYNCML_DM_RET_STATUS_T
    345 SyncML_DM_Archiver::deserialize(FILESETTYPE nFileSet,
    346                                               SYNCML_DM_TREE_LOCK_TYPE_T eLockType)
    347 {
    348     DMGlobalLockHelper oGlobalLock;  // protect serialize/recovery from multi process access
    349     FILESETTYPE set=1;
    350     SYNCML_DM_RET_STATUS_T dm_stat = SYNCML_DM_SUCCESS;
    351 
    352     if( !m_pTree ) return SYNCML_DM_FAIL;
    353 
    354     checkRecovery();
    355 
    356     // do not load files itself, instead create only skeleton based on file set.
    357     for (INT32 i=0; i< m_numArchives && m_pArchives[i] !=NULL; i++)
    358     {
    359         if (  (nFileSet & set) !=0 )
    360         {
    361             BOOLEAN bIsPermitted = TRUE;
    362             bIsPermitted = m_pArchives[i]->verifyPermission(XPL_FS_RDONLY_MODE);
    363 
    364             if ( bIsPermitted )
    365             {
    366 
    367                 if ( !m_pArchives[i]->LoadSkeleton(m_pTree))
    368                       dm_stat = SYNCML_DM_DEVICE_FULL;
    369 
    370                 if ( dm_stat != SYNCML_DM_SUCCESS )
    371                     return dm_stat;
    372 
    373                 if ( eLockType == SYNCML_DM_LOCK_TYPE_SHARED )
    374                 {
    375                    dm_stat =  m_pArchives[i]->deserialize(m_pTree,TRUE);
    376                 }
    377             }
    378 
    379             m_pArchives[i]->setDirty(FALSE);
    380 
    381         }
    382         set = set <<1;
    383     }
    384 
    385     XPL_LOG_DM_TMN_Debug(("End of all deserialize retStat=%d\n", dm_stat));
    386     return dm_stat;
    387 }
    388 
    389 
    390 //Get all required Archives containing the URI
    391 FILESETTYPE SyncML_DM_Archiver::getArchivesByURI(CPCHAR pURI) const
    392 {
    393     FILESETTYPE nFileSet=0;
    394     FILESETTYPE set=1;
    395     SyncML_DM_Archive* pArchive=NULL;
    396 
    397     INT32 containingArchive=0;
    398     INT32 containingArchiveURIlen=0;
    399     BOOLEAN bContainingNeeded = TRUE;
    400 
    401    //set = set <<1; //start from 2nd file
    402     for (int i=0; i< m_numArchives; i++)  //NOT detect root !
    403     {
    404         pArchive = m_pArchives[i];
    405 
    406         //For now assume no recursive files
    407         const char * archivePath=pArchive->getURI();
    408 
    409         char * ptr=NULL;
    410 
    411         //we need any file that is subtree of the pURI
    412         //For example, archivePath=./abc pURI=. then
    413         //if we found pURI under archivePath, we go
    414         ptr=(char*)DmStrstr(archivePath, pURI );
    415 
    416         if ( ptr !=NULL && ptr == archivePath ) {
    417             nFileSet= nFileSet | set;
    418         }
    419 
    420         // in case when we hit exactly root path , we don't need parent
    421         if ( DmStrcmp( archivePath, pURI ) == 0  )
    422             bContainingNeeded = FALSE;
    423 
    424         //search for longest archives that has the pURI as a childnode
    425         //For example, archivePath=./abc pURI=./abc/def then
    426         //if we found archivePath under pURI, we go
    427         ptr=(char*)DmStrstr(pURI, archivePath );
    428 
    429         if (ptr !=NULL && ptr == pURI) {
    430             if (containingArchiveURIlen < (INT32)DmStrlen(archivePath)) {
    431                 containingArchive=i;
    432                 containingArchiveURIlen = DmStrlen(archivePath);
    433             }
    434         }
    435 
    436         set = set <<1;
    437     }
    438 
    439     if ( bContainingNeeded )
    440         nFileSet=nFileSet | (1 << (containingArchive)); //we need the containing archive
    441 
    442    //Debug("Add file [%d] to set, %s\n", containingArchive, m_pArchives[containingArchive]);
    443 
    444     return nFileSet;
    445 }
    446 
    447 
    448 
    449 //Get exact Archive containing the URI
    450 SyncML_DM_Archive* SyncML_DM_Archiver::getArchiveByURI(CPCHAR pURI) const
    451 {
    452 
    453 
    454     FILESETTYPE nFileSet ;
    455     FILESETTYPE set=1;
    456     INT32 index = 0;
    457 
    458     nFileSet = getArchivesByURI(pURI);
    459 
    460     for (INT32 i=0; i< m_numArchives && m_pArchives[i] !=NULL; i++)
    461     {
    462         if (  (nFileSet & set) !=0 )
    463         {
    464             if ( DmIsParentURI(m_pArchives[i]->getURI(), pURI) )
    465             {
    466                 index = i;
    467                 break;
    468             }
    469         }
    470          set = set <<1;
    471     }
    472 
    473     //XPL_LOG_DM_TMN_Debug(("returning archive=%x, uri=%s\n",m_pArchives[index], pURI ));
    474     return m_pArchives[index];
    475 }
    476 
    477 /*==================================================================================================
    478 
    479 Function:    SyncML_DM_Archiver::checkRecovery
    480 
    481 Description: Resolve recovery records after a serious phone critical failure event
    482 
    483 Returns:     SYNCML_DM_SUCCESS
    484              SYNCML_DM_IO_FAILURE
    485              SYNCML_DM_FILE_NOT_FOUND
    486              SYNCML_DM_LOG_CORRUPT
    487 
    488 ==================================================================================================*/
    489 SYNCML_DM_RET_STATUS_T
    490 SyncML_DM_Archiver::checkRecovery()
    491 {
    492     if( !m_pTree ) return SYNCML_DM_FAIL;
    493 
    494     SYNCML_DM_RET_STATUS_T retStat=SYNCML_DM_SUCCESS;
    495 
    496     //Check and recover All nodes all at once.
    497     DMString strOrgFilePathBuffer, strTmpFilePathBuffer, strBakFilePathBuffer, strCmtFilePathBuffer;
    498 
    499     char *orgFilePath = strOrgFilePathBuffer.AllocateBuffer(XPL_FS_MAX_FILE_NAME_LENGTH);
    500     char *tmpFilePath =strTmpFilePathBuffer.AllocateBuffer(XPL_FS_MAX_FILE_NAME_LENGTH);
    501     char *bakFilePath = strBakFilePathBuffer.AllocateBuffer(XPL_FS_MAX_FILE_NAME_LENGTH);
    502     char *cmtFilePath = strCmtFilePathBuffer.AllocateBuffer(XPL_FS_MAX_FILE_NAME_LENGTH);
    503 
    504     if ( !orgFilePath || !tmpFilePath || !bakFilePath || !cmtFilePath)
    505       return SYNCML_DM_DEVICE_FULL;
    506 
    507     XPL_FS_RET_STATUS_T ret=0;
    508 
    509     //Logic for checking corrupted files
    510     BOOLEAN tmpFileExists=FALSE;
    511     BOOLEAN bakFileExists=FALSE;
    512     BOOLEAN cmtFileExists=FALSE;
    513     INT32 i;
    514 
    515     if ( DmGetMemFailedFlag() ) // device runs out of memory
    516       return SYNCML_DM_DEVICE_FULL;
    517 
    518     m_pTree->RecoverPlugin();
    519 
    520     for (i=0; i< m_numArchives; i++)
    521     {
    522         m_pArchives[i]->getFilePath(orgFilePath, "");
    523         m_pArchives[i]->getFilePath(bakFilePath, ".bak");
    524         m_pArchives[i]->getFilePath(tmpFilePath, ".temp");
    525         m_pArchives[i]->getFilePath(cmtFilePath, ".cmt");
    526 
    527         if (XPL_FS_Exist(tmpFilePath))
    528             tmpFileExists=TRUE;
    529         if (XPL_FS_Exist(bakFilePath))
    530             bakFileExists=TRUE;
    531         if (XPL_FS_Exist(cmtFilePath))
    532             cmtFileExists=TRUE;
    533     }
    534 
    535     if ( tmpFileExists || bakFileExists )
    536         XPL_FS_Remove(DM_ISP_LOCK);
    537 
    538     if (tmpFileExists)
    539     {
    540         if (bakFileExists)
    541         {
    542             //Both temp file and bak file exists, rename bak to orig
    543             // rename bak files to orig files, then delete tmp files and commit log files
    544             for (i=0; i< m_numArchives; i++)
    545             {
    546                 m_pArchives[i]->getFilePath(orgFilePath, "");
    547                 m_pArchives[i]->getFilePath(bakFilePath, ".bak");
    548                 ret=XPL_FS_Rename(bakFilePath, orgFilePath);
    549                 XPL_LOG_DM_TMN_Debug(("DmFsRename %s->%s ret=%d\n", bakFilePath, orgFilePath, ret));
    550             }
    551         }
    552         for (i=0; i< m_numArchives; i++)
    553         {
    554             m_pArchives[i]->getFilePath(tmpFilePath, ".temp");
    555             m_pArchives[i]->getFilePath(cmtFilePath, ".cmt");
    556 #ifndef DM_NO_LOCKING
    557             ret=XPL_FS_Unlink(tmpFilePath);
    558             ret=XPL_FS_Unlink(cmtFilePath);
    559 #else
    560             ret=XPL_FS_Remove(tmpFilePath);
    561             ret=XPL_FS_Remove(cmtFilePath);
    562 #endif
    563             XPL_LOG_DM_TMN_Debug(("delete %s ret=%d\n", tmpFilePath, ret));
    564         }
    565     }
    566     else
    567     {
    568         if (bakFileExists | cmtFileExists)
    569         {
    570             //Only bak file exists
    571             // Delete bak files
    572             for (i=0; i< m_numArchives; i++)
    573             {
    574                 m_pArchives[i]->getFilePath(bakFilePath, ".bak");
    575                 m_pArchives[i]->getFilePath(cmtFilePath, ".cmt");
    576                 // Remove .bak file
    577                 if (XPL_FS_Exist(bakFilePath))
    578                 {
    579 #ifndef DM_NO_LOCKING
    580                     ret=XPL_FS_Unlink(bakFilePath);
    581 #else
    582                     ret=XPL_FS_Remove(bakFilePath);
    583 #endif
    584                     XPL_LOG_DM_TMN_Debug(("delete %s ret=%d\n", bakFilePath, ret));
    585                }
    586 #ifdef LOB_SUPPORT
    587                 // Play and remove commit log file
    588                if (XPL_FS_Exist(cmtFilePath))
    589                {
    590                     m_pArchives[i]->PlayCommitLog();
    591                }
    592 #endif
    593             }
    594         }
    595     }
    596 
    597    // Remove temorary LOB files
    598     {
    599         DMString lobDir;
    600         m_pEnv->GetWFSFullPath(NULL,lobDir);
    601         DmRemoveTempfile(lobDir);
    602     }
    603 
    604     //Logic for checking newer files
    605     for (i=0; i< m_numArchives && m_pArchives[i] !=NULL; i++)
    606     {
    607         if (m_pArchives[i]->getRootNode() !=NULL && !m_pArchives[i]->getRootNode()->IsSkeletonNode())
    608         {
    609             //Already loaded in memory
    610             if (m_pArchives[i]->getLastModifiedTime() != m_pArchives[i]->getLastSavedTime())
    611             {
    612                 //The files needed to be reloaded.
    613                 XPL_LOG_DM_TMN_Debug(("File[%d] %s is newer, need delete subtree & reload\n", i, m_pArchives[i]->getURI()));
    614                 XPL_LOG_DM_TMN_Debug((" last file modified time=0x%x memory time=0x%x\n",m_pArchives[i]->getLastModifiedTime(), m_pArchives[i]->getLastSavedTime()));
    615                 m_pTree->UnloadArchive(m_pArchives[i]->getRootNode());
    616             }
    617         }
    618     }
    619 
    620     return retStat;
    621 }
    622 
    623 SYNCML_DM_RET_STATUS_T
    624 SyncML_DM_Archiver::rollback(INT32 nFileSet)
    625 {
    626     if( !m_pTree ) return SYNCML_DM_FAIL;
    627 
    628     SYNCML_DM_RET_STATUS_T retStat=SYNCML_DM_SUCCESS;
    629 
    630     INT32 i=0;
    631     INT32 set=1;
    632     for (i=0, set=1; i< m_numArchives && m_pArchives[i] !=NULL; i++, set = set <<1 )
    633     {
    634         if ( (nFileSet & set) !=0 && m_pArchives[i]->getRootNode() != NULL )
    635         {
    636             //Already loaded in memory
    637             if ( m_pArchives[i]->isDirty() )
    638             {
    639                 //The files needed to be reloaded.
    640                 XPL_LOG_DM_TMN_Debug((" last file modified time=0x%x memory time=0x%x\n", m_pArchives[i]->getLastModifiedTime(),
    641                                                          m_pArchives[i]->getLastSavedTime()));
    642 
    643 #ifdef LOB_SUPPORT
    644                 // Rollback all changes for ESN
    645               m_pArchives[i]->rollbackESN(m_pTree);
    646 #endif
    647                m_pTree->UnloadArchive(m_pArchives[i]->getRootNode());
    648                m_pArchives[i]->setDirty(FALSE);
    649                m_pArchives[i]->GetEventLogger().Reset();
    650             }
    651         }
    652     }
    653 
    654     return retStat;
    655 }
    656 
    657 void
    658 SyncML_DM_Archiver::CheckMemoryAging(INT32 nAgingTime)
    659 {
    660     if( !m_pTree ) return;
    661 
    662     // current time in seconds
    663     XPL_CLK_CLOCK_T currentTime = XPL_CLK_GetClock();
    664     for (INT32 i=0; i < m_numArchives && m_pArchives[i] !=NULL; i++)
    665     {
    666       // free from memory
    667         if ( m_pArchives[i]->getRootNode()
    668             && !m_pArchives[i]->getRootNode()->IsSkeletonNode()
    669             && !m_pArchives[i]->isDirty() )
    670         {
    671             // Check the last accessed time in seconds
    672             XPL_CLK_CLOCK_T lastAccessedTime = m_pArchives[i]->getLastAccessedTime();
    673             if ( (currentTime - lastAccessedTime) >= (XPL_CLK_CLOCK_T)nAgingTime )
    674             {
    675                 XPL_LOG_DM_TMN_Debug(("m_pArchives[%d]->getURI() : %s is being unloaded, unused for %d >= aging time = %d\n",
    676                             i, m_pArchives[i]->getURI(), (currentTime - lastAccessedTime), nAgingTime));
    677             }
    678 
    679             m_pTree->UnloadArchive(m_pArchives[i]->getRootNode());
    680         }
    681     }
    682 }
    683 
    684 //------------------------------------------------------------------------
    685 // FUNCTION        : InvokeCommitPlugins
    686 // DESCRIPTION     : This function iterates all commit plug-ins
    687 //                   and calls "OnCommit" on each which has update event(s)
    688 // ARGUMENTS PASSED: szURI - sub-tree root uri
    689 //                   nFileSet - currently used file set
    690 // RETURN VALUE    : void
    691 // PRE-CONDITIONS  : called after successful serialization
    692 // POST-CONDITIONS :
    693 // IMPORTANT NOTES :
    694 // REQUIREMENT #   :
    695 //------------------------------------------------------------------------
    696 void SyncML_DM_Archiver::InvokeCommitPlugins(FILESETTYPE nFileSet, CPCHAR szURI)
    697 {
    698     PDmtTree tree( new DmtTreeImpl(true) );
    699     DMPluginVector  plugins;
    700     FILESETTYPE set=1;
    701     INT32 i=0;
    702 
    703     DMPluginManager & oPluginManager = m_pTree->GetPluginManager();
    704 
    705     oPluginManager.GetPlugins(szURI, SYNCML_DM_COMMIT_PLUGIN, plugins);
    706 
    707     for (INT32 nPlugin = 0; nPlugin < plugins.size(); nPlugin++ )
    708     {
    709         DmtEventMap updatedNodes;
    710 
    711         for (i=0, set=1; i< m_numArchives && m_pArchives[i] !=NULL; i++, set = set <<1)
    712         {
    713             if ( (nFileSet & set) !=0  && m_pArchives[i]->isDirty() )
    714             {
    715                 m_pArchives[i]->GetEventLogger().GetCommitPluginEvents(plugins[nPlugin], updatedNodes );
    716             }
    717         }
    718 
    719         if ( updatedNodes.size() > 0 )
    720             plugins[nPlugin]->OnCommit( updatedNodes, tree );
    721     }
    722 }
    723 
    724 
    725 //------------------------------------------------------------------------
    726 // FUNCTION        : CleanEvents
    727 // DESCRIPTION     : This function iterates all archives and remove stored events
    728 // ARGUMENTS PASSED: szURI - sub-tree root uri
    729 // RETURN VALUE    : void
    730 // PRE-CONDITIONS  : called after successful serialization
    731 // POST-CONDITIONS :
    732 // IMPORTANT NOTES :
    733 // REQUIREMENT #   :
    734 //------------------------------------------------------------------------
    735 SYNCML_DM_RET_STATUS_T
    736 SyncML_DM_Archiver::CleanEvents(CPCHAR szURI)
    737 
    738 {
    739     FILESETTYPE set=1;
    740     FILESETTYPE nFileSet=0;
    741 
    742     nFileSet = getArchivesByURI(szURI);
    743 
    744     for (FILESETTYPE i=0, set=1; i < m_numArchives; i++, set <<= 1)
    745     {
    746         if ( (nFileSet & set) !=0 && m_pArchives[i]->isDirty() )
    747         {
    748             m_pArchives[i]->GetEventLogger().CleanEvents(szURI);
    749         }
    750     }
    751     return SYNCML_DM_SUCCESS;
    752 }
    753 
    754 
    755 //------------------------------------------------------------------------
    756 // FUNCTION        : UpdateEvents
    757 // DESCRIPTION     : This function iterates all archives and remove stored events
    758 // ARGUMENTS PASSED: szURI - sub-tree root uri
    759 // RETURN VALUE    : void
    760 // PRE-CONDITIONS  : called after successful serialization
    761 // POST-CONDITIONS :
    762 // IMPORTANT NOTES :
    763 // REQUIREMENT #   :
    764 //------------------------------------------------------------------------
    765 SYNCML_DM_RET_STATUS_T
    766 SyncML_DM_Archiver::UpdateEvents(CPCHAR szURI, CPCHAR szNewName)
    767 
    768 {
    769     FILESETTYPE set=1;
    770     FILESETTYPE nFileSet=0;
    771 
    772     nFileSet = getArchivesByURI(szURI);
    773 
    774     for (FILESETTYPE i=0, set=1; i< m_numArchives; i++, set = set <<1)
    775     {
    776         if ( (nFileSet & set) !=0  && m_pArchives[i]->isDirty() )
    777         {
    778             m_pArchives[i]->GetEventLogger().UpdateEvents(szURI,szNewName);
    779         }
    780     }
    781     return SYNCML_DM_SUCCESS;
    782 }
    783 
    784 //------------------------------------------------------------------------
    785 // FUNCTION        : IsDirty
    786 // DESCRIPTION     : Checks if file set has been modified
    787 //
    788 // ARGUMENTS PASSED: nFileSet - currently used file set
    789 // RETURN VALUE    : void
    790 // PRE-CONDITIONS  : called before serialization
    791 // POST-CONDITIONS :
    792 // IMPORTANT NOTES :
    793 // REQUIREMENT #   :
    794 //------------------------------------------------------------------------
    795 BOOLEAN SyncML_DM_Archiver::IsDirty(FILESETTYPE * pFileSet)
    796 {
    797     FILESETTYPE i=0;
    798     FILESETTYPE set=1;
    799 
    800     if ( pFileSet == NULL )
    801         return TRUE;
    802 
    803     for (i=0, set=1; i< m_numArchives;   i++, set = set <<1)
    804     {
    805         if ( ((*pFileSet) & set) !=0  && m_pArchives[i]->isDirty() == FALSE )
    806             (*pFileSet) &= ~set;
    807     }
    808 
    809     if ( (*pFileSet) == 0 )
    810         return FALSE;
    811     else
    812         return TRUE;
    813 }
    814