VError DB4DJournalParser::NextOperation( uLONG8 &outOperation, uLONG8 *outGlobalOperation, CDB4DJournalData **outJournalData ) { VError error = VE_OK; RecordHeader recHeader; if ( outJournalData ) *outJournalData = NULL; outOperation = fCurrentOperation; sLONG8 globaloperation = 0; if ( fFileStream ) { uLONG operationTag; error = fFileStream->GetLong(operationTag); if ( error == VE_OK ) { if ( operationTag == kTagLogDB4D ) { sLONG8 contextID; DB4D_LogAction logAction; sLONG len; sLONG8 curpos; error = fFileStream->GetLong8(globaloperation); if ( error == VE_OK ) { error = fFileStream->GetLong(len); } if ( !outJournalData ) { error = fFileStream->SetPosByOffset( len - 24 );//- 4 /*Tag*/ - 8 /*Operation#*/- 4 /*len*/ - 4 /*len at the end*/ - 4 /*tag at the end*/ } else { if ( error == VE_OK ) error = fFileStream->GetLong((uLONG&)logAction); if ( error == VE_OK ) error = fFileStream->GetLong8(contextID); uLONG8 timeStamp; if (error == VE_OK) error = fFileStream->GetLong8(timeStamp); if (error == VE_OK) { switch (logAction) { case DB4D_Log_OpenData: case DB4D_Log_CloseData: case DB4D_Log_StartBackup: case DB4D_Log_StartTrans: case DB4D_Log_Commit: case DB4D_Log_RollBack: { *outJournalData = new VDB4DJournalData(globaloperation, logAction,contextID, GetContextExtraData( contextID),timeStamp); } break; case DB4D_Log_CloseContext: { *outJournalData = new VDB4DJournalData(globaloperation, logAction,contextID, GetContextExtraData( contextID),timeStamp); fContextExtraByID.erase(contextID); } break; case DB4D_Log_CreateRecord: case DB4D_Log_ModifyRecord: { VUUID xTableID; if ( error == VE_OK ) error = recHeader.ReadFromStream(fFileStream); if ( error == VE_OK ) if ( !recHeader.Match(DBOH_Record) ) error = VE_DB4D_WRONGRECORDHEADER; if ( error == VE_OK ) error = xTableID.ReadFromStream(fFileStream); curpos = fFileStream->GetPos(); if ( error == VE_OK ) { sLONG dataSize = recHeader.GetLen() + sizeof(ChampHeader)*(recHeader.GetNbFields()); error = fFileStream->SetPosByOffset(dataSize); } if ( error == VE_OK ) *outJournalData = new VDB4DJournalData(globaloperation, logAction,contextID, GetContextExtraData( contextID),&recHeader,timeStamp, curpos, fFileStream, xTableID); } break; case DB4D_Log_DeleteBlob: { VString path; sLONG blobnumber; if ( error == VE_OK ) error = fFileStream->GetLong(blobnumber); if (blobnumber == -2) { sLONG lenpath = 0; error = fFileStream->GetLong(lenpath); if (lenpath > 0) { tempBuffer<256> buff(len); error = fFileStream->GetWords((sWORD*)buff.GetPtr(), &lenpath); path.FromBlock(buff.GetPtr(), lenpath * sizeof(UniChar), VTC_UTF_16); } } VUUID xTableID; if ( error == VE_OK ) error = xTableID.ReadFromStream(fFileStream); if ( error == VE_OK ) { VDB4DJournalData* jdata = new VDB4DJournalData(globaloperation, logAction,contextID, GetContextExtraData( contextID),timeStamp, blobnumber ,xTableID); *outJournalData = jdata; if (!path.IsEmpty()) { jdata->SetPath(path); } } } break; case DB4D_Log_DeleteRecord: case DB4D_Log_TruncateTable: { sLONG recordNumber; if ( error == VE_OK ) error = fFileStream->GetLong(recordNumber); /* sLONG tableIndex; if ( error == VE_OK ) error = fFileStream->GetLong(tableIndex); */ VUUID xTableID; if ( error == VE_OK ) error = xTableID.ReadFromStream(fFileStream); if ( error == VE_OK ) *outJournalData = new VDB4DJournalData(globaloperation, logAction,contextID, GetContextExtraData( contextID),timeStamp,recordNumber,xTableID); } break; case DB4D_Log_CreateContextWithUserUUID: { VUUID userID; error = userID.ReadFromStream(fFileStream); if (error == VE_OK) *outJournalData = new VDB4DJournalData(globaloperation, logAction,contextID, GetContextExtraData( contextID),timeStamp,userID); } break; case DB4D_Log_CreateContextWithExtra: { VValueBag *bag = new VValueBag; if (bag != NULL) { // the extra data is always stored in little endian Boolean oldNeedSwap = fFileStream->NeedSwap(); fFileStream->SetLittleEndian(); error = bag->ReadFromStream(fFileStream); fFileStream->SetNeedSwap( oldNeedSwap); if (error == VE_OK) { try { fContextExtraByID[contextID] = bag; } catch(...) { } *outJournalData = new VDB4DJournalData(globaloperation, logAction,contextID, GetContextExtraData( contextID),timeStamp); } } else { error = memfull; } ReleaseRefCountable( &bag); } break; case DB4D_Log_CreateBlob: case DB4D_Log_ModifyBlob: { VString path; sLONG lenblob = 0; sLONG blobNumber; if ( error == VE_OK ) error = fFileStream->GetLong(blobNumber); if (blobNumber == -2) { sLONG lenpath = 0; error = fFileStream->GetLong(lenpath); if (lenpath > 0) { tempBuffer<256> buff(len); error = fFileStream->GetWords((sWORD*)buff.GetPtr(), &lenpath); path.FromBlock(buff.GetPtr(), lenpath * sizeof(UniChar), VTC_UTF_16); } } VUUID xTableID; if ( error == VE_OK ) error = xTableID.ReadFromStream(fFileStream); curpos = fFileStream->GetPos(); if ( error == VE_OK ) { error = fFileStream->GetLong(lenblob); error = fFileStream->SetPosByOffset(lenblob); } if ( error == VE_OK ) { VDB4DJournalData* jdata = new VDB4DJournalData(globaloperation, logAction,contextID, GetContextExtraData( contextID),timeStamp, blobNumber, lenblob, xTableID, curpos, fFileStream); *outJournalData = jdata; if (!path.IsEmpty()) { jdata->SetPath(path); } } } break; case DB4D_Log_SaveSeqNum: { sLONG8 seqnum; if ( error == VE_OK ) error = fFileStream->GetLong8(seqnum); /* sLONG tableIndex; if ( error == VE_OK ) error = fFileStream->GetLong(tableIndex); */ VUUID xTableID; if ( error == VE_OK ) error = xTableID.ReadFromStream(fFileStream); if ( error == VE_OK ) *outJournalData = new VDB4DJournalData(globaloperation, logAction,contextID, GetContextExtraData( contextID), timeStamp, seqnum, xTableID, true); } break; default: assert(false); break; } } } sLONG lenEnd; if ( error == VE_OK ) { error = fFileStream->GetLong(lenEnd); if (len != lenEnd) error = VE_UNIMPLEMENTED; } uLONG operationTagEnd; if (error == VE_OK) { error = fFileStream->GetLong((uLONG&)operationTagEnd); if (operationTagEnd != kTagLogDB4DEnd) error = VE_UNIMPLEMENTED; } } else { error = VE_UNIMPLEMENTED; // bad file } if ( error != VE_OK ) { if ( outJournalData && *outJournalData ) { (*outJournalData)->Release(); *outJournalData = NULL; } } else { outOperation = ++fCurrentOperation; if ( outJournalData && *outJournalData ) { if ( fCurrentData ) fCurrentData->Release(); fCurrentData = *outJournalData; fCurrentData->Retain(); } } } } else { error = VE_UNIMPLEMENTED; // not initialized } if (outGlobalOperation != NULL) *outGlobalOperation = globaloperation; return error; }