/***************************************************************************
                   Shared Memory (using ARP) Class ( SharedMemAPR.cpp )
                -----------------------------------------

	begin      : 2015/03/18
	copyright  : (C) 2013 Solbox Inc.
	author     : Development 1 Team
					- 2015/03/18 - 1st dadamin
	email      : storage.sd@solbox.com
	version    : 3.5.0

	CopyRight(C) 2005 Solbox Inc. All Rights reserved.
	Redistribution and use in source and binary forms, with or with out
	modification, are not permitted in outside of Solbox Inc.
***************************************************************************/
#include "SharedMemAPR.h"

#include "Logger.h"

CSharedMem::CSharedMem()
	: is_attach(false), m_mem(NULL), m_shm(NULL), m_pool(NULL)
{
}

CSharedMem::~CSharedMem()
{
}

bool CSharedMem::Create(const char *filename, int allocSize, apr_pool_t *pool)
{
	ostringstream msg;
	if (Attach(filename, allocSize, pool, false))
		return true;

	// Delete shared memory files generated during abnormal termination.
	apr_shm_remove(filename, pool);

	apr_status_t sts = apr_shm_create(&m_shm, allocSize, filename, pool);

	if (sts != APR_SUCCESS)
	{
		msg << "cannot attach & create shared memory [" << filename << "]";
		LOG(LERR, "%s", msg.str().c_str());
		cerr  << msg.str() << endl;
		return false;
	}

	if (!EqualAllocSize(allocSize))
	{
		apr_shm_detach(m_shm);
		msg << "size not match(create). request size " << allocSize << " alloced size " 
			<< apr_shm_size_get(m_shm) << " [" << filename << "]";
		LOG(LERR, "%s", msg.str().c_str());
		cerr << msg.str() << endl;
		return false;
	}

	m_mem = apr_shm_baseaddr_get(m_shm);
	if (m_mem == NULL)
	{
		msg << "cannot find shared memory address(create) [" << filename << "]";
		LOG(LERR, "%s", msg.str().c_str());
		cerr << msg.str() << endl;
		return false;
	}

	Clear();
	m_shm_key = filename;
	return true;
}

bool CSharedMem::Attach(const char *filename, int allocSize, apr_pool_t *pool, bool outlog)
{
	ostringstream msg;
	apr_status_t sts = apr_shm_attach(&m_shm, filename, pool);
	if (sts != APR_SUCCESS)
	{
		if (outlog)
		{
			msg << "cannot attach shared memory [" << filename << "]";
			LOG(LERR, "%s", msg.str().c_str());
			cerr << msg.str() << endl;
		}
		return false;
	}

	if (!EqualAllocSize(allocSize))
	{
		apr_shm_detach(m_shm);
		if (outlog)
		{
			msg << "size not match(attach). request size " << allocSize << " alloced size " 
				<< apr_shm_size_get(m_shm) << " [" << filename << "]";
			LOG(LERR, "%s", msg.str().c_str());
			cerr << msg.str() << endl;
		}
		return false;
	}

	m_mem = apr_shm_baseaddr_get(m_shm);

	if (m_mem == NULL)
	{
		apr_shm_detach(m_shm);
		if (outlog)
		{
			msg << "cannot find shared memory address(attach) [" << filename << "]";
			LOG(LERR, "%s", msg.str().c_str());
			cerr << msg.str() << endl;
		}
		return false;
	}

	m_shm_key = filename;
	return true;
}

bool CSharedMem::Attach(const char *filename, int allocSize, apr_pool_t *pool)
{
	return Attach(filename, allocSize, pool, true);
}

void CSharedMem::Detach()
{
	if (m_shm)
		apr_shm_detach(m_shm);
}

void CSharedMem::Destroy()
{
	if (m_shm)
		apr_shm_destroy(m_shm);
}

int CSharedMem::GetSize()
{
	return (int)apr_shm_size_get(m_shm);
}

bool CSharedMem::EqualAllocSize(int allocSize)
{
	return	((int)apr_shm_size_get(m_shm) == allocSize);
}

void CSharedMem::Clear()
{
	if( m_mem != NULL)
		memset(m_mem, 0, apr_shm_size_get(m_shm));
}
