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 /*==================================================================================================
     18 
     19     File Name: SyncML_PlugIn_WBXMLLog.cc
     20 
     21     General Description: This contains function implementations of the WBXMLLog class.
     22 
     23 ==================================================================================================*/
     24 
     25 #include "dmStringUtil.h"
     26 #include "SyncML_PlugIn_WBXMLLog.H"
     27 #include "SyncML_DM_WBXMLArchive.H"
     28 #include "dmtRWPlugin.hpp"
     29 #include "dm_tree_plugin_util.H"
     30 #include "dm_uri_utils.h"
     31 #include "dm_tree_util.h"
     32 
     33 #ifdef TEST_DM_RECOVERY
     34 extern char power_fail_point[];
     35 #endif
     36 
     37 /*==================================================================================================
     38 
     39 Function:    SyncML_PlugIn_WBXMLLog::SyncML_PlugIn_WBXMLLog
     40 
     41 Description: Constructor for the Log object
     42 
     43 ==================================================================================================*/
     44 
     45 SyncML_PlugIn_WBXMLLog::SyncML_PlugIn_WBXMLLog(const DmtRWPluginTree *pluginTree, const char * rootPath):SyncML_Log()
     46 {
     47     m_strRootPath=rootPath;
     48     prevRecord = 0;
     49     this->pluginTree = pluginTree;
     50 }
     51 /*==================================================================================================
     52 
     53 Function:    SyncML_PlugIn_WBXMLLog::~SyncML_PlugIn_WBXMLLog
     54 
     55 Description: Destructor for the Log object
     56 
     57 ==================================================================================================*/
     58 SyncML_PlugIn_WBXMLLog::~SyncML_PlugIn_WBXMLLog()
     59 {
     60 	UnInitLog();
     61 }
     62 /*==================================================================================================
     63 
     64 Function:    SyncML_PlugIn_WBXMLLog::UnInitLog
     65 
     66 Description: Uninitialize log
     67 
     68 ==================================================================================================*/
     69  SYNCML_DM_RET_STATUS_T SyncML_PlugIn_WBXMLLog::UnInitLog()
     70 {
     71     if(reader != NULL)
     72     {
     73         delete reader;
     74         reader = NULL;
     75     }
     76 
     77     if(writer != NULL)
     78     {
     79         delete writer;
     80         writer = NULL;
     81     }
     82    return	 SYNCML_DM_SUCCESS;
     83 }
     84 /*==================================================================================================
     85 
     86 Function:    SyncML_PlugIn_WBXMLLog::InitLog
     87 
     88 Description: Open/Create log file
     89 
     90 ==================================================================================================*/
     91 SYNCML_DM_RET_STATUS_T SyncML_PlugIn_WBXMLLog::InitLog(CPCHAR logFileName)
     92 {
     93   SYNCML_DM_RET_STATUS_T dm_stat =  UnInitLog();;
     94   BOOLEAN  m_WriteHeader = FALSE;
     95 
     96    if ( dm_stat != SYNCML_DM_SUCCESS)
     97 		 return dm_stat;
     98 
     99     if (!XPL_FS_Exist(logFileName))
    100         m_WriteHeader = TRUE;
    101 
    102    dm_stat = SyncML_Log::InitLog(logFileName);
    103    if ( dm_stat != SYNCML_DM_SUCCESS)
    104 	   return dm_stat;
    105 
    106 	// Write log file file header
    107     if(m_WriteHeader)
    108    	{
    109         // Go to end of log file
    110         if(this->fileHandle->seek(XPL_FS_SEEK_END, 0) != SYNCML_DM_SUCCESS)
    111          {
    112 		CloseLog();
    113          	dm_stat = SYNCML_DM_IO_FAILURE;
    114         }
    115         // Write log header
    116         prevRecord = this->fileHandle->position();
    117         if(prevRecord == 0)
    118         {
    119 		if(writer == NULL)
    120 		{  writer = new SyncML_DM_WBXMLWriter(this->fileHandle);
    121 			   if( writer == NULL)
    122 			   return SYNCML_DM_DEVICE_FULL;
    123 		}
    124             if(this->writeLogHeader(writer) != SYNCML_DM_SUCCESS)
    125 		{
    126 			CloseLog();
    127 			dm_stat = SYNCML_DM_IO_FAILURE;
    128 		}
    129         }
    130     	}
    131 	return dm_stat;
    132 }
    133 
    134 /*============================================================================n
    135 
    136 Function:    SyncML_PlugIn_WBXMLLog::updatePosition
    137 
    138 Description: Update position information
    139 
    140 Memory:      The caller is responsible for freeing the SyncML_DM_Command object
    141 
    142 Notes:
    143 
    144 ================================================================================*/
    145 SYNCML_DM_RET_STATUS_T
    146 SyncML_PlugIn_WBXMLLog::updatePosition(SyncML_DM_WBXMLWriter* writer)
    147 {
    148     INT32 tempPos = 0;
    149     INT32 currentPos = 0;
    150 
    151 
    152     // Write previous record position
    153     if(writer->writeData((const UINT8*)&this->prevRecord, sizeof(this->prevRecord)) != SYNCML_DM_SUCCESS)
    154         return  SYNCML_DM_IO_FAILURE;
    155 
    156     // Place holder for next record  pointer
    157     if(writer->writeData((const UINT8*)&tempPos, sizeof(tempPos)) != SYNCML_DM_SUCCESS)
    158         return  SYNCML_DM_IO_FAILURE;
    159 
    160     // Go to end of log file
    161     if(this->fileHandle->seek(XPL_FS_SEEK_END, 0) != SYNCML_DM_SUCCESS)
    162         return  SYNCML_DM_IO_FAILURE;
    163 
    164     currentPos = this->fileHandle->position();
    165 
    166     // Go to the previous place holder
    167     if(this->fileHandle->seek(XPL_FS_SEEK_SET, this->prevRecord - sizeof(INT32)) != SYNCML_DM_SUCCESS)
    168         return  SYNCML_DM_IO_FAILURE;
    169 
    170     tempPos = this->fileHandle->position();
    171 
    172     if(writer->writeData((const UINT8*)&currentPos, sizeof(currentPos)) != SYNCML_DM_SUCCESS)
    173         return  SYNCML_DM_IO_FAILURE;
    174 
    175     // Go to end of log file
    176     if(this->fileHandle->seek(XPL_FS_SEEK_END, 0) != SYNCML_DM_SUCCESS)
    177         return  SYNCML_DM_IO_FAILURE;
    178 
    179     this->prevRecord = currentPos;
    180 
    181     return SYNCML_DM_SUCCESS;
    182 
    183 }
    184 /*============================================================================n
    185 
    186 Function:    SyncML_PlugIn_WBXMLLog::writeLogHeader
    187 
    188 Description: Write log header information
    189 
    190 Notes:
    191 
    192 ================================================================================*/
    193 SYNCML_DM_RET_STATUS_T
    194 SyncML_PlugIn_WBXMLLog::writeLogHeader(SyncML_DM_WBXMLWriter* writer)
    195 {
    196     INT32 tempPos = 0;
    197     prevRecord    = 3 * sizeof(INT32) + m_strRootPath.length() + 4;
    198 
    199     if(writer->writeData((const UINT8*)&prevRecord, sizeof(prevRecord)) != SYNCML_DM_SUCCESS)
    200        return  SYNCML_DM_IO_FAILURE;
    201 
    202     if(writer->writeByte(SyncML_DM_WBXMLArchive::URI_START_TAG
    203                          | SyncML_DM_WBXMLArchive::TAG_CONTENT_MASK) != SYNCML_DM_SUCCESS)
    204         return  SYNCML_DM_IO_FAILURE;
    205 
    206     if(writer->writeString(m_strRootPath.c_str()) != SYNCML_DM_SUCCESS)
    207         return  SYNCML_DM_IO_FAILURE;
    208 
    209     if(this->fileHandle->seek(XPL_FS_SEEK_END, 0) != SYNCML_DM_SUCCESS)
    210         return  SYNCML_DM_IO_FAILURE;
    211 
    212     if(writer->writeByte(SyncML_DM_WBXMLArchive::END_TAG) != SYNCML_DM_SUCCESS)
    213         return  SYNCML_DM_IO_FAILURE;
    214 
    215     if(writer->writeData((const UINT8*)&tempPos, sizeof(tempPos)) != SYNCML_DM_SUCCESS)
    216         return  SYNCML_DM_IO_FAILURE;
    217 
    218     if(writer->writeData((const UINT8*)&tempPos, sizeof(tempPos)) != SYNCML_DM_SUCCESS)
    219         return  SYNCML_DM_IO_FAILURE;
    220 
    221     return SYNCML_DM_SUCCESS;
    222 }
    223 /*============================================================================n
    224 
    225 Function:    SyncML_PlugIn_WBXMLLog::writeLogHeader
    226 
    227 Description: Write log header information
    228 
    229 Notes:
    230 
    231 ================================================================================*/
    232 SYNCML_DM_RET_STATUS_T
    233 SyncML_PlugIn_WBXMLLog::writePluginNode(CPCHAR pbURI, SyncML_DM_WBXMLWriter* writer, const DmtNode* ptrNode)
    234 {
    235     SYNCML_DM_RET_STATUS_T dm_stat = SYNCML_DM_SUCCESS;
    236     DMString strVal;
    237     DMGetData oGetData;
    238     BOOLEAN  m_bESN = FALSE;
    239     CPCHAR tmpStr = NULL;
    240 
    241 
    242     DmtAttributes oAttr;
    243     dm_stat = ptrNode->GetAttributes( oAttr );
    244     if( dm_stat != SYNCML_DM_SUCCESS )
    245         return dm_stat;
    246 
    247     if (ptrNode->IsLeaf())
    248     {
    249         DmtData data;
    250         dm_stat = ptrNode->GetValue(data);
    251 
    252         if (dm_stat == SYNCML_DM_SUCCESS)
    253             dm_stat = oGetData.set(data,oAttr.GetType());
    254 #ifdef LOB_SUPPORT
    255 	if(ptrNode->IsExternalStorageNode())
    256       {
    257 		PDmtRWPluginNode pRWNode = (DmtRWPluginNode *) ((DmtNode *)ptrNode);
    258 		m_bESN = TRUE;
    259 		tmpStr = pRWNode->GetESNBackupFileName();
    260 	}
    261 #endif
    262     }
    263     else
    264     {
    265         DMStringVector mapNodeNames;
    266 
    267         dm_stat = ((DmtPluginTree *)this->pluginTree)->GetChildNodeNames( pbURI, mapNodeNames );
    268 
    269         if ( dm_stat != SYNCML_DM_SUCCESS )
    270            return dm_stat;
    271 
    272         for ( int i = 0; i < mapNodeNames.size(); i++ )
    273         {
    274            if (i >0)
    275               strVal += "/";
    276 
    277            strVal += mapNodeNames[i];
    278         }
    279         dm_stat = oGetData.set(SYNCML_DM_FORMAT_NODE,strVal,strVal.length(),"text/plain");
    280     }
    281 
    282     if ( dm_stat != SYNCML_DM_SUCCESS )
    283         return dm_stat;
    284 
    285     DMNode * psNodeObject = dmTreeObj.CreateNodeObj(oGetData.m_nFormat, m_bESN, tmpStr);
    286     if(psNodeObject == NULL)
    287        return SYNCML_DM_DEVICE_FULL;
    288 
    289     DMString nodeName;
    290 
    291     dm_stat = ptrNode->GetNodeName(nodeName);
    292     if ( dm_stat == SYNCML_DM_SUCCESS )
    293     {
    294         dm_stat = psNodeObject->set(nodeName,oAttr.GetTitle(),&oGetData);
    295         if ( dm_stat == SYNCML_DM_SUCCESS )
    296         {    dm_stat = writer->writeNode((const DMNode*)psNodeObject);
    297         	if ( dm_stat == SYNCML_DM_SUCCESS )
    298         	{
    299 			// Write interior node information
    300 			if (!ptrNode->IsLeaf())
    301 			{
    302 				if(strVal.length()!= 0)
    303 				{
    304 					if(writer->writeByte(SyncML_DM_WBXMLArchive::DATA_START_TAG | SyncML_DM_WBXMLArchive::TAG_CONTENT_MASK) != SYNCML_DM_SUCCESS ||
    305 						writer->writeOpaque((const UINT8*)strVal.c_str(), strVal.length()) != SYNCML_DM_SUCCESS ||
    306 						writer->writeByte(SyncML_DM_WBXMLArchive::END_TAG) != SYNCML_DM_SUCCESS)
    307 						dm_stat = SYNCML_DM_IO_FAILURE;
    308 
    309 				}
    310 			}
    311 
    312         	}
    313 
    314         }
    315     }
    316 
    317     delete psNodeObject;
    318 
    319     return dm_stat;
    320 }
    321 /*============================================================================n
    322 
    323 Function:    SyncML_PlugIn_WBXMLLog::writeURIInfo
    324 
    325 Description:Log URI information
    326 
    327 Memory:
    328 
    329 Notes:
    330 
    331 ================================================================================*/
    332 
    333 SYNCML_DM_RET_STATUS_T
    334 SyncML_PlugIn_WBXMLLog::writeURIInfo(SYNCML_DM_PLUGIN_COMMAND_T commandType, CPCHAR pbURI, SyncML_DM_WBXMLWriter* writer)
    335 {
    336     SYNCML_DM_RET_STATUS_T ret_code = SYNCML_DM_SUCCESS;
    337     UINT8 ioArray[5] = { SyncML_DM_WBXMLArchive::ENTRY_START_TAG |
    338                          SyncML_DM_WBXMLArchive::TAG_CONTENT_MASK,
    339                          SyncML_DM_WBXMLArchive::CMDTYPE_START_TAG |
    340                          SyncML_DM_WBXMLArchive::TAG_CONTENT_MASK,
    341                          commandType,
    342                          SyncML_DM_WBXMLArchive::END_TAG,
    343                          SyncML_DM_WBXMLArchive::URI_START_TAG |
    344                          SyncML_DM_WBXMLArchive::TAG_CONTENT_MASK};
    345 
    346     if(writer == NULL || fileHandle == NULL)
    347                 return SYNCML_DM_FAIL;
    348 
    349     // Go to end of log file
    350     if(this->fileHandle->seek(XPL_FS_SEEK_END, 0) != SYNCML_DM_SUCCESS)
    351     {
    352         ret_code = SYNCML_DM_IO_FAILURE;
    353         goto URIWriteFailed;
    354     }
    355 
    356 
    357     if(writer->writeData(ioArray, sizeof(ioArray)) != SYNCML_DM_SUCCESS){
    358         ret_code = SYNCML_DM_IO_FAILURE;
    359         goto URIWriteFailed;
    360     }
    361 
    362     if(writer->writeString(pbURI) != SYNCML_DM_SUCCESS){
    363         ret_code = SYNCML_DM_IO_FAILURE;
    364         goto URIWriteFailed;
    365     }
    366 
    367     /* End of the URI field */
    368     if(writer->writeByte(SyncML_DM_WBXMLArchive::END_TAG) != SYNCML_DM_SUCCESS){
    369         ret_code = SYNCML_DM_IO_FAILURE;
    370         goto URIWriteFailed;
    371     }
    372      return ret_code;
    373 
    374     URIWriteFailed:
    375         delete writer;
    376         writer = NULL;
    377         this->fileHandle->close();
    378         return ret_code;
    379 }
    380 
    381 /*============================================================================n
    382 
    383 Function:    SyncML_PlugIn_WBXMLLog::logCommand
    384 
    385 Description: logs the command type, URI, node properties and recovery field for
    386          a command in the log file.
    387 
    388 Memory:      The caller is responsible for freeing the SyncML_DM_Command object
    389 
    390 Notes:
    391 
    392 ================================================================================*/
    393 SYNCML_DM_RET_STATUS_T
    394 SyncML_PlugIn_WBXMLLog::logCommand(SYNCML_DM_PLUGIN_COMMAND_T commandType,
    395                                         CPCHAR pbURI,
    396                                         SYNCML_DM_PLUGIN_COMMAND_ATTRIBUTE_T attribute,
    397                                         const DmtNode* node)
    398 {
    399     SYNCML_DM_RET_STATUS_T ret_code = SYNCML_DM_SUCCESS;
    400     INT32 tempPos = 0;
    401     INT32 currentPos = 0;
    402     DMVector<PDmtNode> oChildren;
    403     PDmtRWPluginNode ptrTempNode = (DmtRWPluginNode *) ((DmtPluginNode *)node);
    404 
    405     if(commandType != SYNCML_DM_PLUGIN_ADD &&
    406        commandType != SYNCML_DM_PLUGIN_ADD_CHILD &&
    407        commandType != SYNCML_DM_PLUGIN_DELETE &&
    408        commandType != SYNCML_DM_PLUGIN_REPLACE)
    409     {
    410         return SYNCML_DM_FAIL;
    411     }
    412   if(writer == NULL)
    413   {  writer = new SyncML_DM_WBXMLWriter(this->fileHandle);
    414 	   if( writer == NULL)
    415 	   return SYNCML_DM_DEVICE_FULL;
    416   }
    417 
    418     if(commandType != SYNCML_DM_PLUGIN_ADD)
    419     {
    420         ret_code = writeURIInfo(commandType, pbURI, writer);
    421         if(ret_code != SYNCML_DM_SUCCESS)
    422             goto WriteFailed;
    423     }
    424 
    425     INT32 i;
    426     switch ( commandType )
    427     {
    428         case SYNCML_DM_PLUGIN_ADD:
    429         {
    430             if(node == NULL)
    431                 return  SYNCML_DM_FAIL;
    432 
    433              // Serialize the subtree
    434             ret_code = ptrTempNode->GetChildNodes( oChildren );
    435             DMString nodePath;
    436             for (i = 0; i < oChildren.size(); i++ )
    437             {
    438                 ret_code = oChildren[i]->GetPath(nodePath);
    439                 if(ret_code != SYNCML_DM_SUCCESS)
    440                     goto WriteFailed;
    441 
    442                 ret_code = logCommand(SYNCML_DM_PLUGIN_ADD,
    443                                       nodePath.c_str(),
    444                                       attribute,
    445                                      (const DmtNode*)oChildren[i]);
    446                 if(ret_code != SYNCML_DM_SUCCESS)
    447                     goto WriteFailed;
    448             }
    449             ret_code = writeURIInfo(commandType, pbURI, writer);
    450             if(ret_code != SYNCML_DM_SUCCESS)
    451                 goto WriteFailed;
    452 
    453             if(writePluginNode(pbURI, writer, node) != SYNCML_DM_SUCCESS)
    454             {
    455                 ret_code = SYNCML_DM_IO_FAILURE;
    456                 goto WriteFailed;
    457             }
    458             if(writer->writeByte(SyncML_DM_WBXMLArchive::END_TAG) != SYNCML_DM_SUCCESS)
    459             {
    460                 ret_code = SYNCML_DM_IO_FAILURE;
    461                 goto WriteFailed;
    462             }
    463 
    464             if(updatePosition(writer) != SYNCML_DM_SUCCESS)
    465             {
    466                 ret_code = SYNCML_DM_IO_FAILURE;
    467                 goto WriteFailed;
    468             }
    469         }
    470             break;
    471 
    472         case SYNCML_DM_PLUGIN_REPLACE:
    473             if(writer->writeByte(attribute) != SYNCML_DM_SUCCESS)
    474             {
    475                 ret_code = SYNCML_DM_IO_FAILURE;
    476                 goto WriteFailed;
    477             }
    478 
    479             switch(attribute)
    480             {
    481                 case SYNCML_DM_PLUGIN_COMMAND_ON_NODE:
    482                     if (node->IsLeaf())
    483                     {
    484                         DmtData data;
    485                         DMString strVal;
    486                         ret_code = node->GetValue(data);
    487                         if(ret_code == SYNCML_DM_SUCCESS)
    488                         {
    489                             if ( data.GetType() != SYNCML_DM_DATAFORMAT_NULL )
    490                                 ret_code = data.GetString(strVal);
    491                             if (ret_code == SYNCML_DM_SUCCESS && strVal.length() != 0)
    492                             {
    493                                  if(writer->writeByte(SyncML_DM_WBXMLArchive::DATA_START_TAG | SyncML_DM_WBXMLArchive::TAG_CONTENT_MASK) != SYNCML_DM_SUCCESS ||
    494                                     writer->writeOpaque((UINT8*)strVal.c_str(),strVal.length()) != SYNCML_DM_SUCCESS ||
    495                                     writer->writeByte(SyncML_DM_WBXMLArchive::END_TAG) != SYNCML_DM_SUCCESS)
    496                                  {
    497                                      ret_code = SYNCML_DM_IO_FAILURE;
    498                                      goto WriteFailed;
    499                                  }
    500                              }
    501 
    502                          }
    503                     }
    504                     else
    505                     {
    506                         ret_code = SYNCML_DM_FAIL;
    507                         goto WriteFailed;
    508                     }
    509                     break;
    510 
    511                 case SYNCML_DM_PLUGIN_COMMAND_ON_NAME_PROPERTY:
    512                 {
    513                     DMString nodeName;
    514 
    515                     ret_code = node->GetNodeName(nodeName);
    516                     if ( ret_code == SYNCML_DM_SUCCESS )
    517                     {
    518                         if(writer->writeByte(SyncML_DM_WBXMLArchive::NAME_START_TAG | SyncML_DM_WBXMLArchive::TAG_CONTENT_MASK) != SYNCML_DM_SUCCESS ||
    519                            writer->writeString(nodeName.c_str()) != SYNCML_DM_SUCCESS ||
    520                            writer->writeByte(SyncML_DM_WBXMLArchive::END_TAG) != SYNCML_DM_SUCCESS)
    521                         {
    522                             ret_code = SYNCML_DM_IO_FAILURE;
    523                             goto WriteFailed;
    524                         }
    525                     }
    526                 }
    527                     break;
    528 
    529                 case SYNCML_DM_PLUGIN_COMMAND_ON_TITLE_PROPERTY:
    530                 {
    531                     DmtAttributes oAttr;
    532                     ret_code = node->GetAttributes( oAttr );
    533                     if ( ret_code == SYNCML_DM_SUCCESS )
    534                     {
    535                         const DMString & title = oAttr.GetTitle();
    536                         if(writer->writeByte(SyncML_DM_WBXMLArchive::TITLE_START_TAG | SyncML_DM_WBXMLArchive::TAG_CONTENT_MASK) != SYNCML_DM_SUCCESS ||
    537                            writer->writeString(title.c_str()) != SYNCML_DM_SUCCESS ||
    538                            writer->writeByte(SyncML_DM_WBXMLArchive::END_TAG) != SYNCML_DM_SUCCESS)
    539                         {
    540                             ret_code = SYNCML_DM_IO_FAILURE;
    541                             goto WriteFailed;
    542                         }
    543                     }
    544                     else
    545                     {
    546                         ret_code = SYNCML_DM_FAIL;
    547                         goto WriteFailed;
    548                     }
    549                 }
    550                     break;
    551 #ifdef LOB_SUPPORT
    552 		   case SYNCML_DM_PLUGIN_COMMAND_ON_LOB_PROPERTY:
    553 		   {
    554 				CPCHAR  tmpStr = ptrTempNode->GetESNBackupFileName();
    555 
    556 				if ( tmpStr != NULL)
    557 				{
    558 					if(writer->writeByte(SyncML_DM_WBXMLArchive::ESN_File_NAME_START_TAG | SyncML_DM_WBXMLArchive::TAG_CONTENT_MASK) != SYNCML_DM_SUCCESS ||
    559 						writer->writeString(tmpStr) != SYNCML_DM_SUCCESS ||
    560 						writer->writeByte(SyncML_DM_WBXMLArchive::END_TAG) != SYNCML_DM_SUCCESS)
    561 						{
    562 								ret_code = SYNCML_DM_IO_FAILURE;
    563 								goto WriteFailed;
    564 						}
    565 				}
    566 				else
    567 				{
    568 					if(writer->writeByte(SyncML_DM_WBXMLArchive::END_TAG) != SYNCML_DM_SUCCESS)
    569 					{
    570 						ret_code = SYNCML_DM_IO_FAILURE;
    571 						goto WriteFailed;
    572 					}
    573 				}
    574 			}
    575 			break;
    576 #endif
    577 		default:
    578 			ret_code = SYNCML_DM_INVALID_PARAMETER;
    579 			goto WriteFailed;
    580 
    581             }
    582 
    583             if(updatePosition(writer) != SYNCML_DM_SUCCESS)
    584             {
    585                 ret_code = SYNCML_DM_IO_FAILURE;
    586                 goto WriteFailed;
    587             }
    588             break;
    589 
    590         case SYNCML_DM_PLUGIN_DELETE:
    591             if(writer->writeByte(SyncML_DM_WBXMLArchive::END_TAG) != SYNCML_DM_SUCCESS)
    592             {
    593                 ret_code = SYNCML_DM_IO_FAILURE;
    594                 goto WriteFailed;
    595             }
    596             if(updatePosition(writer) != SYNCML_DM_SUCCESS)
    597             {
    598                 ret_code = SYNCML_DM_IO_FAILURE;
    599                 goto WriteFailed;
    600             }
    601             break;
    602 
    603         case SYNCML_DM_PLUGIN_ADD_CHILD:
    604             if(writer->writeByte(SyncML_DM_WBXMLArchive::END_TAG) != SYNCML_DM_SUCCESS)
    605             {
    606                 ret_code = SYNCML_DM_IO_FAILURE;
    607                 goto WriteFailed;
    608             }
    609             if(updatePosition(writer) != SYNCML_DM_SUCCESS)
    610             {
    611                 ret_code = SYNCML_DM_IO_FAILURE;
    612                 goto WriteFailed;
    613             }
    614             break;
    615     }
    616 
    617 #ifdef TEST_DM_RECOVERY
    618     if ((power_fail_point != NULL) && (DmStrcmp(power_fail_point, "PLUGIN_PF4") == 0))
    619     {
    620         printf("Type Ctrl-C to simulate Power Fail ...\n");
    621         sleep(30);
    622     }
    623 #endif
    624 
    625     return ret_code;
    626 
    627 
    628     WriteFailed:
    629         delete writer;
    630         writer = NULL;
    631         this->fileHandle->close();
    632         return ret_code;
    633 
    634 }
    635 
    636 /*==============================================================================
    637 ====================
    638 
    639 Function:    SyncML_PlugIn_WBXMLLog::gotoLastRecord
    640 
    641 Description: Goto last log entry position
    642 
    643 Returns:     SYNCML_DM_IO_FAILURE     - could not perform an I/O operation
    644          SYNCML_DM_LOG_CORRUPT    - there was an invalid byte read
    645          SYNCML_DM_SUCCESS
    646          SYNCML_DM_FILE_NOT_FOUND - could not find the log file
    647 
    648 ================================================================================
    649 ==================*/
    650 SYNCML_DM_RET_STATUS_T
    651 SyncML_PlugIn_WBXMLLog::gotoLastRecord(SyncML_DM_WBXMLReader* reader,
    652                                            UINT8 *lastByte,
    653                                            INT32 *currentPos )
    654 {
    655     SYNCML_DM_RET_STATUS_T ret_code = SYNCML_DM_SUCCESS;
    656     INT32 tempPos = 0;
    657     INT32 currentRecordPos = 0;
    658     INT32 nextRecordPos = 0;
    659 
    660     *currentPos = 0;
    661 
    662     // Go to end of log file
    663     if(this->fileHandle->seek(XPL_FS_SEEK_SET, prevRecord - 2*sizeof(INT32)) != SYNCML_DM_SUCCESS)
    664         return  SYNCML_DM_IO_FAILURE;
    665 
    666     if(this->fileHandle->read((UINT8 *)currentPos, sizeof(INT32)) != SYNCML_DM_SUCCESS)
    667         return  SYNCML_DM_IO_FAILURE;
    668 
    669     // No log entry
    670     if(*currentPos == 0)
    671         return SYNCML_DM_SUCCESS;
    672 
    673     // Point to last log entry
    674     ret_code = this->fileHandle->seek(XPL_FS_SEEK_SET, (int)*currentPos);
    675 
    676     // If it is valid log entry
    677     if(reader->readByte(lastByte) != SYNCML_DM_SUCCESS ||
    678        *lastByte != (SyncML_DM_WBXMLArchive::ENTRY_START_TAG | SyncML_DM_WBXMLArchive::TAG_CONTENT_MASK))
    679     {
    680         // Point to last log entry
    681 
    682         if(this->fileHandle->seek(XPL_FS_SEEK_SET, 0) != SYNCML_DM_SUCCESS)
    683             return  SYNCML_DM_IO_FAILURE;
    684 
    685         if ((ret_code = this->fileHandle->read((UINT8 *)&currentRecordPos, sizeof(INT32))) != SYNCML_DM_SUCCESS)
    686             return  SYNCML_DM_IO_FAILURE;
    687 
    688         nextRecordPos = currentRecordPos;
    689 
    690         while((ret_code == SYNCML_DM_SUCCESS))
    691         {
    692             // Read next entry until the pointer is 0
    693             tempPos = currentRecordPos;
    694             this->fileHandle->seek(XPL_FS_SEEK_SET, tempPos-sizeof(INT32));
    695 
    696             ret_code=  this->fileHandle->read((UINT8 *)&currentRecordPos, sizeof(INT32));
    697             if((currentRecordPos == 0) || (ret_code != SYNCML_DM_SUCCESS))
    698                 break;
    699             nextRecordPos = tempPos;
    700         }
    701         *currentPos = nextRecordPos;
    702          // Read last entry
    703         this->fileHandle->seek(XPL_FS_SEEK_SET, (int)*currentPos);
    704 
    705         // If it is valid log entry
    706         if(reader->readByte(lastByte) != SYNCML_DM_SUCCESS ||
    707            *lastByte != (SyncML_DM_WBXMLArchive::ENTRY_START_TAG | SyncML_DM_WBXMLArchive::TAG_CONTENT_MASK))
    708         {
    709             //Read previous entry
    710             if(this->fileHandle->seek(XPL_FS_SEEK_SET, nextRecordPos-2*sizeof(INT32)) != SYNCML_DM_SUCCESS)
    711                 return  SYNCML_DM_IO_FAILURE;
    712             if(this->fileHandle->read((UINT8 *)currentPos, sizeof(INT32)) != SYNCML_DM_SUCCESS)
    713                 return  SYNCML_DM_IO_FAILURE;
    714 
    715             // No log entry
    716             if(*currentPos == 0)
    717                 return SYNCML_DM_SUCCESS;
    718             // Point to last log entry
    719             this->fileHandle->seek(XPL_FS_SEEK_SET, (int)*currentPos);
    720             ret_code = reader->readByte(lastByte);
    721         }
    722     }
    723     return ret_code;
    724 }
    725 /*==================================================================================================
    726 
    727 Function:	 SyncML_PlugIn_WBXMLLog::playLog
    728 
    729 Description:  Log file playback and remove
    730 
    731 ==================================================================================================*/
    732 SYNCML_DM_RET_STATUS_T SyncML_PlugIn_WBXMLLog::playLog(CPCHAR logFileName)
    733 {
    734 	return SyncML_Log::playLog(logFileName);
    735 }
    736 
    737 /*===============================================================================================
    738 
    739 Function:    SyncML_PlugIn_WBXMLLog::playLog
    740 
    741 Description: This function provides log looping for log playback and recovery
    742          purposes.  If the isRecovery field is set the function performs
    743          calls to recovery functions for the log entries in the log file.
    744          Otherwise, the function does log playback to the Tree and node
    745          manager.
    746 
    747 Returns:     SYNCML_DM_IO_FAILURE     - could not perform an I/O operation
    748          SYNCML_DM_LOG_CORRUPT    - there was an invalid byte read
    749          SYNCML_DM_SUCCESS
    750          SYNCML_DM_FILE_NOT_FOUND - could not find the log file
    751 
    752 ==================================================================================================*/
    753 SYNCML_DM_RET_STATUS_T
    754 SyncML_PlugIn_WBXMLLog::playLog()
    755 {
    756     SYNCML_DM_RET_STATUS_T ret_code = SYNCML_DM_SUCCESS;
    757     SYNCML_DM_COMMAND_T cmdType = SYNCML_DM_NO_COMMAND;
    758     DMBuffer cmdURI;
    759     BOOLEAN isLast = TRUE;
    760     DMAddNodeProp props;
    761     INT32 currentRecordPos = 0;
    762 
    763     UINT8 bYte;
    764     SYNCML_DM_URI_RESULT_T attribute;
    765 
    766     if((fileHandle == NULL))
    767          return SYNCML_DM_FAIL;
    768 
    769     if(reader == NULL)
    770    {		 reader = new SyncML_DM_WBXMLReader(this->fileHandle);
    771 
    772 		 if(reader == NULL)
    773 			 return SYNCML_DM_DEVICE_FULL;
    774    }
    775   if(this->fileHandle->seek(XPL_FS_SEEK_END, 0) != SYNCML_DM_SUCCESS)
    776 	  ret_code = SYNCML_DM_IO_FAILURE;
    777 
    778    prevRecord = this->fileHandle->position();
    779 
    780     if((ret_code=gotoLastRecord(reader,&bYte, &currentRecordPos)) != SYNCML_DM_SUCCESS)
    781        return ret_code;
    782 
    783     // No log entry
    784     if(currentRecordPos == 0)
    785         return SYNCML_DM_SUCCESS;
    786 
    787     while(1)
    788     {
    789         if(bYte == SyncML_DM_WBXMLArchive::END_TAG)
    790         {
    791             /* Signifies the end of the log file */
    792             break;
    793         }
    794         else
    795             if(bYte == (SyncML_DM_WBXMLArchive::ENTRY_START_TAG | SyncML_DM_WBXMLArchive::TAG_CONTENT_MASK))
    796             {
    797                 if(reader->readOneLogRecord(&cmdType, &cmdURI, &attribute,&props,&bYte) != SYNCML_DM_SUCCESS)
    798                 {
    799                     ret_code = SYNCML_DM_IO_FAILURE;
    800                     goto PlayFinished;
    801                 }
    802 
    803                 ret_code = playbackOneRecord(cmdType,(const char *)cmdURI.getBuffer(),attribute,&props);
    804 
    805 #ifdef TEST_DM_RECOVERY
    806                 if ((power_fail_point != NULL) && (DmStrcmp(power_fail_point, "PLUGIN_PF5") == 0))
    807                 {
    808                     printf("Type Ctrl-C to simulate Power Fail ...\n");
    809                     sleep(30);
    810                 }
    811 #endif
    812 
    813                 if(ret_code == SYNCML_DM_IO_FAILURE)
    814                 {
    815                     if(!isLast)
    816                         break;
    817                 }
    818                 isLast = FALSE;
    819                 // Go to previous entry
    820                 if(this->fileHandle->seek(XPL_FS_SEEK_SET, currentRecordPos-2 * sizeof(INT32)) != SYNCML_DM_SUCCESS)
    821                 {
    822                     ret_code = SYNCML_DM_IO_FAILURE;
    823                     goto PlayFinished;
    824                 }
    825                 // Last log entry position
    826                 if(this->fileHandle->read((UINT8 *)&currentRecordPos, sizeof(INT32)) != SYNCML_DM_SUCCESS)
    827                     return  SYNCML_DM_IO_FAILURE;
    828 
    829                 // No more log entry
    830                 if(currentRecordPos == 0)
    831                     break;
    832 
    833                 // Goto the entry
    834                 if(this->fileHandle->seek(XPL_FS_SEEK_SET, currentRecordPos) != SYNCML_DM_SUCCESS)
    835                 {
    836                     ret_code = SYNCML_DM_IO_FAILURE;
    837                     goto PlayFinished;
    838                 }
    839                 // Read the first byte of data looking for an ENTRY_START_TAG
    840                 if(reader->readByte(&bYte) != SYNCML_DM_SUCCESS)
    841                 {
    842                     ret_code = SYNCML_DM_IO_FAILURE;
    843                     goto PlayFinished;
    844                 }
    845 
    846             }
    847     }
    848 
    849     PlayFinished:
    850 
    851     UnInitLog();
    852     return ret_code;
    853 }
    854 /*=============================================================================================
    855 
    856 Function:    SyncML_DM_WBXMLLog::performRecovery
    857 
    858 Description: The function arguments are the command type and the full URI
    859          including the query and special case extensions (e.g. http://hi.com?ACL=*).
    860 
    861 Returns:    SYNCML_DM_SUCCES
    862             SYNCML_DM_FAIL
    863             SYNCML_DM_IO_FAILURE
    864 
    865 Notes:
    866 
    867 =============================================================================================*/
    868 SYNCML_DM_RET_STATUS_T
    869 SyncML_PlugIn_WBXMLLog::playbackOneRecord(SYNCML_DM_PLUGIN_COMMAND_T commandType,
    870                                            CPCHAR pbURI,
    871                                            SYNCML_DM_PLUGIN_COMMAND_ATTRIBUTE_T attribute,
    872                                            DMAddNodeProp* props)
    873 
    874 {
    875     PDmtRWPluginNode ptrNode = NULL;
    876     PDmtNode ptrDmtNode;
    877     DmtData oData;
    878     SYNCML_DM_RET_STATUS_T dm_stat = SYNCML_DM_SUCCESS;
    879 
    880     if(pluginTree == NULL)
    881          return SYNCML_DM_FAIL;
    882 
    883     /* Call the recovery functions */
    884     switch(commandType)
    885     {
    886         case SYNCML_DM_PLUGIN_ADD:
    887         {
    888 		dm_stat =  dmBuildData(props->m_nFormat, props->m_oData, oData);
    889 		if ( dm_stat != SYNCML_DM_SUCCESS )
    890 				return dm_stat;
    891 
    892             if (props->m_nFormat == SYNCML_DM_FORMAT_NODE)
    893             {
    894                 DMStringVector oChildren;
    895                 DmStrToStringVector((CPCHAR)props->m_oData.getBuffer(),props->m_oData.getSize(), oChildren, '/');
    896 
    897                 dm_stat = ((DmtRWPluginTree *)this->pluginTree)->CreateInteriorNodeInternal(pbURI, ptrDmtNode, oChildren);
    898             }
    899             else
    900             {
    901 #ifdef LOB_SUPPORT
    902 		boolean isESN = (props->m_nFlags & DMNode::enum_NodeESN) != 0;
    903                 dm_stat = ((DmtRWPluginTree *)this->pluginTree)->CreateLeafNodeInternal(pbURI, ptrDmtNode, oData, isESN);
    904 		 if(dm_stat == SYNCML_DM_SUCCESS)
    905 		 {
    906 			// Restore ESN data
    907 			if(isESN)
    908 			{
    909 	                ptrNode = (DmtRWPluginNode *) ((DmtNode *)ptrDmtNode);
    910 			   dm_stat = ptrNode->RestoreESNData(props->getESNFileName());
    911 			}
    912 		 }
    913 #else
    914                 dm_stat = ((DmtRWPluginTree *)this->pluginTree)->CreateLeafNodeInternal(pbURI, ptrDmtNode, oData);
    915 #endif
    916             }
    917            break;
    918         }
    919 
    920         case SYNCML_DM_PLUGIN_ADD_CHILD:
    921             dm_stat = ((DmtRWPluginTree *)this->pluginTree)->LinkToParentNode(pbURI);
    922             break;
    923 
    924         case SYNCML_DM_PLUGIN_DELETE:
    925             dm_stat = ((DmtRWPluginTree *)this->pluginTree)->DeleteNode(pbURI);
    926             break;
    927 
    928         case SYNCML_DM_PLUGIN_REPLACE:
    929             dm_stat = ((DmtRWPluginTree *)this->pluginTree)->GetNode(pbURI, ptrDmtNode);
    930             if ( dm_stat == SYNCML_DM_SUCCESS )
    931             {
    932                 ptrNode = (DmtRWPluginNode *) ((DmtNode *)ptrDmtNode);
    933                 if(ptrNode != NULL)
    934                 {
    935 
    936                     switch( attribute)
    937                     {
    938                         case SYNCML_DM_PLUGIN_COMMAND_ON_NODE:
    939 				  {
    940 				  	DmtData curData;
    941 				  	 dm_stat = ptrNode->GetValue(curData);
    942 					 dm_stat =	dmBuildData(curData.GetType(), props->m_oData, oData);
    943 					 if ( dm_stat != SYNCML_DM_SUCCESS )
    944 						 return dm_stat;
    945 
    946                             	dm_stat = ptrNode->SetValue(oData);
    947                         	 }
    948                            break;
    949 
    950                         case SYNCML_DM_PLUGIN_COMMAND_ON_NAME_PROPERTY:
    951                             dm_stat = ptrNode->Rename(props->getName());
    952                             break;
    953 
    954                         case SYNCML_DM_PLUGIN_COMMAND_ON_TITLE_PROPERTY:
    955                             dm_stat = ptrNode->SetTitle(props->getTitle());
    956                             break;
    957 #ifdef LOB_SUPPORT
    958 			     case	SYNCML_DM_PLUGIN_COMMAND_ON_LOB_PROPERTY:
    959 			 	 dm_stat = ptrNode->RestoreESNData(props->getESNFileName());
    960 				 break;
    961 #endif
    962 				default:
    963 					break;
    964                     }
    965                 }
    966              }
    967              break;
    968 
    969          default:
    970          /* recovery_status has already been initialized to fail */
    971          break;
    972    }
    973 
    974    return dm_stat;
    975 
    976 }
    977