ximpfw/presence/srcpresencecache/presencecacheserver/presencecachesession.cpp
author Pat Downey <patd@symbian.org>
Wed, 01 Sep 2010 12:27:45 +0100
branchRCL_3
changeset 22 113b91e0a2ad
parent 21 cfd5c2994f10
permissions -rw-r--r--
Revert incorrect RCL_3 drop: Revision: 201033 Kit: 201035

/*
* Copyright (c) 2007, 2008 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:  Impementation for Presence Cache Server session
*
*/


// INCLUDE FILES
#include <presenceobjectfactory.h>
#include <personpresenceinfo.h>
#include <presencebuddyinfo.h>
#include <presencebuddyinfolist.h>
#include <presenceinfofieldcollection.h>

#include "presencecachesession.h"
#include "presencecacheserver.h"
#include "ximptrace.h"
#include "ximpobjecthelpers.h"
#include "presenceinfoimp.h"
#include "presencebuddyinfolistimp.h"
#include "presencebuddyinfoimp.h"
#include "ximpidentityimp.h"

#include "presencecacheservicestore.h"
#include "presencecachebuddystore.h"

//Include Cache server namespace
using namespace NCacheSrv;


// ---------------------------------------------------------------------------
// CPresenceCacheSession::NewL()
// ---------------------------------------------------------------------------
//
CPresenceCacheSession* CPresenceCacheSession::NewL( CPresenceCacheServer& aServer )
    {
    CPresenceCacheSession* self = CPresenceCacheSession::NewLC( aServer );
    CleanupStack::Pop(self);
    return self;    
    }
    
// ---------------------------------------------------------------------------
// CPresenceCacheSession::NewLC()
// ---------------------------------------------------------------------------
//
CPresenceCacheSession* CPresenceCacheSession::NewLC( CPresenceCacheServer& aServer )
    {
    CPresenceCacheSession* self = new ( ELeave ) CPresenceCacheSession( aServer );
    CleanupStack::PushL(self);
    self->ConstructL();
    return self;    
    }

// ---------------------------------------------------------------------------
// CPresenceCacheSession::~CPresenceCacheSession()
// ---------------------------------------------------------------------------
//
CPresenceCacheSession::~CPresenceCacheSession()
    {
    if(iDataPack)
        delete iDataPack;
    if(iDataPackAsync)
        delete iDataPackAsync;
    if(iDataPackNotifier)
        delete iDataPackNotifier;
    if(iBuddypresInfoList)
        delete iBuddypresInfoList;
    if(iActiveHelper)
        delete iActiveHelper;
    iServer.DecrementSessions();
    RemoveMySubscriptions(); // remove all subscriptions subscribed by this session
    iSubscribedStores.Close();
    TRACE_1( _L("CPresenceCacheSession[%d]::~CPresenceCacheSession()"), this );
    }


// ---------------------------------------------------------------------------
// CPresenceCacheSession::ServiceL()
// ---------------------------------------------------------------------------
//
void CPresenceCacheSession::ServiceL( const RMessage2& aMessage )
    {
    switch ( aMessage.Function() )
        {
        case NRequest::EPrepReadPresenceInfoSync:
            HandlePrepReadPresenceInfoSyncL(aMessage);
            break;
            
        case NRequest::EGetLastPreparedPacket:
            HandleGetLastPreparedPacketL(aMessage);
            break;
            
        case NRequest::EGetLastAsyncPreparedPacket:
            HandleGetLastPreparedAsyncPacketL(aMessage);
            break;
            
        case NRequest::EBuddyCountInAllServices:
            HandleBuddyCountInAllServices(aMessage);
            break;
            
        case NRequest::EBuddyCountInService:
            HandleBuddyCountInService(aMessage);
            break;
            
        case NRequest::EGetServiceCount:
            HandleGetServiceCount(aMessage);
            break;
            
        case NRequest::EDeleteService:
            HandleDeleteService(aMessage);
            break;
            
        case NRequest::EDeletePresence:
            HandleDeletePresence(aMessage);
            break;
            
        case NRequest::ECancelAsyncOperation:
            HandleCancel(aMessage);
            break;

        case NRequest::EWritePresenceInfoSync:
            HandleWritePresenceInfoSyncL(aMessage);
            break;

        case NRequest::EWritePresenceInfoAsync:
            HandleWritePresenceInfoAsyncL(aMessage);
            break;
            
        case NRequest::EPrepReadAllBuddiesPresenceInService:
            HandlePrepReadAllBuddiesPresenceInService(aMessage);
            break;
            
        case NRequest::ESubscribeBuddyPresenceChange:// 0:aService.iUid, 1:myIdPack
            HandleSubscribeBuddyPresenceChange(aMessage);
            break;
        
        case NRequest::EUnSubscribeBuddyPresenceChange: // 0:aService.iUid, 1:myIdPack
            HandleUnSubscribeBuddyPresenceChange(aMessage);
            break;
        
        case NRequest::EGetLastNotifiedtPacket: // 0:&ptrBuf
            HandleGetLastNotifiedtPacketL(aMessage);
            break;
        
        case NRequest::EWaitingForNotification: // 0:&sizePckg
            HandleWaitingForNotification(aMessage);
            break;
        
        case NRequest::ECancelWaitingForNotification:
            HandleCancelWaitingForNotification(aMessage);
            break;

        default:
        	TRACE( _L("CPresenceCacheSession::ServiceL - default"));
            aMessage.Complete(KErrArgument);
            break;
        }
    }

// ---------------------------------------------------------------------------
// CPresenceCacheSession::HandlePrepReadPresenceInfoSyncL()
// ---------------------------------------------------------------------------
//
void CPresenceCacheSession::HandlePrepReadPresenceInfoSyncL( const RMessage2& aMessage )
    {
    TRACE( _L("CPresenceCacheSession::HandlePrepReadPresenceInfoSyncL - begin"));

    TInt sizeOfReturnPacket(NULL);
 
    // unpacking identity
    const TInt pckSize = aMessage.GetDesLengthL(1);
    HBufC8* idPack = HBufC8::NewLC( pckSize );
    TPtr8 paramPckPtr = idPack->Des();
    aMessage.ReadL( 1, paramPckPtr );
    CXIMPIdentityImp* identity = CXIMPIdentityImp::NewLC();
    TXIMPObjectPacker< CXIMPIdentityImp >::UnPackL(*identity, *idPack);
    
    TPtrC serviceName = GetServiceName(identity->Identity());
    
    // now processing
    TInt serviceCount = iServer.iPresenceCache.Count();
    MPresenceBuddyInfo* buddyPresenceInfo(NULL);
    CPresenceCacheBuddyStore* buddyStore(NULL);
    
    TRACE_1( _L("_______serviceCount[%d]"), serviceCount);
    
    for(TInt i=0; i<serviceCount; i++)
        {
        if (serviceName == (iServer.iPresenceCache[i])->ServiceName())
            {
            buddyStore = (iServer.iPresenceCache[i])->FindAndGet(*identity);
            if(buddyStore)
                buddyPresenceInfo = buddyStore->PresenceBuddyInfo();
            break;
            }
        }
    
    CleanupStack::PopAndDestroy(identity);
    CleanupStack::PopAndDestroy(idPack);
    
    TInt err = KErrNotFound;
    
    TRACE_1( _L("_______buddyPresenceInfo[%d]"), buddyPresenceInfo);
    if(buddyPresenceInfo) // if found
        {
        const CPresenceInfoImp* presInfo = 
            TXIMPGetImpClassOrPanic< const CPresenceInfoImp >::From(*(buddyPresenceInfo->PresenceInfo()));
        if(iDataPack)
            delete iDataPack; iDataPack=NULL;
        iDataPack = PackPresenceInfoLC(*presInfo);
        CleanupStack::Pop(iDataPack);
        sizeOfReturnPacket = (iDataPack->Des()).Size();
        err = KErrNone;
        }
    
    TPckgBuf<TInt> p(sizeOfReturnPacket);
    aMessage.WriteL(2,p);            
    aMessage.Complete(err);
    TRACE( _L("CPresenceCacheSession::HandlePrepReadPresenceInfoSyncL - end"));
    }

// ---------------------------------------------------------------------------
// CPresenceCacheSession::HandleGetLastPreparedPacketL()
// ---------------------------------------------------------------------------
//
void CPresenceCacheSession::HandleGetLastPreparedPacketL( const RMessage2& aMessage )
    {
    TRACE( _L("CPresenceCacheSession::HandleGetLastPreparedPacketL() - begin"));
    if(iDataPack)
        aMessage.WriteL(0, *(iDataPack));
    aMessage.Complete(KErrNone);   
    }

// ---------------------------------------------------------------------------
// CPresenceCacheSession::HandleGetLastPreparedAsyncPacketL()
// ---------------------------------------------------------------------------
//
void CPresenceCacheSession::HandleGetLastPreparedAsyncPacketL( const RMessage2& aMessage )
    {
    if(iDataPackAsync)
        aMessage.WriteL(0, *(iDataPackAsync));
    aMessage.Complete(KErrNone);   
    }

// ---------------------------------------------------------------------------
// CPresenceCacheSession::HandleWritePresenceInfoSyncL()
// ---------------------------------------------------------------------------
//
void CPresenceCacheSession::HandleWritePresenceInfoSyncL(const RMessage2& aMessage )
    {
    TRACE( _L("CPresenceCacheSession::HandleWritePresenceInfoSyncL - begin"));
    TInt err(KErrNone);
    const TInt pckSize = aMessage.GetDesLengthL(0);
    if(iDataPack)
        delete iDataPack; iDataPack=NULL;
    iDataPack = HBufC8::NewL( pckSize );
    TPtr8 paramPckPtr = iDataPack->Des();
    aMessage.ReadL( 0, paramPckPtr );
    
    CPresenceBuddyInfoImp* buddypresenceInfo = CPresenceBuddyInfoImp::NewLC();
   

    TXIMPObjectPacker< CPresenceBuddyInfoImp >::UnPackL(*buddypresenceInfo, *iDataPack);
    
    err = TryWriteBuddyToCacheL(buddypresenceInfo);
    
    if(err==KErrNone) //ownership transferred    
        CleanupStack::Pop(buddypresenceInfo);
    else
        CleanupStack::PopAndDestroy(buddypresenceInfo);    
    aMessage.Complete(err);
    TRACE( _L("CPresenceCacheSession::HandleWritePresenceInfoSyncL - end"));
    }

// ---------------------------------------------------------------------------
// CPresenceCacheSession::HandlePrepReadAllBuddiesPresenceInService()
// ---------------------------------------------------------------------------
//
void CPresenceCacheSession::HandlePrepReadAllBuddiesPresenceInService
                                                        (const RMessage2& aMessage )
    {
    if(iActiveHelper->IsActive())
        aMessage.Complete(KErrServerBusy);
    else
        {
        iMessage = aMessage;
        
        iAsyncReq = NRequest::EPrepReadAllBuddiesPresenceInService;
        iActiveHelper->Start();
        }
    }

// ---------------------------------------------------------------------------
// CPresenceCacheSession::ReadAllBuddiesPresenceInServiceL()
// ---------------------------------------------------------------------------
//
void CPresenceCacheSession::ReadAllBuddiesPresenceInServiceL()
    {
    const TInt pckSize = iMessage.GetDesLengthL(0);
    HBufC* serviceName = HBufC16::NewLC( pckSize );
    TPtr16 paramPckPtr = serviceName->Des();
    iMessage.ReadL( 0, paramPckPtr );
    
    TInt serviceCount = iServer.iPresenceCache.Count();
    CPresenceCacheServiceStore* serviceStore(NULL);
    CPresenceBuddyInfoListImp* buddyPresenceInfoList(NULL);
    CPresenceCacheBuddyStore* buddyStore(NULL);
    MPresenceBuddyInfo* presBuddyInfo(NULL);
    TInt presCount(0);
    TInt count(0);
    
    for(TInt i=0; i<serviceCount; i++)
        {
        serviceStore = iServer.iPresenceCache[i];
        if (serviceName->Des() == serviceStore->ServiceName())
            {
            presCount = serviceStore->PresenceCount();
            // if it has presences
            if(presCount)
                {
                buddyPresenceInfoList = CPresenceBuddyInfoListImp::NewLC(*serviceName);
                buddyPresenceInfoList->SetOwnObjects(EFalse);
                count = serviceStore->Count();
                for(TInt j=0; j<count; j++)
                    {
                    buddyStore = serviceStore->GetObjectCollection()[j];
                    presBuddyInfo = buddyStore->PresenceBuddyInfo();
                    if(presBuddyInfo)
                        buddyPresenceInfoList->BlindAddL(presBuddyInfo);    
                    }
                }
            break;
            }
        }
    
    TInt size(KErrNotFound); // this may also indicate error to client if negative
    if(buddyPresenceInfoList) // if found
        {
        if(iDataPackAsync)
            delete iDataPackAsync; iDataPackAsync = NULL;
        iDataPackAsync = TXIMPObjectPacker< CPresenceBuddyInfoListImp>::PackL( *buddyPresenceInfoList);
        size = (iDataPackAsync->Des()).Size();
        CleanupStack::PopAndDestroy(buddyPresenceInfoList);
        }
    
    CleanupStack::PopAndDestroy(serviceName);
    iAsyncReq = NRequest::ENoRequestMade;
    iMessage.Complete(size);
    }
    

// ---------------------------------------------------------------------------
// CPresenceCacheSession::TryWriteBuddyToCache()
// ---------------------------------------------------------------------------
//
TInt CPresenceCacheSession::TryWriteBuddyToCacheL(MPresenceBuddyInfo* aBuddyPresInfo)
    {
    if(!aBuddyPresInfo)
        return KErrArgument;
    
    TPtrC serviceName = GetServiceName(aBuddyPresInfo->BuddyId()->Identity());
    TInt serviceCount = iServer.iPresenceCache.Count();
    CPresenceCacheBuddyStore* buddyStore(NULL);
    
    for(TInt i=0; i<serviceCount; i++)
        {
        if (serviceName == (iServer.iPresenceCache[i])->ServiceName())
            {
            buddyStore = (iServer.iPresenceCache[i])->AddOrReplacePresenceL(aBuddyPresInfo);
            break;
            }
        }
    if(!buddyStore) // if not written
        {
        CPresenceCacheServiceStore* newServiceStore = CPresenceCacheServiceStore::NewLC();
        newServiceStore->SetServiceNameL(serviceName);
        buddyStore = newServiceStore->AddOrReplacePresenceL(aBuddyPresInfo);
        (iServer.iPresenceCache).Append(newServiceStore); //ownership transferred
        CleanupStack::Pop(newServiceStore);
        }
        
    if(buddyStore) //  inform to subscribers
        NotifyAllSubscribersL(buddyStore);
        
    return buddyStore ? KErrNone : KErrGeneral;
    }
    

// ---------------------------------------------------------------------------
// CPresenceCacheSession::HandleCancel()
// ---------------------------------------------------------------------------
//
void CPresenceCacheSession::HandleCancel(const RMessage2& aMessage )
    {
    if (iActiveHelper->IsActive())
        iActiveHelper->Cancel(); //see also iActiveHelper->DoCancel()
    aMessage.Complete(KErrNotFound);
    }
    
// ---------------------------------------------------------------------------
// CPresenceCacheSession::HandleBuddyCountInAllServices()
// ---------------------------------------------------------------------------
//
void CPresenceCacheSession::HandleBuddyCountInAllServices(const RMessage2& aMessage )
    {
    TRACE( _L("CPresenceCacheSession::HandleBuddyCountInAllServices - begin"));
    TInt count(NULL);
    TInt serviceCount = iServer.iPresenceCache.Count();
    
    for(TInt i=0; i<serviceCount; i++)
        {
        count = (count) + ((iServer.iPresenceCache[i])->PresenceCount());
        }
    
    TPckgBuf<TInt> p(count);
    aMessage.WriteL(0,p);               
    aMessage.Complete(KErrNone);
    TRACE( _L("CPresenceCacheSession::HandleBuddyCountInAllServices - end"));
    }

// ---------------------------------------------------------------------------
// CPresenceCacheSession::HandleBuddyCountInService()
// ---------------------------------------------------------------------------
//
void CPresenceCacheSession::HandleBuddyCountInService(const RMessage2& aMessage )
    {
    TInt count(NULL);
    
    const TInt pckSize = aMessage.GetDesLengthL(1);
    HBufC* serviceName = HBufC16::NewLC( pckSize );
    TPtr16 paramPckPtr = serviceName->Des();
    aMessage.ReadL( 1, paramPckPtr );
    
    TInt serviceCount = iServer.iPresenceCache.Count();
    TInt err(KErrNotFound);
    
    for(TInt i=0; i<serviceCount; i++)
        {
        if (serviceName->Des() == (iServer.iPresenceCache[i])->ServiceName())
            {
            count = ((iServer.iPresenceCache[i])->PresenceCount());
            err = KErrNone;
            break;
            }
        }
    
    CleanupStack::PopAndDestroy(serviceName);
    TPckgBuf<TInt> p(count);
    aMessage.WriteL(0,p);
    aMessage.Complete(err);    
    }

// ---------------------------------------------------------------------------
// CPresenceCacheSession::HandleDeleteService()
// ---------------------------------------------------------------------------
//
void CPresenceCacheSession::HandleDeleteService(const RMessage2& aMessage )
    {
    TRACE( _L("CPresenceCacheSession::HandleDeleteService - begin"));
    TInt err(KErrNotFound);
    
    const TInt pckSize = aMessage.GetDesLengthL(0);
    HBufC* serviceName = HBufC16::NewLC( pckSize );
    TPtr16 paramPckPtr = serviceName->Des();
    aMessage.ReadL( 0, paramPckPtr );
    
    TInt serviceCount = iServer.iPresenceCache.Count();
    TInt buddyCount(NULL);
    
    TRACE_1( _L("_______serviceCount[%d]"), serviceCount);
    for(TInt i=0; i<serviceCount; i++)
        {
        if (serviceName->Des() == (iServer.iPresenceCache[i])->ServiceName())
            {
            (iServer.iPresenceCache[i])->RemoveAllPresences();
            buddyCount = (iServer.iPresenceCache[i])->GetObjectCollection().Count();
            TRACE_1( _L("_______buddyCountAfter[%d]"), buddyCount);
            
            //if there are no buddies left in this service delete this whole service
            if(buddyCount==0)
                {
                delete iServer.iPresenceCache[i];
                iServer.iPresenceCache.Remove(i);
                }
                
            //inform all subscribers
            for(TInt j=0;j<buddyCount;j++)
                {
                NotifyAllSubscribersL((iServer.iPresenceCache[i])->GetObjectCollection()[j]);
                }
            err = KErrNone;
            break;
            }
        }
    CleanupStack::PopAndDestroy(serviceName);
    aMessage.Complete(err);
    TRACE( _L("CPresenceCacheSession::HandleDeleteService - end"));
    }
    
// ---------------------------------------------------------------------------
// CPresenceCacheSession::HandleDeletePresence()
// ---------------------------------------------------------------------------
//
void CPresenceCacheSession::HandleDeletePresence(const RMessage2& aMessage )
    {
    const TInt pckSize = aMessage.GetDesLengthL(0);
    HBufC8* idPack = HBufC8::NewLC( pckSize );
    TPtr8 paramPckPtr = idPack->Des();
    aMessage.ReadL( 0, paramPckPtr );
    TInt err(KErrNotFound);
    TInt buddyCount(NULL);
    
    CXIMPIdentityImp* identity = CXIMPIdentityImp::NewLC();
    
    TXIMPObjectPacker< CXIMPIdentityImp >::UnPackL(*identity, *idPack);
    
    TPtrC serviceName = GetServiceName(identity->Identity());
    
    TInt serviceCount = iServer.iPresenceCache.Count();
    
    CPresenceCacheBuddyStore* buddyStore(NULL);
    for(TInt i=0; i<serviceCount; i++)
        {
        if(((iServer.iPresenceCache[i])->ServiceName()) == serviceName)
            {
            buddyStore = (iServer.iPresenceCache[i])->FindAndRemove(*identity,err);
            
            buddyCount = (iServer.iPresenceCache[i])->GetObjectCollection().Count();
            TRACE_1( _L("_______buddyCountAfter[%d]"), buddyCount);
            
            //if there are no buddies left in this service delete this whole service
            if(buddyCount==0)
                {
                delete iServer.iPresenceCache[i];
                iServer.iPresenceCache.Remove(i);
                }
            break;
            }
        }
    
    CleanupStack::PopAndDestroy(identity);
    CleanupStack::PopAndDestroy(idPack);
    aMessage.Complete(err);
    
    if(buddyStore) // if subscribers
        NotifyAllSubscribersL(buddyStore);
    }
    

// ---------------------------------------------------------------------------
// CPresenceCacheSession::HandleGetServiceCount()
// ---------------------------------------------------------------------------
//
void CPresenceCacheSession::HandleGetServiceCount(const RMessage2& aMessage )
    {
    // iLastServiceCount is also used for mem aloc by client before calling
    // GetAllServices
    TInt serviceCount = iServer.iPresenceCache.Count();
    iLastServiceCount = 0;
    TRACE_1( _L("CPresenceCacheSession::HandleGetServiceCount realcount[%d]- end"),serviceCount);
    for(TInt i=0;i<serviceCount;i++)
        {
        if((iServer.iPresenceCache[i])->PresenceCount())
            iLastServiceCount++;
        }

    TPckgBuf<TInt> p(iLastServiceCount);
    aMessage.WriteL(0,p);
    aMessage.Complete(KErrNone);
    }

// ---------------------------------------------------------------------------
// CPresenceCacheSession::HandleGetAllServicesL()
// ---------------------------------------------------------------------------
//
/*
void CPresenceCacheSession::HandleGetAllServicesL(const RMessage2& aMessage )   
    {
    TInt serviceCount = iServer.iPresenceCache.Count();
    TInt size(NULL);
    
    if(serviceCount)
    	{
        CArrayFixFlat<TUid>* services = new (ELeave) CArrayFixFlat<TUid>(1);
        CleanupStack::PushL(services);
    	
    	for(TInt i=0; i<serviceCount; i++)
	        {
	        if((iServer.iPresenceCache[i])->PresenceCount())
	            services->AppendL((iServer.iPresenceCache[i])->Service());
	        }
	    
	    if (iDataPack)
	        {
	        delete iDataPack; iDataPack = NULL;
	        }
	    iDataPack = PackServicesL(services);
	    CleanupStack::PopAndDestroy(services);
	    size = (iDataPack->Des()).Size();
    	}
    aMessage.Complete(size);
    }*/
    
// ---------------------------------------------------------------------------
// CPresenceCacheSession::HandleWritePresenceInfoAsyncL()
// ---------------------------------------------------------------------------
//
void CPresenceCacheSession::HandleWritePresenceInfoAsyncL(const RMessage2& aMessage )
    {
    if(iActiveHelper->IsActive())
        {
        aMessage.Complete(KErrServerBusy);
        return;        
        }
    iMessage = aMessage;
    
    const TInt pckSize = aMessage.GetDesLengthL(0);
    if(iDataPackAsync)
        delete iDataPackAsync; iDataPackAsync = NULL;
    iDataPackAsync = HBufC8::NewL( pckSize );
    TPtr8 paramPckPtr = iDataPackAsync->Des();
    aMessage.ReadL( 0, paramPckPtr );
    
    if(iBuddypresInfoList)
        delete iBuddypresInfoList; iBuddypresInfoList = NULL;
    iBuddypresInfoList = CPresenceBuddyInfoListImp::NewLC(KNullDesC);
    CleanupStack::Pop(iBuddypresInfoList);
    
    TXIMPObjectPacker< CPresenceBuddyInfoListImp >::UnPackL(*iBuddypresInfoList, *iDataPackAsync);
    
    iAsyncReq = NRequest::EWritePresenceInfoAsync;
    iActiveHelper->Start();
    return;
    }

// ---------------------------------------------------------------------------
// CPresenceCacheSession::WritePresenceInfoAsyncL()
// ---------------------------------------------------------------------------
//
void CPresenceCacheSession::WritePresenceInfoAsyncL()
    {
    TInt err(KErrNone);
    TInt thisTimeWrites(0);
    if(!iBuddypresInfoList) // return if this function is wrongly called
        return;
    
    // This routine reads data from iBuddypresInfoList and tries to write 
    // data to cache on each runl cycle. It writes either KMaxWriteEachCycle 
    // times, or upto data is finnished. After data is written KMaxWriteEachCycle
    // times and still more data is left, it makes this class active so that this
    // function is again called on next RunL.
    while(iBuddypresInfoList->Count())
        {
        err = TryWriteBuddyToCacheL((iBuddypresInfoList->GetObjectCollection())[0]);
        if(err==KErrNone) // if no erroe then pop the object from list
            (iBuddypresInfoList->GetObjectCollection()).Remove(0);
        else
            break; // break in case of error
        thisTimeWrites++;    
        if(thisTimeWrites == NConstants::KMaxWriteEachCycle) // this times writes are over
            {
            if(iActiveHelper->IsActive())// unusual condition
                {
                err = KErrGeneral;
                break;
                }
            iActiveHelper->Start();
            return; // set for next time writing.
            }
       }
    // if we able to come out of while loop either writing is complete or
    // there was some error while writing, in both cases finnish writing
    iAsyncReq = NRequest::ENoRequestMade;
    iMessage.Complete(err);
    return;
    }

// ---------------------------------------------------------------------------
// CPresenceCacheSession::HandleSubscribeBuddyPresenceChange()
// ---------------------------------------------------------------------------
//
void CPresenceCacheSession::HandleSubscribeBuddyPresenceChange
                                                (const RMessage2& aMessage )
    {
    TRACE( _L("CPresenceCacheSession::HandleSubscribeBuddyPresenceChange - begin"));

    // Extract info from message
    const TInt pckSize = aMessage.GetDesLengthL(1);
    HBufC8* idPack = HBufC8::NewLC( pckSize );
    TPtr8 paramPckPtr = idPack->Des();
    aMessage.ReadL( 1, paramPckPtr );
    
    CXIMPIdentityImp* identity = CXIMPIdentityImp::NewLC();
    
    TXIMPObjectPacker< CXIMPIdentityImp >::UnPackL(*identity, *idPack);
    
    TPtrC serviceName = GetServiceName(identity->Identity());
    
    CPresenceCacheBuddyStore* buddyStore(NULL);
    CPresenceCacheServiceStore* serviceStore(NULL);
    
    TInt err(KErrGeneral); // there must not be error in this handler
                           // but just for debug purpose
    
    
    // now processing
    TInt serviceCount = iServer.iPresenceCache.Count();

    
    TRACE_1( _L("_______serviceCount[%d]"), serviceCount);
    
    for(TInt i=0; i<serviceCount; i++)
        {
        if (serviceName == (iServer.iPresenceCache[i])->ServiceName())
            {
            serviceStore = iServer.iPresenceCache[i];
            buddyStore = (iServer.iPresenceCache[i])->FindAndGet(*identity);
            break;
            }
        }
        
    if(!buddyStore) // if buddy was not found, create and add it
        {
        if(!serviceStore) //if service was also not found, create it
            {
            serviceStore = CPresenceCacheServiceStore::NewLC();
            serviceStore->SetServiceNameL(serviceName);
            (iServer.iPresenceCache).Append(serviceStore); //ownership transferred
            CleanupStack::Pop(serviceStore);  
            }
        buddyStore = CPresenceCacheBuddyStore::NewLC(serviceStore,identity);
        err = serviceStore->AddBlind(buddyStore); //ownership transferred
        CleanupStack::Pop(buddyStore);
        CleanupStack::Pop(identity);
        } 
    else
        CleanupStack::PopAndDestroy(identity); // since in this case ownership wasnt tranferred
    
    CleanupStack::PopAndDestroy(idPack);
    
    TRACE_1( _L("buddyStore[%d]"), buddyStore);
    if(buddyStore) // must be there, just for double check
        {
        buddyStore->AddSubscribedSession(this);
        if(iSubscribedStores.Find(buddyStore) < 0) //if session not already there
            iSubscribedStores.Append(buddyStore);
        err = KErrNone;
        }
    
    aMessage.Complete(err); // there shouldnt be any errors
    TRACE( _L("CPresenceCacheSession::HandleSubscribeBuddyPresenceChange - end"));
    }

// ---------------------------------------------------------------------------
// CPresenceCacheSession::HandleUnSubscribeBuddyPresenceChange()
// ---------------------------------------------------------------------------
//
void CPresenceCacheSession::HandleUnSubscribeBuddyPresenceChange
                                                (const RMessage2& aMessage )
    {
    TRACE( _L("CPresenceCacheSession::HandleUnSubscribeBuddyPresenceChange - begin"));

    // Extract info from message
    const TInt pckSize = aMessage.GetDesLengthL(1);
    HBufC8* idPack = HBufC8::NewLC( pckSize );
    TPtr8 paramPckPtr = idPack->Des();
    aMessage.ReadL( 1, paramPckPtr );
    TInt err(KErrNotFound);
    
    CXIMPIdentityImp* identity = CXIMPIdentityImp::NewLC();
    
    TXIMPObjectPacker< CXIMPIdentityImp >::UnPackL(*identity, *idPack);
    
    TPtrC serviceName = GetServiceName(identity->Identity());
    
    
    // now processing
    TInt serviceCount = iServer.iPresenceCache.Count();
    CPresenceCacheBuddyStore* buddyStore(NULL);
    
    TRACE_1( _L("_______serviceCount[%d]"), serviceCount);
    
    for(TInt i=0; i<serviceCount; i++)
        {
        if (serviceName == (iServer.iPresenceCache[i])->ServiceName())
            {
            buddyStore = (iServer.iPresenceCache[i])->FindAndGet(*identity);
            break;
            }
        }
    
    CleanupStack::PopAndDestroy(identity);
    CleanupStack::PopAndDestroy(idPack);
    
    TRACE_1( _L("buddyStore[%d]"), buddyStore);
    if(buddyStore) // if found
        {
        buddyStore->RemoveSubscribedSession(this);
        iSubscribedStores.Remove(iSubscribedStores.Find(buddyStore));
        err = KErrNone;
        }
    
    aMessage.Complete(err);
    TRACE_1( _L("CPresenceCacheSession::HandleUnSubscribeBuddyPresenceChange (%d) - end"),err);
    }

// ---------------------------------------------------------------------------
// CPresenceCacheSession::HandleGetLastNotifiedtPacketL()
// ---------------------------------------------------------------------------
//
void CPresenceCacheSession::HandleGetLastNotifiedtPacketL(const RMessage2& aMessage )
    {
    TRACE( _L("CPresenceCacheSession::HandleGetLastNotifiedtPacketL() - begin"));
    if(iDataPackNotifier)
        aMessage.WriteL(0, *(iDataPackNotifier));
    aMessage.Complete(KErrNone);
    }

// ---------------------------------------------------------------------------
// CPresenceCacheSession::HandleWaitingForNotification()
// ---------------------------------------------------------------------------
//
void CPresenceCacheSession::HandleWaitingForNotification(const RMessage2& aMessage )
    {
    iMessageForNoti = aMessage;
    }

// ---------------------------------------------------------------------------
// CPresenceCacheSession::HandleCancelWaitingForNotification()
// ---------------------------------------------------------------------------
//
void CPresenceCacheSession::HandleCancelWaitingForNotification
                                                    (const RMessage2& aMessage )
    {
    aMessage.Complete(KErrNone);
    if(!iMessageForNoti.IsNull())
        iMessageForNoti.Complete(KErrCancel);
    }

// ---------------------------------------------------------------------------
// CPresenceCacheSession::NotifyPresenceChangeL()
// ---------------------------------------------------------------------------
//
void CPresenceCacheSession::NotifyPresenceChangeL(
                               const CPresenceBuddyInfoImp* aPresenceBuddyInfo)
    {
    TRACE( _L("CPresenceCacheSession::NotifyPresenceChangeL() - begin"));
    TInt sizeOfReturnPacket(NULL);
    if(aPresenceBuddyInfo && (!iMessageForNoti.IsNull())) // if pointers are valid
        {
        if(iDataPackNotifier)
            delete iDataPackNotifier; iDataPackNotifier=NULL;
        iDataPackNotifier = PackBuddyPresenceInfoLC(aPresenceBuddyInfo);
        CleanupStack::Pop(iDataPackNotifier);
        sizeOfReturnPacket = (iDataPackNotifier->Des()).Size();
        TPckgBuf<TInt> p(sizeOfReturnPacket);
        iMessageForNoti.WriteL(0,p);            
        iMessageForNoti.Complete(KErrNone);
        TRACE( _L("_______message was valid"));
        }
    TRACE( _L("CPresenceCacheSession::NotifyPresenceChangeL - end"));
    }
    
// ---------------------------------------------------------------------------
// CPresenceCacheSession::NotifyAllSubscribersL()
// ---------------------------------------------------------------------------
//
void CPresenceCacheSession::NotifyAllSubscribersL
                                        (CPresenceCacheBuddyStore* aBuddyStore)
    {
    TRACE( _L("CPresenceCacheSession::NotifyAllSubscribers() - begin"));
    if(!aBuddyStore)
        return;
    TInt subsCount = aBuddyStore->GetSubscribedSessions().Count();
    TRACE_1( _L("_______total subscribed sessions[%d]"), subsCount);
    TBool ownBuddyInfo(EFalse);
    const CPresenceBuddyInfoImp* buddyInfo;
    
    if(subsCount) // start processing if there are subscribers
        {
        //if presence has been deleted we need to identity and service id in the packed
        //which will be sent to clients
        if(!(aBuddyStore->PresenceBuddyInfo()))
            {
            CPresenceBuddyInfoImp* buddyInfoTemp = CPresenceBuddyInfoImp::NewLC();
            MXIMPIdentity* id = CXIMPIdentityImp::NewLC(aBuddyStore->BuddyId()->Identity());
            buddyInfoTemp->SetBuddyId(id);
            CleanupStack::Pop(1); //id
            ownBuddyInfo = ETrue;
            buddyInfo = buddyInfoTemp;
            }
        else
            {
            buddyInfo = 
                TXIMPGetImpClassOrPanic< const CPresenceBuddyInfoImp >::From( *(aBuddyStore->PresenceBuddyInfo()) );    
            }
            
        CPresenceCacheSession* session(NULL);
        for(TInt i=0;i<subsCount;i++)
            {
            session = aBuddyStore->GetSubscribedSessions()[i];
            if(iServer.SessionExists(session))
                {
                TRACE_1( _L("_______valid session notified[%d]"), session);
                session->NotifyPresenceChangeL(buddyInfo);
                }
            else
                {
                aBuddyStore->RemoveSubscribedSession(session);
                subsCount--;//substract this removed session from total count
                i--;
                TRACE_1( _L("_______invalid session removed[%d]"), session);
                }    
            }
        }
        
    if(ownBuddyInfo)
        CleanupStack::PopAndDestroy(1); //buddyInfoTemp
    TRACE( _L("CPresenceCacheSession::NotifyAllSubscribers() - end"));
    }

// ---------------------------------------------------------------------------
// CPresenceCacheSession::GetServiceName()
// ---------------------------------------------------------------------------
//
TPtrC CPresenceCacheSession::GetServiceName(const TDesC& aXspId)
    {
    _LIT(KColon, ":");
    TInt pos = aXspId.Find(KColon);
    TPtrC serviceName;
    if(pos>0) // if colon found and there is something before colon, i.e. xsp id
        {
        serviceName.Set(aXspId.Left(pos));
        }
    else
        serviceName.Set(TPtrC());
    return serviceName;
    }
        
// ---------------------------------------------------------------------------
// CPresenceCacheSession::Cancel()
// ---------------------------------------------------------------------------
//
void CPresenceCacheSession::Cancel()
    {
    if (iAsyncReq != NRequest::ENoRequestMade)
        {
        iMessage.Complete(KErrCancel);
        iAsyncReq = NRequest::ENoRequestMade;
        }
    return;   
    }
    
// ---------------------------------------------------------------------------
// CPresenceCacheSession::PackPresenceDocLC()
// ---------------------------------------------------------------------------
//
HBufC8* CPresenceCacheSession::PackPresenceInfoLC(const MPresenceInfo& aPresInfo)
    {
    const CPresenceInfoImp* tmp =
        TXIMPGetImpClassOrPanic< const CPresenceInfoImp >::From(aPresInfo);
    HBufC8* pack = TXIMPObjectPacker< CPresenceInfoImp>::PackL( *tmp);
    CleanupStack::PushL( pack );

    return pack;
    }
    
// ---------------------------------------------------------------------------
// CPresenceCacheSession::PackBuddyPresenceInfoLC()
// ---------------------------------------------------------------------------
//
HBufC8* CPresenceCacheSession::PackBuddyPresenceInfoLC(
                                    const CPresenceBuddyInfoImp* aBuddyPresInfo)
    {
    HBufC8* pack(NULL);
    if(aBuddyPresInfo)
        {
        //const CPresenceBuddyInfoImp* pifImp = 
        //    TXIMPGetImpClassOrPanic< const CPresenceBuddyInfoImp >::From( *aBuddyPresInfo );    
        
        pack = TXIMPObjectPacker< const CPresenceBuddyInfoImp>::PackL( *aBuddyPresInfo );
        CleanupStack::PushL( pack );
        }

    return pack;
    }
    

// ---------------------------------------------------------------------------
// CPresenceCacheSession::PackServicesL()
// ---------------------------------------------------------------------------
//
/*
HBufC8* CPresenceCacheSession::PackServicesL(CArrayFixFlat<TUid>* aArray )
	{
    CBufFlat* packBuf = CBufFlat::NewL( NConstants::KGranularity );
    CleanupStack::PushL( packBuf );

    RBufWriteStream ws;
    ws.Open( *packBuf ); // CSI: 65 #
    CleanupClosePushL( ws );

    // Get count of objects
    TInt objCount = aArray->Count();
    // write the count
    ws.WriteInt32L( objCount );
    // objects
    for ( TInt count(0); count < objCount; count++ )
        {
        ws<<(aArray->At(count));
        }

    ws.CommitL();
    CleanupStack::PopAndDestroy(); //ws

    HBufC8* packBufDesc = packBuf->Ptr(0).AllocL();
    CleanupStack::PopAndDestroy( packBuf );

    return packBufDesc;
	}*/

// ---------------------------------------------------------------------------
// CPresenceCacheSession::CPresenceCacheSession()
// ---------------------------------------------------------------------------
//
CPresenceCacheSession::CPresenceCacheSession( CPresenceCacheServer& aServer )
                                                        : iServer( aServer ),
                                                        iLastServiceCount(0)
    {
    TRACE( _L("CPresenceCacheSession::CPresenceCacheSession()"));
    }

// ---------------------------------------------------------------------------
// CPresenceCacheSession::ConstructL()
// ---------------------------------------------------------------------------
//
void CPresenceCacheSession::ConstructL()
    {
    iActiveHelper = CCacheSessionActiveHelper::NewL(this);    
    iServer.IncrementSessions();
    return;
    }
    
// ---------------------------------------------------------------------------
// CPresenceCacheSession::RemoveMySubscriptions()
// ---------------------------------------------------------------------------
//
void CPresenceCacheSession::RemoveMySubscriptions()
    {
    TInt count = iSubscribedStores.Count();
    for(TInt i=0;i<count;i++)
        {
        // it can be assumed that store is alive, since it won't be deleted
        // until there is any session subscribed to it
        (iSubscribedStores[i])->RemoveSubscribedSession(this);
        }
    }
    
    
// ---------------------------------------------------------------------------
// CCacheSessionActiveHelper::NewL()
// ---------------------------------------------------------------------------
//
CCacheSessionActiveHelper* CCacheSessionActiveHelper::NewL
                                            (CPresenceCacheSession* aSession )
    {
    CCacheSessionActiveHelper* self = new(ELeave) CCacheSessionActiveHelper(aSession);
    CleanupStack::PushL( self );
    self->ConstructL( );
    CleanupStack::Pop( self );
    return self;
    }

// ---------------------------------------------------------------------------
// CCacheSessionActiveHelper::~CCacheSessionActiveHelper()
// ---------------------------------------------------------------------------
//
CCacheSessionActiveHelper::~CCacheSessionActiveHelper( )
    {
    Cancel();   
    }

// ---------------------------------------------------------------------------
// CCacheSessionActiveHelper::Start()
// ---------------------------------------------------------------------------
//
void CCacheSessionActiveHelper::Start()
    {
    TRequestStatus* status = &iStatus;
    User::RequestComplete(status,KErrNone);
    SetActive();
    }

// ---------------------------------------------------------------------------
// CCacheSessionActiveHelper::CCacheSessionActiveHelper()
// ---------------------------------------------------------------------------
//
CCacheSessionActiveHelper::CCacheSessionActiveHelper(CPresenceCacheSession* aSession ) 
                                                    : CActive(EPriorityStandard)
    {
    iCacheSession = aSession;
    }

// ---------------------------------------------------------------------------
// CCacheSessionActiveHelper::RunL()
// ---------------------------------------------------------------------------
//
void CCacheSessionActiveHelper::RunL()
    {
    switch (iCacheSession->iAsyncReq)
        {
        case NRequest::EWritePresenceInfoAsync:
            iCacheSession->WritePresenceInfoAsyncL();
            break;

        case NRequest::EPrepReadAllBuddiesPresenceInService:
            iCacheSession->ReadAllBuddiesPresenceInServiceL();
            break;

        case NRequest::ENoRequestMade:
        default:
            break;
        }    
    }

// ---------------------------------------------------------------------------
// CCacheSessionActiveHelper::DoCancel()
// ---------------------------------------------------------------------------
//
void CCacheSessionActiveHelper::DoCancel()
    {
    iCacheSession->Cancel();
    }

// ---------------------------------------------------------------------------
// CCacheSessionActiveHelper::ConstructL()
// ---------------------------------------------------------------------------
//
void CCacheSessionActiveHelper::ConstructL()
    {
	CActiveScheduler::Add(this);
    }


// End of File