/*
* Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "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: A task to update all Feeds.
*
*/
#include <folderattributes.h>
#include "FeedsDatabase.h"
#include "FeedsServer.h"
#include <leaktracker.h>
#include "Logger.h"
#include "PackedFeed.h"
#include "PackedFolder.h"
#include "UpdateAllFeedsTask.h"
#include <SysUtil.h>
// -----------------------------------------------------------------------------
// CUpdateAllFeedsTask::NewL
//
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CUpdateAllFeedsTask* CUpdateAllFeedsTask::NewL(CFeedsServer& aFeedsServer,
TInt aFolderListId, MUpdateAllFeedsTaskObserver& aObserver)
{
CUpdateAllFeedsTask* self = new (ELeave) CUpdateAllFeedsTask(aFeedsServer,
aFolderListId, aObserver, EFalse);
CleanupStack::PushL(self);
self->ConstructL();
CleanupStack::Pop();
return self;
}
// -----------------------------------------------------------------------------
// CUpdateAllFeedsTask::NewL
//
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CUpdateAllFeedsTask* CUpdateAllFeedsTask::NewL(CFeedsServer& aFeedsServer,
TInt aFolderListId, const RArray<TInt>& aFeedIds, MUpdateAllFeedsTaskObserver& aObserver)
{
CUpdateAllFeedsTask* self = new (ELeave) CUpdateAllFeedsTask(aFeedsServer,
aFolderListId, aObserver, ETrue);
CleanupStack::PushL(self);
self->ConstructL();
for (TInt i = 0; i < aFeedIds.Count(); i++)
{
// Add it to the list of entries to update (duplicate ids are ignored).
(void) self->iFeedIds.InsertInOrder(aFeedIds[i]);
}
CleanupStack::Pop();
return self;
}
// -----------------------------------------------------------------------------
// CUpdateAllFeedsTask::CUpdateAllFeedsTask
// C++ default constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
//
CUpdateAllFeedsTask::CUpdateAllFeedsTask(CFeedsServer& aFeedsServer,
TInt aFolderListId, MUpdateAllFeedsTaskObserver& aObserver, TBool aSelected):
CTask(aFeedsServer), iLeakTracker(CLeakTracker::EUpdateAllFeedsTask),
iObserver(aObserver), iFolderListId(aFolderListId), iSelected(aSelected)
{
}
// -----------------------------------------------------------------------------
// CUpdateAllFeedsTask::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CUpdateAllFeedsTask::ConstructL()
{
BaseConstructL(ETrue);
iCheckDiskSpace = CCheckDiskSpace::NewL(this);
iCheckDiskSpace->StartListening();
}
// -----------------------------------------------------------------------------
// CUpdateAllFeedsTask::~CUpdateAllFeedsTask
// Deconstructor.
// -----------------------------------------------------------------------------
//
CUpdateAllFeedsTask::~CUpdateAllFeedsTask()
{
iFeedIds.Close();
delete iUpdateFeedTask;
delete iCheckDiskSpace;
iCheckDiskSpace = NULL;
}
// -----------------------------------------------------------------------------
// CUpdateAllFeedsTask::StartTaskL.
//
// Starts the task.
// -----------------------------------------------------------------------------
//
void CUpdateAllFeedsTask::StartTaskL()
{
TInt drive( EDriveC );
TBool isSpace( EFalse );
RFs rfs;
User::LeaveIfError(rfs.Connect());
CleanupClosePushL(rfs);
TRAP_IGNORE( isSpace = !SysUtil::DiskSpaceBelowCriticalLevelL(
&rfs,
KMinFreebytes,
drive ));
CleanupStack::PopAndDestroy(); //rfs
// Abort the updation of feeds under low memory.
if(!isSpace)
{
iObserver.UpdateAllFeedsCompleted(KErrNoMemory);
return;
}
// Extract all of the ids if not selected update.
if ( !iSelected )
{
if( iFeedIds.Count() != 0 )
{
FEED_LOG1(_L("Feeds"), _L("Feeds_Errors.log"),
EFileLoggingModeAppend, _L("CUpdateAllFeedsTask::StartTaskL iFeedIds count is %d when updating all"),
iFeedIds.Count());
}
iFeedsServer.Database().AllFeedIdsL( iFeedIds, iFolderListId );
}
// Otherwise just use the feed ids already in iFeedIds.
// Start the first update.
UpdateNextFeedL();
}
// -----------------------------------------------------------------------------
// CUpdateAllFeedsTask::StartWait
//
// Notifies the observer that the UrlHandler is about to start a lengthy operation.
// In response the observer could display somekind of status indicator.
// -----------------------------------------------------------------------------
//
void CUpdateAllFeedsTask::StartWait()
{
//iObserver.StartWait();
}
// -----------------------------------------------------------------------------
// CUpdateAllFeedsTask::Completed
//
// Called upon completion of the task.
// -----------------------------------------------------------------------------
//
void CUpdateAllFeedsTask::Completed(CPackedFeed* aPackedFeed, const TDesC& aFeedUrl,TInt aFeedId,
TInt aStatusCode)
{
TInt err;
// Delete the task.
iUpdateFeedTask->AutoDelete();
iUpdateFeedTask = NULL;
// A new packed feed is ready update the database.
if (aPackedFeed != NULL)
{
// Update the database.
TRAP_IGNORE(iFeedsServer.Database().UpdateFeedL(*aPackedFeed, aFeedUrl,aFeedId, iFolderListId));
iFeedIds.Remove(iNextFeedIndex);
delete aPackedFeed;
}
else
{
iFeedIds.Remove(iNextFeedIndex);
}
if(aStatusCode != KErrCancel && aStatusCode != KErrNoMemory)
{
// Update the database.
TRAP_IGNORE(iFeedsServer.Database().UpdateFeedStatusL(aFeedId,aStatusCode));
}
// Stop updating if a fatal error ocurrs.
// TODO: What other errors should stop this?
if ((aStatusCode == KErrCancel) || (aStatusCode == KErrNoMemory))
{
iObserver.UpdateAllFeedsCompleted(aStatusCode);
}
// Otherwise start the next update. Note: this is done even if the last
// update failed.
else
{
TRAP(err, UpdateNextFeedL());
// Just stop updating if an error occurred.
if (err != KErrNone)
{
iObserver.UpdateAllFeedsCompleted(err);
}
}
}
// -----------------------------------------------------------------------------
// CUpdateAllFeedsTask::UpdateNextFeed
//
// Starts the update of the next feed.
// -----------------------------------------------------------------------------
//
void CUpdateAllFeedsTask::UpdateNextFeedL()
{
TBool done = EFalse;
// TODO: Allow several feeds to be updated at the same time.
while (!done)
{
// Update the next feed.
if (iNextFeedIndex < iFeedIds.Count())
{
HBufC* feedUrl = NULL;
if(iFeedIds[iNextFeedIndex] > 0)
{
// Get feed's url from the datbase.
(void) iFeedsServer.Database().UrlFromFeedIdL(
iFeedIds[iNextFeedIndex], feedUrl);
User::LeaveIfNull(feedUrl);
CleanupStack::PushL(feedUrl);
// Create a new task to update the feed.
iUpdateFeedTask = CUpdateFeedTask::NewL(iFeedsServer,
*feedUrl,iFeedIds[iNextFeedIndex], *this);
TRAPD(err, iUpdateFeedTask->StartTaskL());
// Done if the task was started.
if (err == KErrNone)
{
done = ETrue;
}
// Otherwise the task wasn't started so delete it.
else
{
if(err != KErrCancel && err != KErrNoMemory)
{
iFeedsServer.Database().UpdateFeedStatusL(iFeedIds[iNextFeedIndex],err);
}
delete iUpdateFeedTask;
iUpdateFeedTask = NULL;
}
CleanupStack::PopAndDestroy(feedUrl);
}
}
// Otherwise notify the observer that there are no more feeds to update.
else
{
#if defined(_DEBUG)
iFeedsServer.Database().DebugPrintItemTableL();
#endif
iObserver.UpdateAllFeedsCompleted(KErrNone);
done = ETrue;
}
}
}
// -----------------------------------------------------------------------------
// CUpdateAllFeedsTask::AddFeedL
//
// return integer
// -----------------------------------------------------------------------------
//
TInt CUpdateAllFeedsTask::AddFeedL( RArray<TInt> aFeedIds)
{
TBool taskRunning = EFalse;
if(iFeedIds.Count())
{
taskRunning = ETrue;
}
for(TInt i=0 ; i< aFeedIds.Count(); i++)
{
if( iFeedIds.Find(aFeedIds[i]) < 0 )
{
iFeedIds.Append(aFeedIds[i]);
}
}
if(!taskRunning)
{
iNextFeedIndex = 0;
UpdateNextFeedL();
}
return KErrNone;
}
// -----------------------------------------------------------------------------
// CUpdateAllFeedsTask::HttpConnection
//
// return connection
// -----------------------------------------------------------------------------
//
CHttpConnection& CUpdateAllFeedsTask::HttpConnection()
{
return iObserver.HttpConnection();
}
// -----------------------------------------------------------------------------
// CUpdateAllFeedsTask::UpdateAllFeedsCompleted
//
// return connection
// -----------------------------------------------------------------------------
//
void CUpdateAllFeedsTask::UpdateAllFeedsCompleted(TInt aStatusCode)
{
iObserver.UpdateAllFeedsCompleted(aStatusCode);
}
// -----------------------------------------------------------------------------
// CCheckDiskSpace::NewL
//
// Two-phased constructor.
// -----------------------------------------------------------------------------
CCheckDiskSpace* CCheckDiskSpace::NewL(CUpdateAllFeedsTask* aUpdateAllFeedsTask)
{
CCheckDiskSpace* self = new (ELeave) CCheckDiskSpace();
CleanupStack::PushL(self);
self->ConstructL(aUpdateAllFeedsTask);
CleanupStack::Pop();
return self;
}
// -----------------------------------------------------------------------------
// CCheckDiskSpace::~CCheckDiskSpace
//
// Destructor
// -----------------------------------------------------------------------------
CCheckDiskSpace::~CCheckDiskSpace()
{
if(iIsListening)
{
Cancel();
iIsListening = EFalse;
}
iRfs.Close();
}
// -----------------------------------------------------------------------------
// CCheckDiskSpace::ConstructL
//
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
void CCheckDiskSpace::ConstructL(CUpdateAllFeedsTask* aUpdateAllFeedsTask)
{
CActiveScheduler::Add(this);
iUpdateAllFeedsTask = aUpdateAllFeedsTask;
User::LeaveIfError(iRfs.Connect());
}
// -----------------------------------------------------------------------------
// CCheckDiskSpace::CCheckDiskSpace
//
//C++ default constructor can NOT contain any code that
// might leave.
// -----------------------------------------------------------------------------
CCheckDiskSpace::CCheckDiskSpace():CActive(EPriorityStandard ), iIsListening(EFalse)
{
}
// -----------------------------------------------------------------------------
// CCheckDiskSpace::RunL
//
// To Receive event from Subscribe and publish server and
// based on the C: drive memory.
// -----------------------------------------------------------------------------
void CCheckDiskSpace::RunL()
{
if(iStatus == KErrNone)
{
TInt drive( EDriveC );
TBool isSpace( EFalse );
TRAP_IGNORE( isSpace = !SysUtil::DiskSpaceBelowCriticalLevelL(
&iRfs,
KMinFreebytes,
drive ));
if(!isSpace)
{
iUpdateAllFeedsTask->UpdateAllFeedsCompleted(KErrNoMemory);
}
else
{
StartListening();
}
}
else
{
iIsListening = EFalse;
}
}
// -----------------------------------------------------------------------------
// CCheckDiskSpace::RunError
//
// -----------------------------------------------------------------------------
void CCheckDiskSpace::RunError()
{
}
// -----------------------------------------------------------------------------
// CCheckDiskSpace::DoCancel
//
// -----------------------------------------------------------------------------
void CCheckDiskSpace::DoCancel()
{
iRfs.NotifyDiskSpaceCancel(iStatus);
}
// -----------------------------------------------------------------------------
// CCheckDiskSpace::StartListening
//
// This function subscribe to receive events on C: drive memory activites.
// -----------------------------------------------------------------------------
void CCheckDiskSpace::StartListening()
{
if(!IsActive())
{
TInt drive( EDriveC );
iRfs.NotifyDiskSpace( KMinFreebytes, drive, iStatus);
iIsListening = ETrue;
SetActive();
}
}