diff -r b183ec05bd8c -r 19bba8228ff0 fotaapplication/fotaserver/FotaStorage/src/fotaDiskStorage.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fotaapplication/fotaserver/FotaStorage/src/fotaDiskStorage.cpp Wed Sep 01 12:27:42 2010 +0100 @@ -0,0 +1,545 @@ +/* +* Copyright (c) 2005-2006 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: stores update package to filesystem +* +*/ + + + +// INCLUDE FILES +#include +#include +#include +#include +#include "fotadiskstoragePrivateCRKeys.h" +#include "fotaDiskStorage.h" +#include "fotadebug.h" + +// CONSTANTS +// System Critical Level (128KB) plus 5KB for fota operations. +const TInt KSystemCriticalWorkingspace = 136192; + +// MACROS +#ifdef __EABI__ +#ifndef IMPLEMENTATION_PROXY_ENTRY +typedef TAny* TProxyNewLPtr; +#define IMPLEMENTATION_PROXY_ENTRY(aUid, aFuncPtr) {{aUid},(TProxyNewLPtr)(aFuncPtr)} +#endif +#endif + +// ============================ MEMBER FUNCTIONS ============================= + +// --------------------------------------------------------------------------- +// CFotaDiskStorage::CFotaDiskStorage() +// --------------------------------------------------------------------------- +// +CFotaDiskStorage::CFotaDiskStorage () + { + } + +// --------------------------------------------------------------------------- +// CFotaDiskStorage::NewL() +// --------------------------------------------------------------------------- +// +CFotaDiskStorage* CFotaDiskStorage::NewL() + { + FLOG(_L("CFotaDiskStorage::NewL()")); + CFotaDiskStorage* self = new ( ELeave ) CFotaDiskStorage; + FLOG(_L(" CFotaDiskStorage created at %X "), self); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// --------------------------------------------------------------------------- +// CFotaDiskStorage::ConstructL() +// --------------------------------------------------------------------------- +// +void CFotaDiskStorage::ConstructL() + { + FLOG(_L("CFotaDiskStorage::ConstructL() >>")); + TInt err; + User::LeaveIfError ( iFs.Connect() ); + + // Ensures that fotaserver private dir exists + err = iFs.MkDirAll(KDummyFilePath); + if ( err!=KErrAlreadyExists && err != KErrNone ) + { + FLOG(_L(" created priv dir err %d"),err); + User::Leave ( err ) ; + } + FLOG(_L("CFotaDiskStorage::ConstructL() sessionpath to %S") + , &KDummyFilePath,err); + User::LeaveIfError ( iFs.SetSessionPath ( KDummyFilePath ) ); + + // newdummy remains should not exist now. safety. + err = iFs.Delete ( _L("newdummy") ) ; + if ( err!=KErrNone && err!= KErrNotFound ) User::Leave (err); + + // Get write limit + TInt writelimit( KFileReservationDefaultSize ); + TInt chunksize ( iChunkSize ); + CRepository* centrep( NULL); + TRAP(err, centrep = CRepository::NewL( KCRUidFotaDiskStorage ) ); + if ( centrep ) + { + err = centrep->Get( KFotaDiskSpaceReservationKey, writelimit ); + err = centrep->Get( KFotaDiskSpaceReservationChunkKey, chunksize ); + } + iDummySize = writelimit; + iChunkSize = chunksize; + delete centrep; + + AdjustDummyStorageL(); + FLOG(_L("CFotaDiskStorage::ConstructL() <<")); + } + +// --------------------------------------------------------------------------- +// CFotaDiskStorage::~CFotaDiskStorage () +// --------------------------------------------------------------------------- +// +CFotaDiskStorage::~CFotaDiskStorage () + { + FLOG(_L("CFotaDiskStorage::~CFotaDiskStorage ()")); + iFileWriteStream.Close(); + iFs.Close(); + } + + +// --------------------------------------------------------------------------- +// CFotaDiskStorage::IsPackageStoreSizeAvailableL +// does the pkg fit to reservation or filesystem +// --------------------------------------------------------------------------- +// +CFotaStorage::TFreeSpace CFotaDiskStorage::IsPackageStoreSizeAvailableL(TInt& aSize) + { + CFotaStorage::TFreeSpace isavailable; + TInt swupdSize(0); + TInt dummySize(0); + SpaceAllocatedBySWUPDFilesL( swupdSize, dummySize); + + if ( aSize <= dummySize ) + { + // fits to reservation + isavailable = CFotaStorage::EFitsToReservation; + } + else + { + // doesnt fit to reservation, does it fit to filesystem? + TInt sizeNeededFromFS = aSize - dummySize ; + if ( sizeNeededFromFS < 0 ) sizeNeededFromFS = 0; + TBool critical = SysUtil::FFSSpaceBelowCriticalLevelL( &iFs, sizeNeededFromFS ); + if ( critical ) + { + // how much space would be needed + TVolumeInfo vi; + iFs.Volume(vi,EDriveC); + + TInt neededspace = sizeNeededFromFS - vi.iFree + KSystemCriticalWorkingspace; + FLOG(_L("neededspace = %d vi.iFree = %d "), neededspace , vi.iFree); + FLOG(_L(" neededspace = sizeNeededFromFS - vi.iFree + KSystemCriticalWorkingspace;") ); + //= aSize - vi.iFree; + aSize = neededspace; + isavailable = CFotaStorage::EDoesntFitToFileSystem; + } + else + { + isavailable = CFotaStorage::EFitsToFileSystem; + } + } + TInt fitstodummy = isavailable==CFotaStorage::EFitsToReservation?1:0 ; + TInt fitstoFS = isavailable==CFotaStorage::EFitsToFileSystem?1:0 ; + TInt DoesntFitToFS = isavailable==CFotaStorage::EDoesntFitToFileSystem?1:0 ; + + FLOG(_L("CFotaDiskStorage::IsPackageStoreSizeAvailableL %d<%d (sz vs dummy) => fitstodummy:%d fitstoFS:%d DoesntFitToFS:%d") + ,aSize,dummySize,fitstodummy,fitstoFS,DoesntFitToFS ); + + return isavailable; + } + + +// --------------------------------------------------------------------------- +// CFotaDiskStorage::AdjustDummyStorageL() +// Ensure that total of iDummySize bytes are reserved by .swupd files and +// dummy file. +// --------------------------------------------------------------------------- +// +TInt CFotaDiskStorage::AdjustDummyStorageL ( ) + { + FLOG(_L("CFotaDiskStorage::AdjustDummyStorageL >>")); + // Count size reserved by .swupd files + // CDir* list; + TInt err; + TInt swupdSize(0); + TInt dummySize(0); + RFile dummy; + + TRAP(err,SpaceAllocatedBySWUPDFilesL( swupdSize, dummySize)); + + // Calculate space for dummy file + TInt targetsize = iDummySize - swupdSize; + if ( targetsize<0 ) + { + targetsize=0; + } + + // Reduce dummy file size + if ( dummySize != targetsize || dummySize ==0 ) + { + FLOG(_L(" dummy new size %d (old %d)"), targetsize,dummySize); + + err = dummy.Open(iFs, KDummyFileName, EFileWrite|EFileShareExclusive); + + if (err == KErrNotFound ) + { + User::LeaveIfError(dummy.Replace(iFs, KDummyFileName + , EFileWrite|EFileShareExclusive)); + } + else + if ( err!=KErrNone) User::LeaveIfError (err); + + CleanupClosePushL(dummy); + TInt err= dummy.SetSize (targetsize); + if (err!=KErrNone) + { + FLOG(_L("Error while creating reserved space: %d "),err ); + } + CleanupStack::PopAndDestroy(1); // dummy + } + FLOG(_L("CFotaDiskStorage::AdjustDummyStorageL, reserved file size = %d <<"),targetsize); + return 0; + } + +// --------------------------------------------------------------------------- +// CFotaDiskStorage::OpenUpdatePackageStore +// Open upd pkg store for writing (writes to dummy file). +// --------------------------------------------------------------------------- +TInt CFotaDiskStorage::OpenUpdatePackageStoreL(const TInt aPkgId,TInt aNewDummySize + , RWriteStream*& aPkgStore) + { + FLOG(_L("CFotaDiskStorage::OpenUpdatePackageStore")); + TInt err (KErrNone); + + // Remove reserved memory + RFile tmp; + err = tmp.Open(iFs, KDummyFileName, EFileWrite|EFileShareExclusive); + CleanupClosePushL(tmp); + if ( !err ) + { + FLOG(_L("Removing the reserved memory as download has started"), iDummySize); + tmp.SetSize( KErrNone ); + } + CleanupStack::PopAndDestroy( &tmp ); + // flexible mem handling: increase dummy size to receive over sized package + if (iDummySize < aNewDummySize) + iDummySize = aNewDummySize; + FLOG(_L("Newer dummy size = %d"),iDummySize); + + TBuf swupd; + + swupd.AppendNum(aPkgId); + swupd.Append(_L(".swupd")); + err = iFileWriteStream.Open(iFs, swupd, EFileWrite) ; + if (err == KErrNotFound ) + { + User::LeaveIfError(iFileWriteStream.Replace(iFs, swupd + , EFileWrite)); + } + else + if ( err!=KErrNone) User::LeaveIfError (err); + + //Positioning the seek if the file is already present (in case of resume) + TEntry entry; + TInt size (KErrNone); + err = iFs.Entry(swupd,entry); + if (!err) + size = entry.iSize; + if (size) + { + MStreamBuf* x = iFileWriteStream.Sink(); + TStreamPos pos(0); + TRAPD(err2, pos = x->TellL(MStreamBuf::EWrite)); + + pos+=size; + TRAP(err2, x->SeekL(MStreamBuf::EWrite,pos )); + } + aPkgStore = &iFileWriteStream; + return err; + } + +// --------------------------------------------------------------------------- +// CFotaDiskStorage::GetDownloadedUpdatePackageSizeL +// Gets the downloaded update package size in bytes +// --------------------------------------------------------------------------- + +void CFotaDiskStorage::GetDownloadedUpdatePackageSizeL(const TInt aPkgId, TInt& aSize) + { + FLOG(_L("CFotaDiskStorage::GetDownloadedUpdatePackageSizeL >>")); + aSize = 0; + + TBuf swupd; + + swupd.AppendNum(aPkgId); + swupd.Append(_L(".swupd")); + + TInt err(KErrNone); + TEntry entry; + err = iFs.Entry(swupd,entry); + if (!err) + aSize = entry.iSize; + FLOG(_L("CFotaDiskStorage::GetDownloadedUpdatePackageSizeL,err = %d, aSize = %d <<"),err, aSize); + } + + +// --------------------------------------------------------------------------- +// CFotaDiskStorage::UpdatePackageDownloadComplete +// closes the stream and frees resources +// --------------------------------------------------------------------------- +void CFotaDiskStorage::UpdatePackageDownloadCompleteL(const TInt aPkgId) + { + FLOG(_L("CFotaDiskStorage::UpdatePackageDownloadComplete(const TInt aPkgId)")); + RFile fswupd; + TBuf fn; + TInt err; + iFileWriteStream.Close(); + if(iBytesWritten<1) + { + FLOG(_L(" no bytes received!")); +// User::Leave(KErrNotFound); + return; + } + TBuf swupd; + + swupd.AppendNum(aPkgId); + swupd.Append(_L(".swupd")); + + // open swupd file for reading + err = fswupd.Open(iFs, swupd, EFileWrite|EFileShareExclusive); + FLOG(_L(" open err %d"),err); + if (err == KErrNotFound ) + { + FLOG(_L("swupd not found, creaeting")); + User::LeaveIfError(fswupd.Replace(iFs, swupd + ,EFileWrite|EFileShareExclusive)); + } + else + if ( err!=KErrNone) User::LeaveIfError (err); + CleanupClosePushL(fswupd); + + RFile ND; + User::LeaveIfError ( ND.Replace ( iFs, KDummyFileName, EFileWrite ) ); + CleanupClosePushL ( ND); + CleanupStack::PopAndDestroy(2); // dummies + AdjustDummyStorageL(); + } + +// --------------------------------------------------------------------------- +// CFotaDiskStorage::GetUpdatePackageLocation +// Gets update package location, that is , path. +// --------------------------------------------------------------------------- +void CFotaDiskStorage::GetUpdatePackageLocationL(const TInt aPkgId + , TDes8& aPath ) +{ + TBuf8<20> fn; + fn.AppendNum(aPkgId); + fn.Append(_L8(".swupd")); + TInt pathlength = ((TDesC16)KDummyFilePath).Length(); + HBufC8* path = HBufC8::NewLC( pathlength ); + path->Des().Copy( KDummyFilePath ); + + aPath.Append( path->Des() ); + aPath.Append(fn); + CleanupStack::PopAndDestroy( path ); +} + +// --------------------------------------------------------------------------- +// CFotaDiskStorage::GetUpdatePackageIds +// getupdate package ids +// --------------------------------------------------------------------------- +void CFotaDiskStorage::GetUpdatePackageIdsL(TDes16& aPackageIdList) + { + FLOG(_L("CFotaDiskStorage::GetUpdatePackageIds")); + // Read all .swupd files and parse pkg ids from filenames + TInt err; + CDir* list; + err=iFs.GetDir (_L("*.swupd"), KEntryAttNormal ,ESortByName, list ); + for(int i=0; iCount() ;++i ) + { + TEntry t = (*list)[i]; + TParse p; + TInt16 pkgid; + p.Set(t.iName,NULL,NULL); + TLex lex(p.Name()); + err = lex.Val(pkgid); + FLOG(_L(" %S"),&t.iName); + if(err==KErrNone) + { + TPtrC filename(p.Name()); + FLOG(_L(" pkig found: %d"), pkgid); + TDateTime d = t.iModified.DateTime(); + aPackageIdList.Append (pkgid); + } + } + delete list; + } + +// --------------------------------------------------------------------------- +// CFotaDiskStorage::DeleteUpdatePackageL +// --------------------------------------------------------------------------- +void CFotaDiskStorage::DeleteUpdatePackageL (const TInt aPkgId) + { + FLOG(_L("CFotaDiskStorage::DeleteUpdatePackageL %d >>"),aPkgId); + RFile dummy; + TInt err= dummy.Open(iFs, KDummyFileName , EFileWrite|EFileShareExclusive); + FLOG(_L("Error opening the reserved file...%d"),err); + CleanupClosePushL ( dummy ); + TRAP(err, DoDeleteUpdatePackageL ( dummy, aPkgId, 0 )); + CleanupStack::PopAndDestroy(1); + AdjustDummyStorageL(); + + FLOG(_L("CFotaDiskStorage::DeleteUpdatePackageL %d, err = %d <<"),aPkgId, err); + } + +// --------------------------------------------------------------------------- +// CFotaDiskStorage::DoDeleteUpdatePackageL +// Delete swupd by chunking data to dummy (param) file. Will grow dummy +// independently, but takes already allocated bytes into account. +// --------------------------------------------------------------------------- +void CFotaDiskStorage::DoDeleteUpdatePackageL ( RFile& dummy, TInt aPkgId + , TInt aAlreadyAllocated) + { + // Open swupd file + TInt err; + TBuf8 swupdpath; + TBuf swupdpath16; + GetUpdatePackageLocationL ( aPkgId, swupdpath) ; + swupdpath16.Copy ( swupdpath ); + RFile swupd; + err = swupd.Open( iFs, swupdpath16, EFileWrite ); + if ( err == KErrNotFound ) return; // no need to delete + if ( err != KErrNone ) User::Leave ( err ); + CleanupClosePushL ( swupd ); + + // Reduce dummy size + TInt dummytargetsize = iDummySize - aAlreadyAllocated; + for ( TInt p=0; p<10000 ; ++p ) + { + TInt dsize; + TInt swupdsize(0); + User::LeaveIfError( dummy.Size( dsize ) ); + User::LeaveIfError( swupd.Size( swupdsize) ); + TInt chunk = swupdsize > iChunkSize ? iChunkSize : swupdsize; + + // Ensure that dummy dosnt get oversized + if ( dsize <= dummytargetsize && dsize + chunk >= dummytargetsize ) + chunk = dummytargetsize - dsize; + + // Safety + if ( dsize >= dummytargetsize ) break; + + FLOG(_L(" deleting swupd: dummy %d\t swupd %d\t chunk%d"),dsize + ,swupdsize,chunk); + if (chunk>0) + { + User::LeaveIfError( dummy.SetSize( dsize + chunk ) ); + User::LeaveIfError( swupd.SetSize( swupdsize - chunk ) ); + } + else + break; + } + CleanupStack::PopAndDestroy(1); // swupd + + // Delete swupd (dummy file is big enough now) + err = iFs.Delete ( swupdpath16 ) ; + FLOG(_L("CFotaDiskStorage::DoDeleteUpdatePackageL deleted ,err %d"),err); + if ( err != KErrNone && err != KErrNotFound ) + { + User::Leave ( err ); + } + } + +// --------------------------------------------------------------------------- +// CFotaDiskStorage::SpaceAllocatedBySWUPDFilesL +// Counts space allocated by swupd files +// --------------------------------------------------------------------------- +void CFotaDiskStorage::SpaceAllocatedBySWUPDFilesL( TInt& aSwupdSize, TInt& aDummySize ) + { + CDir* list; + TInt err; + // TInt (0); + aSwupdSize = 0; + aDummySize = 0; + err = iFs.GetDir (_L("*.swupd"), KEntryAttNormal ,ESortByName, list ); + User::LeaveIfError(err); + CleanupStack::PushL ( list ); + + // get sizes of swupd files + for(int i=0; iCount() ;++i ) + { + TEntry t = (*list)[i]; + TParse p; + TInt16 pkgid; + + p.Set(t.iName,NULL,NULL); + TLex lex(p.Name()); + err = lex.Val(pkgid); + if(err==KErrNone) + { + TPtrC filename(p.Name()); + aSwupdSize += t.iSize; + } + } + CleanupStack::PopAndDestroy( list ); + + // get size of dummyfile + err = iFs.GetDir (KDummyFileName, KEntryAttNormal ,ESortByName, list ); + User::LeaveIfError(err); + CleanupStack::PushL ( list ); + if ( list->Count() >0 ) + { + TEntry t = (*list)[0]; + aDummySize = t.iSize; + } + CleanupStack::PopAndDestroy( list ); + FLOG(_L("CFotaDiskStorage::SpaceAllocatedBySWUPDFilesL dummy:%d swupd:%d") + ,aDummySize,aSwupdSize); + } + +// --------------------------------------------------------------------------- +// Global implementation uid array +// Define the Implementation UIDs for JP2K decoder. +// (other items were commented in a header). +// --------------------------------------------------------------------------- +// +const TImplementationProxy ImplementationTable[] = +{ + // implementation_uid + IMPLEMENTATION_PROXY_ENTRY( 0x10207385 , CFotaDiskStorage::NewL ) +}; + +// ========================== OTHER EXPORTED FUNCTIONS ========================= + +// --------------------------------------------------------------------------- +// ImplementationGroupProxy Implements proxy interface for ECom +// Exported proxy for instantiation method resolution. +// --------------------------------------------------------------------------- +// +EXPORT_C const TImplementationProxy* ImplementationGroupProxy( //lint !e714 Used by ECom + TInt& aTableCount ) // Number of tables + { + aTableCount = sizeof( ImplementationTable ) / sizeof( + TImplementationProxy ); + return ImplementationTable; + }