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*)¤tPos, 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 *)¤tRecordPos, 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 *)¤tRecordPos, 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, ¤tRecordPos)) != 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 *)¤tRecordPos, 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