/** * Copyright Mikael Högdahl - triyana@users.sourceforge.net * * This source is distributed under the terms of the Q Public License version 1.0, * created by Trolltech (www.trolltech.com). */ #include "MHFileTransaction.h" #include "MHFile.h" #include "MHString.h" #include "MHVector.h" #include "MHUtil.h" MHFileTransaction* MHFileTransaction::aaTransaction = 0; /** * */ MHFileTransaction::MHFileTransaction () { aOrgFiles = new MHVector (); aNewFiles = new MHVector (); } /** * */ MHFileTransaction::~MHFileTransaction () { aOrgFiles->Erase (); aNewFiles->Erase (); delete aOrgFiles; delete aNewFiles; } /** * */ void MHFileTransaction::Begin () { if (MHFileTransaction::aaTransaction) throw "MHFileTransaction::Begin Exception, transaction already in progress"; MHFileTransaction::aaTransaction = new MHFileTransaction (); } /** * */ void MHFileTransaction::Check (bool rollback) { // Rename all original files to backup names for (int f = 0; f < aOrgFiles->Size(); f++) { MHString* file1 = (MHString*) aOrgFiles->Get(f); MHString* file2 = (MHString*) aNewFiles->Get(f); MHString* file3 = new MHString(*file1); if (rollback) { *file3 += ".tmp.tmp"; remove (file1->Get()); rename (file3->Get(), file1->Get()); } remove (file2->Get()); delete file3; } aOrgFiles->Erase (); aNewFiles->Erase (); } /** * */ bool MHFileTransaction::commit2 () { int f; // Rename all original files to backup names for (f = 0; f < aOrgFiles->Size(); f++) { MHString* file1 = (MHString*) aOrgFiles->Get(f); MHString* file2 = new MHString(*file1); int size1 = MHFile::Size (file1->Get()); bool exist1 = MHFile::Exist (file1->Get()); #ifdef BUGG if (*file1 == "d") { printf ("Delete file d.tmp then press return to continue: "); getc(stdin); } #endif if (size1 >= 0) { *file2 += ".tmp.tmp"; if (exist1 == true && rename (file1->Get(), file2->Get()) != 0) { Check (false); delete file2; return false; } } delete file2; } // Rename all new file to original name for (f = 0; f < aOrgFiles->Size(); f++) { MHString* file1 = (MHString*) aOrgFiles->Get(f); MHString* file2 = (MHString*) aNewFiles->Get(f); if (rename (file2->Get(), file1->Get()) != 0) { Check (true); return false; } } // Delete all tmp2 backup files for (f = 0; f < aOrgFiles->Size(); f++) { MHString* file1 = (MHString*) aOrgFiles->Get(f); *file1 += ".tmp.tmp"; remove (file1->Get()); } aOrgFiles->Erase (); aNewFiles->Erase (); return true; } /** * */ bool MHFileTransaction::Commit () { if (!MHFileTransaction::aaTransaction) throw "MHFileTransaction::Commit Exception, no transaction in progress"; bool ret = MHFileTransaction::aaTransaction->commit2(); delete MHFileTransaction::aaTransaction; MHFileTransaction::aaTransaction = 0; return ret; } /** * Get filename. If transaction is under way return the tmp name otherwise return the original name */ void MHFileTransaction::getFileName (const char* orgName, MHString* newName, bool read) { MHString* org = new MHString (orgName); // Check if file exist, if so return existing tmp name for (int f = 0; f < aOrgFiles->Size(); f++) { MHString* file = (MHString*) aOrgFiles->Get(f); if (*file == *org) { MHString* file2 = (MHString*) aNewFiles->Get(f); *newName = *file2; delete org; return; } } MHString* newTmp = new MHString (*org); *newTmp += ".tmp"; if (read) { // File name is wanted for read operation if (MHFile::Exist (newTmp->Get())) *newName = *newTmp; else *newName = orgName; delete org; delete newTmp; } else { // File name is wanted for write operation aOrgFiles->Push (org); aNewFiles->Push (newTmp); *newName = *newTmp; } } /** * */ void MHFileTransaction::rollback2 () { // Remove all new files for (int f = 0; f < aOrgFiles->Size(); f++) { MHString* file1 = (MHString*) aOrgFiles->Get(f); MHString* file2 = new MHString(*file1); *file2 += ".tmp"; if (MHFile::Size (file2->Get()) >= 0) remove (file2->Get()); delete file2; } aOrgFiles->Erase (); aNewFiles->Erase (); } /** * */ void MHFileTransaction::Rollback () { if (!MHFileTransaction::aaTransaction) throw "MHFileTransaction::Rollback Exception, no transaction in progress"; MHFileTransaction::aaTransaction->rollback2(); delete MHFileTransaction::aaTransaction; MHFileTransaction::aaTransaction = 0; }