

//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
//_/_/
//_/_/  This file is part of CMSDK version 2.0.0.170915_Beta4 (15 September 2017)
//_/_/  
//_/_/  developed by
//_/_/  
//_/_/  Communicative Machines Ltd. 
//_/_/    http://cmlabs.com/
//_/_/  Copyright (c) 2017
//_/_/  
//_/_/  in collaboration with 
//_/_/  
//_/_/  Icelandic Institute for Intelligent Machines ses
//_/_/    Menntavegur 1
//_/_/    101 Reykjavik
//_/_/    ICELAND
//_/_/    http://www.iiim.is/
//_/_/
//_/_/  and is released under the following
//_/_/  
//_/_/  EXTENDED BSD License
//_/_/
//_/_/  Redistribution and use in source and binary forms, with or without
//_/_/  modification, is permitted provided that the following conditions 
//_/_/  are met:
//_/_/
//_/_/  - Redistributions of source code must retain the above copyright 
//_/_/    and collaboration notice, this list of conditions and the following 
//_/_/    disclaimer.
//_/_/
//_/_/  - Redistributions in binary form must reproduce the above copyright 
//_/_/    notice, this list of conditions and the following disclaimer in the 
//_/_/    documentation and/or other materials provided with the distribution.
//_/_/
//_/_/  - Neither the name of its copyright holders nor the names of its 
//_/_/    contributors may be used to endorse or promote products derived from 
//_/_/    this software without specific prior written permission.
//_/_/
//_/_/  - CADIA Clause: The license granted in and to the software under this 
//_/_/    agreement is a limited-use license. The software may not be used in 
//_/_/    furtherance of: (i) intentionally causing bodily injury or severe 
//_/_/    emotional harm to any person; (ii) invading the personal privacy or 
//_/_/    violating the human rights of any person; or (iii) committing or 
//_/_/    preparing for any act of war. 
//_/_/
//_/_/  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
//_/_/  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
//_/_/  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
//_/_/  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
//_/_/  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
//_/_/  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
//_/_/  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
//_/_/  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
//_/_/  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
//_/_/  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
//_/_/  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//_/_/
//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
#if !defined(_COMPONENTDATA_H_)
#define _COMPONENTDATA_H_

#include "MemoryManager.h"
#include "DataMessage.h"

namespace cmlabs {

#define PARAM_STRING		1
#define PARAM_INTEGER		2
#define PARAM_FLOAT			3
#define PARAM_STRING_COLL	4
#define PARAM_INTEGER_COLL	5
#define PARAM_FLOAT_COLL	6
#define PARAM_TYPE_COLL		3

struct ComponentMapHeader {
	uint32 size; // total size of map structure in bytes
	uint32 count; // number of entries
	uint32 bitFieldSize; // number of bytes in the bitfield
	// Bitfield
	// Entries
};

struct ComponentMapEntry {
	uint32 id; // id corresponds to the index in map
	uint16 nodeID; // id of node component is running on currently
	uint16 procID; // id of process component is running in currently
	uint32 pageID; // Memory Page ID
	uint64 time; // timestamp when entered
	char name[MAXKEYNAMELEN+1]; // name in text
};

struct ComponentStats {
	uint64 time;
	uint64 msgInCount;
	uint64 msgInBytes;
	DataMessageHeader recentInMsg[10];
	uint64 msgOutCount;
	uint64 msgOutBytes;
	DataMessageHeader recentOutMsg[10];
	uint64 runCount;
	uint64 runUserTime;
	uint64 runKernelTime;
};

struct COMPONENTDATAHEADER {
	// Admin
	uint32 size;
	uint32 cid;
	uint16 nodeID; // id of node component is running on currently
	uint16 procID; // id of process component is running in currently
	uint32 pageID;
	// Basic data
	uint64 createdTime;
	uint64 migratedTime;
	uint64 lastUpdateTime;
	char name[MAXKEYNAMELEN]; // name in text
	// Statistics
	ComponentStats stats;
	// Parameters
	uint16 paramCount;
	uint32 paramSize;
	// Private Data
	uint16 dataCount;
	uint32 dataSize;
};

struct PARAMHEADER {
	uint32 size;
	uint8 type;
};

// -- integer --
struct PARAMINTEGERHEADER {
	int64 val;
	int64 defaultVal;
	int64 minVal;
	int64 maxVal;
	int64 interval;
};

// -- float --
struct PARAMFLOATHEADER {
	float64 val;
	float64 defaultVal;
	float64 minVal;
	float64 maxVal;
	float64 interval;
};

// -- string --
//struct PARAMSTRINGHEADER {
//	char* val;
//	char* defaultVal;
//};

// -- integer collection --
struct PARAMCOLLHEADER {
	uint32 index;
	uint32 defaultIndex;
	uint32 count;
};

class ComponentData {
public:
	ComponentData(char* data);
	~ComponentData();

	static bool UnitTest();

	static ComponentData* CreateComponent(uint32 id, const char* name, uint32 size, uint16 nodeID, uint16 procID);
	static bool RecordRemoteComponent(uint32 id, const char* name, uint16 nodeID, uint64 time);
	static bool ReserveComponentID(uint32 id, const char* name);
	static bool DestroyComponent(uint32 cid);
	static ComponentData* GetComponentData(uint32 cid);
	static bool GetComponentName(uint32 cid, char* name, uint32 maxNameLen);
	static bool GetComponentID(const char* name, uint32 &cid);
	static ComponentStats GetComponentStats(uint32 cid);
	static bool SetComponentStats(uint32 cid, ComponentStats& stats);
	static bool IsComponentLocal(uint32 cid);
	static bool IsComponentLocal(const char* name);
	static uint16 GetComponentNodeID(uint32 cid);
	static uint16 GetComponentProcessID(uint32 cid);
	static char* GetAndRemoveComponent(uint32 cid, uint32& dataSize);
	static bool AddExistingComponent(uint32 cid, uint16 nodeID, uint16 procID, char* oldData, uint32 dataSize);
	static bool UpdateRemoteComponent(uint32 cid, uint16 nodeID, uint16 procID, const char* name);
	static bool AddComponentStats(uint32 cid, uint64 userCPU, uint64 kernelCPU,
		DataMessage* inputMsg, DataMessage* outputMsg, uint32 runCount);


	bool disconnect();
	bool destroyComponent();
	bool resize(uint32 increase);
	uint32 getAvailableDataSize();

	// Private Data
	bool setPrivateData(const char* name, const char* data, uint32 size);
	uint32 getPrivateDataSize(const char* name);
	bool getPrivateDataCopy(const char* name, char* data, uint32 maxSize);
	bool replacePrivateData(const char* name, const char* data, uint32 size);
	bool replacePrivateData(const char* name, const char* data, uint32 size, uint32 offset);
	bool deletePrivateData(const char* name);

	// Parameters
	bool createParameter(const char* name, const char* val, const char* defaultValue = NULL);
	bool createParameter(const char* name, const char* val, uint32 count, uint32 defaultIndex);
	bool createParameter(const char* name, std::vector<std::string> values, const char* defaultValue = NULL);
	bool createParameter(const char* name, int64* val, uint32 count, uint32 defaultIndex);
	bool createParameter(const char* name, std::vector<std::string> values, int64 defaultValue = 0);
	bool createParameter(const char* name, float64* val, uint32 count, uint32 defaultIndex);
	bool createParameter(const char* name, std::vector<std::string> values, float64 defaultValue = 0);
	bool createParameter(const char* name, int64 val, int64 min = 0, int64 max = 0, int64 interval = 0);
	bool createParameter(const char* name, float64 val, float64 min = 0, float64 max = 0, float64 interval = 0);

	bool hasParameter(const char* name);
	bool deleteParameter(const char* name);

	uint8 getParameterDataType(const char* name);
	uint32 getParameterValueSize(const char* name);
	bool getParameter(const char* name, char* val, uint32 maxSize);
	bool getParameter(const char* name, int64& val);
	bool getParameter(const char* name, float64& val);

	bool setParameter(const char* name, const char* val);
	bool setParameter(const char* name, int64 val);
	bool setParameter(const char* name, float64 val);

	bool resetParameter(const char* name);
	bool tweakParameter(const char* name, int32 tweak);

private:
	static ComponentMapEntry* GetAndLockComponentEntry(uint32 id);
	static bool UnlockComponentMap();

	static bool InsertComponentPageID(uint32 cid, uint32 pageID, uint16 nodeID, uint16 procID, const char* name);
	static bool GetComponentPageID(uint32 cid, uint32& pageID);
	static bool GetNextAvailableComponentID(uint32& cid);
	static bool FreeComponentID(uint32 cid);

	char* makeRoomForPrivateData(uint32 newSize);
	char* makeRoomForParameter(uint32 newSize);
	struct COMPONENTDATAHEADER* header;
};

} // namespace cmlabs

#endif //_COMPONENTDATA_H_

