kernel/eka/debug/crashMonitor/src/scmconfig.cpp
changeset 0 a41df078684a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/debug/crashMonitor/src/scmconfig.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,458 @@
+// Copyright (c) 2008-2009 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:
+// e32\debug\crashMonitor\src\scmconfig.cpp
+// 
+//
+
+/**
+ @file
+ @internalTechnology
+*/
+
+#include <e32err.h>
+#include <e32const.h>
+#include <e32const_private.h>
+
+#include <scmconfig.h>
+#include <scmconfigitem.h>
+#include <scmdatatypes.h>
+
+namespace Debug
+	{
+	/**
+	 * SCMConfiguration constructor
+	 * Initialises the configuration object to default values
+	 */
+	SCMConfiguration::SCMConfiguration() 
+	: iConfigList(NULL)
+		{
+		}
+	
+	/**
+	 * SCMConfiguration destructor
+	 */
+	SCMConfiguration::~SCMConfiguration()
+		{	
+		ClearList();	
+		}
+
+	/**
+	 * Goes to the flash and reads the configuration block and populates the object state
+	 * accordingly
+	 * @return one of the system wide error codes
+	 */
+	TInt SCMConfiguration::Deserialize(TByteStreamReader& aReader)
+		{		
+		if( !iConfigList)
+			{
+			// we need to set up a default configuration to load the data into
+			TInt err = SetDefaultConfig();
+			if(err != KErrNone)
+				{
+				CLTRACE1("SCMConfiguration::Deserialize SetDefaultConfig failed err = %d", err);
+				return err;
+				}
+			}
+		
+		TInt startPos = aReader.CurrentPosition();		
+		
+		TBuf8<10> magicNumbers;
+		// try and read the magic numbers - if they dont exist then 
+		// there is not an scm config there
+		const TInt KLen = KScmConfigHeaderString().Length();
+		for(TInt i=0;i<KLen;i++)
+			{
+			TUint8 b = aReader.ReadByte();			
+			magicNumbers.Append(TChar(b));	
+			}
+		
+		if(magicNumbers.Compare(KScmConfigHeaderString()) != 0)
+			{
+			CLTRACE("No scm, config to read !");
+			return KErrNotReady;
+			}
+				
+		TConfigItem* item = iConfigList;
+		while(item)
+			{
+			item->Deserialize(aReader);
+			item = item->iNext;
+			}
+		
+		TInt endPos = aReader.CurrentPosition();
+		if( endPos - startPos != GetSize())
+			{
+			// error between actual size & real size in data
+			CLTRACE("SCMConfiguration::Deserialize size error");	
+			return KErrCorrupt;
+			}			
+		return KErrNone;			
+		}
+	
+	/**
+	 * This writes the current configuration object state to flash. This configuration will be used on the next crash
+	 * @return one of the system wide error codes
+	 */
+	TInt SCMConfiguration::Serialize(TByteStreamWriter& aWriter)	
+		{		
+		if( !iConfigList)
+			{
+			CLTRACE("SCMConfiguration::Serialize ERROR - NO LIST!!");
+			return KErrNotReady;
+			}
+		
+		TInt startPos = aWriter.CurrentPosition();
+		
+		// write the number of crashes and magic numbers
+		
+		// try and read the magic numbers - if they dont exist then 
+		// there is not an scm config there
+		const TInt KLen = KScmConfigHeaderString().Length();
+		const TDesC8& des = KScmConfigHeaderString();
+		for(TInt i=0;i<KLen;i++)
+			{
+			aWriter.WriteByte(des[i]);
+			}				
+		
+		TConfigItem* item = iConfigList;
+		while(item)
+			{
+			item->Serialize(aWriter);
+			item = item->iNext;
+			}
+
+		TInt endPos = aWriter.CurrentPosition();
+		if( endPos - startPos != GetSize())
+			{
+			// error between actual size & real size in data
+			CLTRACE("SCMConfiguration::Serialize size error");	
+			return KErrCorrupt;
+			}						
+		return KErrNone;
+		}
+	
+	/**
+	 * Returns entire size of the SCMConfiguration block
+	 * @return Size
+	 */
+	TInt SCMConfiguration::GetSize() const
+		{
+		// returns the size of all the config items when serialized to disk / flash
+		return (TConfigItem::ELast * iConfigList->GetSize()) + KScmConfigHeaderString().Length();
+		}
+	
+	/** 
+	 * This will return, one at a time, the highest priority. 
+	 * @see ResetToHighestPriority()
+	 * @param aSizeToDump this will contain the size in bytes of data to dump for this type - 0 means dump all
+	 * @return Data type to dump 
+	 */
+	TConfigItem* SCMConfiguration::GetNextItem()
+		{
+		if(!iNextItem)
+			{
+			return NULL;
+			}
+			
+		//get the values we need
+		TConfigItem* item  = iNextItem;	
+		
+		//Now move iNextItem to be next in the list
+		iNextItem = iNextItem->iNext;			
+		return item;
+		}	
+	
+	/**
+	 * Deletes the linked list
+	 * @return system wide OS code
+	 */
+	void SCMConfiguration::ClearList()
+		{
+		if(!iConfigList)
+			{
+			return;
+			}
+		
+		//all we need to do in here is delete the members of our linked list
+		TConfigItem* item = iConfigList;
+		
+		do{			
+			TConfigItem* tmp = item->iNext;
+			delete item;		
+			item = tmp;		
+		}
+		while(item != NULL);
+		
+		iConfigList = NULL;
+		}
+	
+	/**
+	 * Rather than reading the configuration from the flash, this method sets up the configuration object
+	 * to a default configuration type
+	 * @return one of the system wide error codes
+	 */ 
+	TInt SCMConfiguration::SetDefaultConfig()
+		{
+		//flush the object first
+		ClearList();
+	
+		//This is a predefined default config - in the future we may have multiple defaults based on use case
+		// currently however we use a fixed size list of config items of size TConfigItem::ELast		
+		// also the TSCMDataType of each item must be unique				
+		
+		for(TInt cnt = TConfigItem::ELast - 1; cnt >= 0; cnt --)
+			{			
+			TInt priority = cnt + 1; 
+			
+			//Lets not do these by default
+			if((TConfigItem::TSCMDataType)cnt == TConfigItem::EThreadsUsrStack || (TConfigItem::TSCMDataType)cnt == TConfigItem::EThreadsSvrStack)
+				{
+				priority = 0;
+				}
+			
+			//set it with the priority of its enum (ie. assume that the enum is listed in its priority - it is)
+			//by default dump everything until we run out of space
+			TInt err = CreateConfigItem((TConfigItem::TSCMDataType)cnt, priority, 0);
+			if(KErrNone != err)
+				{
+				return err;
+				}
+			}
+		
+		return KErrNone;		
+		}
+		
+	/**
+	 * This configures the required data for a given configuration item
+	 * Note that aSizeToDump is only used in the case of memory dumps such as stacks
+	 * @param aDataType - Type of data to dump
+	 * @param aPriority - its priority 0-256. 0 Means do not dump and 256 is highest priority
+	 * @param aSizeToDump - amount in bytes to dump. Only relevant for memory dumps and ignored when aPriority is 0
+	 * @return one of the OS wide return codes
+	 */
+	TInt SCMConfiguration::CreateConfigItem(const TConfigItem::TSCMDataType aDataType, const TUint8 aPriority, const TInt32 aSizeToDump)
+		{
+		//create the config item
+		TConfigItem* item = new TConfigItem(aDataType, aPriority, aSizeToDump);
+		
+		//insert to priority list
+		return InsertToList(item);		
+		}
+		
+	
+	/**
+	 * ModifyConfigItemPriority - modifies prioity for a given configuration item
+	 * @param aDataType - The unique type of the config item
+	 * @param aPriority - its priority 0-256. 0 Means do not dump and 256 is highest priority
+	 * @return one of the OS wide return codes
+	 */
+	TInt  SCMConfiguration::ModifyConfigItemPriority(const TConfigItem::TSCMDataType aDataType, const TUint8 aPriority)
+		{
+
+		// find the item with the matching data type
+		TConfigItem* item = iConfigList;		
+		while(item)
+			{
+			if(item->iDataType == aDataType)
+				{
+				break;
+				}
+			item = item->iNext;			
+			}
+	
+		if(!item)
+			{
+			return KErrNotFound;
+			}
+		
+		item->iPriority = aPriority;
+		
+		// now reorder the list according to new priority
+		TInt err = RemoveFromList(item);
+		if(err != KErrNone)
+			{
+			return err;
+			}
+		
+		err = InsertToList(item);
+
+		if(err != KErrNone)
+			{
+			return err;
+			}
+		
+		return KErrNone;
+		}
+
+/**
+ * Removes item from the linked list
+ * @param aItem - item to remove
+ * @return OS code
+ */
+TInt SCMConfiguration::RemoveFromList(TConfigItem* aItem)
+		{
+		if(!aItem)
+			{
+			return KErrArgument;
+			}
+		
+		if(!iConfigList)
+			{
+			return KErrCorrupt;  // oops no list to remove
+			}
+		
+		
+		if(aItem == iConfigList)
+			{
+			// special case remove from beginning of list
+			iConfigList = iConfigList->iNext;
+			return KErrNone;
+			}
+		
+		TConfigItem* item = iConfigList; 
+		while(item)
+			{
+			// is the next item the match ?
+			if(item->iNext == aItem)
+				{
+				item->iNext = aItem->iNext;
+				return KErrNone;
+				}		
+			item = item->iNext;	
+			}
+		
+		return KErrNotFound;	
+		}
+
+/**
+ * Inserts a priority item into the linked list in its correct location
+ * @param aItem - item to insert
+ * @return OS code
+ */
+TInt SCMConfiguration::InsertToList(TConfigItem* aItem)
+	{ 	
+	
+	//if the list is empty, then this is the only item
+	if(!iConfigList)
+		{
+		iConfigList = aItem;			
+		return KErrNone;
+		}
+	
+	//should it go at the start? special case not covered by while loop
+	TConfigItem* temp;
+	
+	if(aItem->iPriority >= iConfigList->iPriority)
+		{
+		temp = iConfigList;
+		iConfigList = aItem;
+		aItem->iNext = temp;
+		return KErrNone;
+		}
+	
+	TConfigItem* item = iConfigList;
+	
+	do{		
+		//if we get to the end of the list and the item still hasnt been assigned then it must be lowest priority
+		if(item->iNext == NULL)
+			{
+			item->iNext = aItem;
+			return KErrNone;
+			}
+		
+		//check if its priority is between these
+		if(aItem->iPriority < item->iPriority && aItem->iPriority >= item->iNext->iPriority)
+			{
+			//insert between these nodes
+			temp = item->iNext;
+			item->iNext = aItem;
+			aItem->iNext = temp;
+			return KErrNone;
+			}
+	
+		item = item->iNext;	
+	}
+	while(item != NULL);	
+	
+	//should never get here
+	return KErrUnknown;
+	}
+	
+/**
+ * This resets the next item counter back to the highest priority item in the list
+ */
+void SCMConfiguration::ResetToHighestPriority()
+	{
+	//set the next item counter back to the head of the list
+	iNextItem = iConfigList;
+	}
+
+/**
+ * Overloaded == operator
+ * @param aOther Item to compare
+ * @return
+ */
+TBool SCMConfiguration::operator == (const SCMConfiguration& aOther) const
+	{
+	
+	if(!iConfigList && !aOther.iConfigList)
+		{
+		return ETrue;
+		}
+	 		
+	if((!iConfigList && aOther.iConfigList) || (iConfigList && !aOther.iConfigList))
+		{
+		return EFalse;
+		}
+	
+	
+	TConfigItem* item1 = iConfigList;
+	TConfigItem* item2 = aOther.iConfigList;
+	
+	while(item1 && item2)
+		{
+		if(!(*item1 == *item2))
+			{
+			return EFalse;
+			}
+		
+		item1 = item1->iNext;			
+		item2 = item2->iNext;			
+		}
+
+	if( item1 != item2)  // both should now be null - if not then lists were different lengths
+		{
+		return EFalse;
+		}
+		
+	return ETrue;
+	
+	}
+ 	
+/**
+ * Getter for the head of the SCMConfig list
+ * @return Head of List
+ */	
+TConfigItem* SCMConfiguration::ConfigList() const
+	{
+	// returns the head of the list	
+	return iConfigList;
+	} 
+} //End of debug namespace
+
+//eof
+
+
+
+