persistentstorage/dbms/sdbms/SD_BUF.CPP
changeset 0 08ec8eefde2f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/persistentstorage/dbms/sdbms/SD_BUF.CPP	Fri Jan 22 11:06:30 2010 +0200
@@ -0,0 +1,368 @@
+// Copyright (c) 1998-2009 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:
+// DBMS server stream buffer classes
+// 
+//
+
+
+
+#include "SD_STD.H"
+
+HDbsBuf* HDbsBuf::NewLC(const RDbsObject& aObject,TDbsFunction aFunction,TIpcArgs& aArgs)
+	{
+	HDbsBuf* self=new(ELeave) HDbsBuf;
+	self->PushL();
+	self->ConstructL(aObject,aFunction,aArgs);
+	return self;
+	}
+
+HDbsBuf* HDbsBuf::NewL(const RDbsObject& aObject,TDbsFunction aFunction,TIpcArgs& aArgs)
+	{
+	HDbsBuf* self=NewLC(aObject,aFunction,aArgs);
+	CleanupStack::Pop();
+	return self;
+	}
+
+void HDbsBuf::ConstructL(const RDbsObject& aObject,TDbsFunction aFunction,TIpcArgs& aArgs)
+	{
+	TPckg<TDbsStreamBuf> pckg(iBuf);
+	aArgs.Set(3,&pckg);
+	iIpc.OpenL(aObject,aFunction,aArgs);
+	TUint8* base=iBuf.iData;
+	// if reading we already have one buffer-full of data
+	TInt avail=Max(0,Min(iBuf.iExt,KDbsStreamBufSize));
+	SetBuf(ERead,base,base+avail);
+	SetPos(ERead,avail);
+	SetBuf(EWrite,base,base);
+	SetPos(EWrite,0);
+	}
+
+TInt HDbsBuf::UnderflowL(TInt)
+//
+// Fill the buffer's read area.
+//
+	{
+	// when handle is null there is no data to read from server
+	if(!iIpc.Handle())
+		return 0;
+
+	__ASSERT(Avail(ERead)==0);
+	TUint8* base=iBuf.iData;
+	IpcWriteL(base,Lag(EWrite));
+	SetBuf(EWrite,base,base);
+//
+	TInt len=IpcReadL(base,iBuf.ESize);
+	SetBuf(ERead,base,base+len);
+	return len;
+	}
+
+void HDbsBuf::OverflowL()
+//
+// Set up the buffer's write area.
+//
+	{
+	__ASSERT(Avail(EWrite)==0);
+	TUint8* base=iBuf.iData;
+	MovePos(ERead,Lag(ERead));
+	SetBuf(ERead,base,base);
+//
+	IpcWriteL(base,Lag(EWrite));
+	SetBuf(EWrite,base,base+iBuf.ESize);
+	}
+
+void HDbsBuf::DoRelease()
+	{
+	delete this;
+	}
+
+void HDbsBuf::DoSynchL()
+//
+// Synchronise this buffer with its file, giving up on outstanding writes in case of failure.
+//
+	{
+	TUint8* base=iBuf.iData;
+	MovePos(ERead,Lag(ERead));
+	TInt lag=Lag(EWrite);
+	SetBuf(ERead|EWrite,base,base);
+	iBuf.iExt=-1;
+	IpcWriteL(base,lag);
+	iIpc.SendReceiveL(EDbsStreamSynch);
+	}
+
+TInt HDbsBuf::DoReadL(TAny* aPtr,TInt aMaxLength)
+//
+// Read direct from ipc if asked to transfer more than a bufferful.
+//
+	{
+	__ASSERT(aMaxLength>=0);
+	__ASSERT(aMaxLength>0);
+	TInt avail=Avail(ERead);
+	__ASSERT(avail>=0&&Avail(EWrite)>=0);
+	if (avail>0)
+		{
+		TInt len=Min(aMaxLength,avail);
+		TUint8* ptr=Ptr(ERead);
+		aPtr=Mem::Copy(aPtr,ptr,len);
+		SetPtr(ERead,ptr+len);
+		aMaxLength-=len;
+		if (aMaxLength==0)
+			return len; // that's it
+		}
+	__ASSERT(Avail(ERead)==0);
+	if (aMaxLength<iBuf.ESize)
+		return avail+TStreamBuf::DoReadL(aPtr,aMaxLength);
+//
+	// when handle is null there is no more data to read from server
+	if(!iIpc.Handle())
+		return avail;
+
+	TUint8* base=iBuf.iData;
+	IpcWriteL(base,Lag(EWrite));
+	SetBuf(ERead|EWrite,base,base);
+	return avail+IpcReadL(aPtr,aMaxLength);
+	}
+
+void HDbsBuf::DoWriteL(const TAny* aPtr,TInt aLength)
+//
+// Write direct to ipc if asked to transfer more than a bufferful.
+//
+	{
+	__ASSERT(aLength>=0);
+	__ASSERT(aLength>0);
+	TInt avail=Avail(EWrite);
+	__ASSERT(Avail(ERead)>=0&&avail>=0);
+	if (avail>0)
+		{
+		TInt len=Min(aLength,avail);
+		SetPtr(EWrite,Mem::Copy(Ptr(EWrite),aPtr,len));
+		aLength-=len;
+		if (aLength==0)
+			return; // done
+//
+		aPtr=(TUint8*)aPtr+len;
+		}
+	__ASSERT(Avail(EWrite)==0);
+	if (aLength<iBuf.ESize)
+		TStreamBuf::DoWriteL(aPtr,aLength);
+	else
+		{
+		TUint8* base=iBuf.iData;
+		IpcWriteL(base,Lag(EWrite));
+		MovePos(ERead,Lag(ERead));
+		SetBuf(ERead|EWrite,base,base);
+		IpcWriteL(aPtr,aLength);
+		}
+	}
+
+TStreamPos HDbsBuf::DoSeekL(TMark aMark,TStreamLocation aLocation,TInt anOffset)
+//
+// Position the mark(s) indicated by aMark at anOffset from aLocation.
+//
+	{
+	TUint8* base=iBuf.iData;
+	TInt end=EndL();
+//
+	switch (aLocation)
+		{
+	case EStreamBeginning:
+		break;
+	case EStreamMark:
+		switch (aMark)
+			{
+		case ERead:
+			anOffset+=Mark(ERead);
+			break;
+		case EWrite:
+			anOffset+=Mark(EWrite);
+			break;
+		default:
+			Panic(EDbsStreamMarkInvalid);
+			break;
+			}
+		break;
+	case EStreamEnd:
+		anOffset+=end;
+		break;
+	default:
+		Panic(EDbsStreamLocationInvalid);
+		break;
+		}
+	TInt r=KErrNone;
+	if (anOffset<0)
+		{
+		anOffset=0;
+		r=KErrEof;
+		}
+	else if (anOffset>end)
+		{
+		anOffset=end;
+		r=KErrEof;
+		}
+//
+	__ASSERT_ALWAYS(!(aMark&~(ERead|EWrite)),Panic(EDbsStreamMarkInvalid));
+	if (aMark&ERead)
+		{
+		TInt lag=anOffset-Pos(ERead);
+		if (lag>=base-End(ERead)&&lag<=0)
+			SetPtr(ERead,End(ERead)+lag);
+		else
+			{
+			SetPos(ERead,anOffset);
+			SetBuf(ERead,base,base);
+			}
+		}
+	if (aMark&EWrite&&anOffset!=Mark(EWrite))
+		{
+		IpcWriteL(base,Lag(EWrite));
+		SetPos(EWrite,anOffset);
+		SetBuf(EWrite,base,base);
+		}
+	__LEAVE_IF_ERROR(r);
+	return TStreamPos(anOffset);
+	}
+
+TInt HDbsBuf::IpcReadL(TAny* aPtr,TInt aMaxLength)
+//
+// Read from the server at the current read position.
+//
+	{
+	__ASSERT(aMaxLength>=0);
+	if (aMaxLength==0)
+		return 0;
+//
+	TPtr8 des((TUint8*)aPtr,aMaxLength);
+	TInt pos=Pos(ERead);
+		
+	TInt len=iIpc.SendReceiveL(EDbsStreamRead,TIpcArgs(pos,&des,aMaxLength));
+	pos+=len;
+	if (len<aMaxLength)
+		iBuf.iExt=pos; // end-of-file encountered
+	SetPos(ERead,pos);
+	return len;
+	}
+
+void HDbsBuf::IpcWriteL(const TAny* aPtr,TInt aLength)
+//
+// Write to the server at the current write position.
+//
+	{
+	__ASSERT(aLength>=0);
+	if (aLength==0)
+		return;
+//
+	TPtrC8 ptr((TUint8*)aPtr,aLength);
+	TInt ext=iBuf.iExt;
+	iBuf.iExt=-1;
+	TInt pos=Pos(EWrite);
+	iIpc.SendReceiveL(EDbsStreamWrite,TIpcArgs(pos,&ptr));
+	pos+=aLength;
+	if (ext>=0&&pos>ext)
+		iBuf.iExt=pos;
+	SetPos(EWrite,pos);
+	}
+
+TInt HDbsBuf::EndL()
+//
+// Determine the end of the stream
+//
+	{
+	TInt ext=iBuf.iExt;
+	if (ext<0)
+		iBuf.iExt=ext=iIpc.SendReceiveL(EDbsStreamSize);
+	return Max(ext,Mark(EWrite));
+	}
+
+// Class HDbsReadBuf
+
+inline HDbsReadBuf::HDbsReadBuf(const TDesC8& aDes)
+	{
+	TUint8* ptr=CONST_CAST(TUint8*,aDes.Ptr());
+	Set(ptr,ptr+aDes.Length(),ERead);
+	}
+
+HDbsReadBuf* HDbsReadBuf::NewL(const TDesC8& aDes)
+	{
+	return new(ELeave) HDbsReadBuf(aDes);
+	}
+
+void HDbsReadBuf::DoRelease()
+	{
+	delete this;
+	}
+
+// Class HDbsStream
+TInt HDbsStream::ReadL(const RMessage2& aMessage)
+	{
+	TInt pos=aMessage.Int0();
+	if (pos!=iRPos)
+		iHost.SeekL(iHost.ERead,EStreamBeginning,pos);
+	iRPos=-1;
+	TInt len=aMessage.Int2();
+	pos+=len;
+	TInt tfr=len;
+	for (;;)
+		{
+		TUint8 buf[KDbsStreamIoSize];
+		TInt read=iHost.ReadL(buf,Min(tfr,KDbsStreamIoSize));
+		if (read==0)
+			break;
+		aMessage.WriteL(1,TPtrC8(buf,read),len-tfr);
+		tfr-=read;
+		if (tfr==0)
+			break;
+		if (read<KDbsStreamIoSize)
+			break;
+		}
+	iRPos=pos-tfr;
+	return len-tfr;
+	}
+
+void HDbsStream::WriteL(const RMessage2& aMessage)
+	{
+	TInt pos=aMessage.Int0();
+	if (pos!=iWPos)
+		iHost.SeekL(iHost.EWrite,EStreamBeginning,pos);
+	iWPos=-1;
+	TInt offset=0;
+	TBuf8<KDbsStreamIoSize> buf;
+	for (;;)
+		{
+		aMessage.ReadL(1,buf,offset);
+		TInt len=buf.Length();
+		if (len==0)
+			break;
+		iHost.WriteL(buf.Ptr(),len);
+		offset+=len;
+		if (len<KDbsStreamIoSize)
+			break;
+		}
+	iWPos=pos+offset;
+	}
+
+// Class HBufBuf
+
+void HBufBuf::DoRelease()
+	{
+	delete this;
+	}
+
+HBufBuf* HBufBuf::NewLC()
+	{
+	HBufBuf* self=new(ELeave) HBufBuf;
+	self->PushL();
+	self->iBuf=CBufSeg::NewL(EGranularity);
+	self->Set(*self->iBuf,0,ERead|EWrite);
+	return self;
+	}
+