/*
 * DbRealTimeData.cpp
 *
 *  Created on: Jan 5, 2011
 *      Author: DS\one55379
 */

#include <stdio.h>
#include <stdlib.h>
#include <sstream>
#include <string.h>

#include "DbRealTimeData.h"
#include "DbUtils.h"
#include "DbQueues.h"
#include "ipfix.h"

/*
 * Tunnel
 */
Tunnel::Tunnel():
    mId(0),
    mTunnelEndpointId(0),
    mCallTraceId(0),
    mTunnelIpPairId(0),
    mInterfaceType(0),
    mStartTime(0)
{
    mLogId = LOG_ID("Tunnel");
}

Tunnel::~Tunnel()
{
}

void Tunnel::reset()
{
    mId = 0;
    mTunnelEndpointId = 0;
    mCallTraceId = 0;
    mTunnelIpPairId = 0;
    mInterfaceType = 0;
    mStartTime = 0;
}

void Tunnel::toFile(ostream& fout)
{
    if  (fout != NULL)
    {
        string mysqlTimestamp;
        // convert time to mysql timestamp
        DbUtils::convertFromUnixTimeToMySqlString(mStartTime, &mysqlTimestamp);

        try
        {
            // must match order of tunnel table.
            fout << mId << "\t" <<  mTunnelEndpointId << "\t" << mCallTraceId << "\t" << mTunnelIpPairId << "\t" << mInterfaceType << "\t" << mysqlTimestamp << endl;
        }
        catch (const exception & ex)
        {
            LOG_ERROR(mLogId,"toFile: Failure to write to file, ostream write failure.");
        }
    }
    else
    {
        LOG_ERROR(mLogId,"toFile: Failure to write to file, NULL ostream found.");
    }

}

/*
 * CallTrace
 */
CallTrace::CallTrace() :
    mId(0),
    mStartTime(0),
    mMsgListOnDisk(0),
    mUeId(0)
{
    mLogId = LOG_ID("CallTrace");
}

void CallTrace::reset()
{
    mId = 0;
    mStartTime = 0;
    mMsgListOnDisk = 0;
    mUeId = 0;
}

void CallTrace::toFile(ostream& fout)
{
    if  (fout != NULL)
    {
        string mysqlTimestamp;
        // convert time to mysql timestamp
        DbUtils::convertFromUnixTimeToMySqlString(mStartTime, &mysqlTimestamp);

        try
        {
            fout << mId << "\t" << mysqlTimestamp << "\t" << mMsgListOnDisk << "\t" << mUeId  << endl;
        }
        catch (const exception & ex)
        {
            LOG_ERROR(mLogId,"toFile: Failure to write to file, ostream write failure.");
        }
    }
    else
    {
        LOG_ERROR(mLogId,"toFile: Failure to write to file, NULL ostream found.");
    }
}


/*
 * Ue
 */
Ue::Ue() :
    mId(0),
    mImsi(""),
    mImei(""),
    mMsisdn(""),
    mDetectTime(0)
{
    mLogId = LOG_ID("Ue");
}

Ue::~Ue()
{
}

void Ue::reset()
{
    mId = 0;
    mImsi.clear();
    mImei.clear();
    mMsisdn.clear();
    mDetectTime = 0;
}

void Ue::toFile(ostream& fout)
{
    if  (fout != NULL)
    {
        string mysqlTimestamp;
        // convert time to mysql timestamp
        DbUtils::convertFromUnixTimeToMySqlString(mDetectTime, &mysqlTimestamp);

        try
        {
            fout << mId << "\t" << mImsi << "\t" << mImei << "\t" << mMsisdn << "\t" << mysqlTimestamp << endl;
        }
        catch (const exception & ex)
        {
            LOG_ERROR(mLogId,"toFile: Failure to write to file, ostream write failure.");
        }
    }
    else
    {
        LOG_ERROR(mLogId,"toFile: Failure to write to file, NULL ostream found.");
    }
}

/*
 * UeUpdate
 */
UeUpdate::UeUpdate() :
    mId(0),
    mUeId(0),
    mNewUeId(0),
    mImsi(""),
    mImei(""),
    mMsisdn("")
{
    mLogId = LOG_ID("UeUpdate");
}

UeUpdate::~UeUpdate()
{
}

void UeUpdate::reset()
{
    mId = 0;
    mUeId = 0;
    mNewUeId = 0;
    mImsi.clear();
    mImei.clear();
    mMsisdn.clear();
}

void UeUpdate::toFile(ostream& fout)
{
    if  (fout != NULL)
    {
        try
        {
            fout << mId << "\t" << mUeId << "\t" << mNewUeId << "\t" << mImsi << "\t" << mImei << "\t" << mMsisdn << endl;
        }
        catch (const exception & ex)
        {
            LOG_ERROR(mLogId,"toFile: Failure to write to file, ostream write failure.");
        }
    }
    else
    {
        LOG_ERROR(mLogId,"toFile: Failure to write to file, NULL ostream found.");
    }
}

/*
 * UeIp
 */
UeIp::UeIp() :
    mId(0),
    mUeId(0),
    mIsIpv6(false),
    mMsIpAddr(0),
    mLsIpAddr(0),
    mInterfaceType(0),
    mDetectTime(0)
{
    mLogId = LOG_ID("UeIp");
}

UeIp::~UeIp()
{
}

void UeIp::reset()
{
    mId = 0;
    mUeId = 0;
    mIsIpv6 = false;
    mMsIpAddr = 0;
    mLsIpAddr = 0;
    mInterfaceType = 0;
    mDetectTime = 0;
}

void UeIp::toFile(ostream& fout)
{
    if  (fout != NULL)
    {
        string mysqlTimestamp;
        // convert time to mysql timestamp
        DbUtils::convertFromUnixTimeToMySqlString(mDetectTime, &mysqlTimestamp);

        try
        {
            fout << mId << "\t" << mUeId << "\t" << mIsIpv6 << "\t" << mMsIpAddr << "\t" << mLsIpAddr << "\t" << mInterfaceType << "\t" << mysqlTimestamp << endl;
        }
        catch (const exception & ex)
        {
            LOG_ERROR(mLogId,"toFile: Failure to write to file, ostream write failure.");
        }
    }
    else
    {
        LOG_ERROR(mLogId,"toFile: Failure to write to file, NULL ostream found.");
    }
}


/*
 * UeIpPart
 */
UeIpPart::UeIpPart() :
    mId(0),
    mUeId(0),
    mCallTraceId(0),
    mIsIpv6(false),
    mMsIpAddr(0),
    mLsIpAddr(0),
    mInterfaceType(0),
    mDetectTime(0),
    mApnId(0),
    mBearerId(0)
{
    mLogId = LOG_ID("UeIpPart");
}

UeIpPart::~UeIpPart()
{
}

void UeIpPart::reset()
{
    mId = 0;
    mUeId = 0;
    mCallTraceId = 0;
    mIsIpv6 = false;
    mMsIpAddr = 0;
    mLsIpAddr = 0;
    mInterfaceType = 0;
    mDetectTime = 0;
    mApnId = 0;
    mBearerId = 0;
}

void UeIpPart::toFile(ostream& fout)
{
    if  (fout != NULL)
    {
        string mysqlTimestamp;
        // convert time to mysql timestamp
        DbUtils::convertFromUnixTimeToMySqlString(mDetectTime, &mysqlTimestamp);

        try
        {
            fout << mId << "\t" << mUeId << "\t" << mCallTraceId << "\t" << mIsIpv6 << "\t" << mMsIpAddr << "\t" << mLsIpAddr << "\t" << mInterfaceType << "\t" << mysqlTimestamp << "\t" << mApnId << '\t' << mBearerId << endl;
        }
        catch (const exception & ex)
        {
            LOG_ERROR(mLogId,"toFile: Failure to write to file, ostream write failure.");
        }
    }
    else
    {
        LOG_ERROR(mLogId,"toFile: Failure to write to file, NULL ostream found.");
    }
}

/*
 * Ip
 */
Ip::Ip() :
    mId(0),
    mIsIpv6(false),
    mMsIpAddr(0),
    mLsIpAddr(0)
{
    mLogId = LOG_ID("Ip");
}

Ip::~Ip()
{
}

void Ip::reset()
{
    mId = 0;
    mIsIpv6 =false;
    mMsIpAddr = 0;
    mLsIpAddr = 0;
}

void Ip::toFile(ostream& fout)
{
    if  (fout != NULL)
    {
        try
        {
            fout << mId << "\t" << mIsIpv6 << "\t" << mMsIpAddr << "\t" << mLsIpAddr << endl;
        }
        catch (const exception & ex)
        {
            LOG_ERROR(mLogId,"toFile: Failure to write to file, ostream write failure.");
        }
    }
    else
    {
        LOG_ERROR(mLogId,"toFile: Failure to write to file, NULL ostream found.");
    }
}

/*
 * NewCall
 */
NewCall::NewCall()
{
    mLogId = LOG_ID("NewCall");
    mCallTrace.reset();
}

void NewCall::toFile(DbFile& access)
{
    mCallTrace.toFile(*access.mCallTraceFile);
}

void NewCall::reset()
{
    mCallTrace.reset();
}


/*
 * CallTraceEnd
 */
CallTraceEnd::CallTraceEnd() :
    mId(0),
    mReason(0),
    mEndTime(0)
{
    mLogId = LOG_ID("CallTraceEnd");
}

CallTraceEnd::~CallTraceEnd()
{
}

void CallTraceEnd::reset()
{
    mId = 0;
    mReason = 0;
    mEndTime = 0;
}

void CallTraceEnd::toFile(ostream& fout)
{
    if  (fout != NULL)
    {
        string mysqlTimestamp;
        // convert time to mysql timestamp
        DbUtils::convertFromUnixTimeToMySqlString(mEndTime, &mysqlTimestamp);

        try
        {
            fout << mId << "\t" << mReason << "\t" << mysqlTimestamp << endl;
        }
        catch (const exception & ex)
        {
            LOG_ERROR(mLogId,"toFile: Failure to write to file, ostream write failure.");
        }
    }
    else
    {
        LOG_ERROR(mLogId,"toFile: Failure to write to file, NULL ostream found.");
    }
}


/*
 * TunnelEnd
 */
TunnelEnd::TunnelEnd() :
    mId(0),
    mReason(0),
    mEndTime(0),
    mTunnelEndpointId(0),
    mCallTraceId(0)
{
    mLogId = LOG_ID("CallTraceEnd");
}

TunnelEnd::~TunnelEnd()
{
}

void TunnelEnd::reset()
{
    mId = 0;
    mReason = 0;
    mEndTime = 0;
    mTunnelEndpointId = 0;
    mCallTraceId = 0;
}

void TunnelEnd::toFile(ostream& fout)
{
    if  (fout != NULL)
    {
        string mysqlTimestamp;
        // convert time to mysql timestamp
        DbUtils::convertFromUnixTimeToMySqlString(mEndTime, &mysqlTimestamp);

        try
        {
            fout << mId << "\t" << mReason << "\t"  << mysqlTimestamp << "\t" << mTunnelEndpointId << "\t" << mCallTraceId << endl;
        }
        catch (const exception & ex)
        {
            LOG_ERROR(mLogId,"toFile: Failure to write to file, ostream write failure.");
        }
    }
    else
    {
        LOG_ERROR(mLogId,"toFile: Failure to write to file, NULL ostream found.");
    }
}



/*
 * APN
 */
Apn::Apn() :
    mId(0),
    mApn("")
{
    mLogId = LOG_ID("APN");
}

Apn::~Apn()
{
}

void Apn::reset()
{
    mId = 0;
    mApn = "";
}

void Apn::toFile(ostream& fout)
{
    if  (fout != NULL)
    {
        try
        {
            fout << mId << "\t" << mApn << endl;
        }
        catch (const exception & ex)
        {
            LOG_ERROR(mLogId,"toFile: Failure to write to file, ostream write failure.");
        }
    }
    else
    {
        LOG_ERROR(mLogId,"toFile: Failure to write to file, NULL ostream found.");
    }
}

/*
 * IpFlow
 */
IpFlow::IpFlow() :
    mId(0),
    mStartTime(0),
    mStartTimePadding(0),
    mEndTime(0),
    mEndTimePadding(0),
    mHWPort(0),
    src_is_ipv6(false),
    ms_src_ip(0),
    ls_src_ip(0),
    dst_is_ipv6(false),
    ms_dst_ip(0),
    ls_dst_ip(0),
    mProtocol(0),
    mSrcPort(0),
    mDstPort(0),
    mIpTOS(0),
    mSrcBytes(0),
    mDstBytes(0),
    mSrcFrames(0),
    mDstFrames(0),
    mPrev(false),
    mNext(false),
    mT1(0),
    mT1Padding(0),
    mT2(0),
    mT2Padding(0),
    mVlan(0),
    mVal1(0),
    mVal2(0),
    mVal3(0),
    mVal4(0)
{
    mLogId = LOG_ID("IpFlow");
    memset(m_IPV4FIXArrayA, 0, sizeof(void*)*16);
    memset(m_IPV4FIXArrayB, 0, sizeof(void*)*16);
    memset(m_IPV4FIXArrayLengths, 0, sizeof(uint16_t)*16);
    reset();
}

IpFlow::~IpFlow()
{
}

void IpFlow::reset()
{
    mId = 0;
    mStartTime = 0;
    mEndTime = 0;
    mHWPort = 0;
    src_is_ipv6 = false;
    ms_src_ip = 0;
    ls_src_ip = 0;
    dst_is_ipv6 = false;
    ms_dst_ip = 0;
    ls_dst_ip = 0;
    mProtocol = 0;
    mSrcPort = 0;
    mDstPort = 0;
    mIpTOS = 0;
    mSrcBytes = 0;
    mDstBytes = 0;
    mSrcFrames = 0;
    mDstFrames = 0;
    mPrev = false;
    mNext = false;
    mT1 = 0;
    mT2 = 0;
    mVlan = 0;
    mVal1=0;
    mVal2=0;
    mVal3=0;
    mVal4=0;
    if((m_IPV4FIXArrayA[0] == NULL) || (m_IPV4FIXArrayA[0] != &mStartTime))
    {
        uint16_t fieldNum = 0;
        addIPFIX_data(fieldNum++, ((uint8_t*)&mStartTime), sizeof(uint32_t));
        addIPFIX_data(fieldNum++, ((uint8_t*)&mEndTime), sizeof(uint32_t));
        addIPFIX_data(fieldNum++, &mHWPort, sizeof(uint16_t));
        addIPFIX_data(true, fieldNum, &ms_src_ip, &ms_dst_ip, sizeof(uint8_t)*16);
        addIPFIX_data(false, fieldNum++, &ls_src_ip, &ls_dst_ip, sizeof(uint8_t)*4);
        addIPFIX_data(true, fieldNum, &ms_dst_ip, &ms_src_ip, sizeof(uint8_t)*16);
        addIPFIX_data(false, fieldNum++, &ls_dst_ip, &ls_src_ip, sizeof(uint8_t)*4);
        addIPFIX_data(fieldNum++, &mProtocol, sizeof(uint16_t));
        addIPFIX_data(true, fieldNum, &mSrcPort, &mDstPort, sizeof(uint16_t));
        addIPFIX_data(false, fieldNum++, &mSrcPort, &mDstPort, sizeof(uint16_t));
        addIPFIX_data(true, fieldNum, &mDstPort, &mSrcPort, sizeof(uint16_t));
        addIPFIX_data(false, fieldNum++, &mDstPort, &mSrcPort, sizeof(uint16_t));
        addIPFIX_data(fieldNum++, &mIpTOS, sizeof(uint16_t));
        addIPFIX_data(true, fieldNum, &mSrcBytes, &mDstBytes, sizeof(uint64_t));
        addIPFIX_data(false, fieldNum++, &mSrcBytes, &mDstBytes, sizeof(uint64_t));
        addIPFIX_data(true, fieldNum, &mSrcFrames, &mDstFrames, sizeof(uint64_t));
        addIPFIX_data(false, fieldNum++, &mSrcFrames, &mDstFrames, sizeof(uint64_t));
        addIPFIX_data(fieldNum++, &mVlan, sizeof(uint16_t));
        addIPFIX_data(true, fieldNum, &mVal1, &mVal2, sizeof(uint64_t));
        addIPFIX_data(false, fieldNum++, &mVal1, &mVal2, sizeof(uint64_t));
        addIPFIX_data(true, fieldNum, &mVal3, &mVal4, sizeof(uint64_t));
        addIPFIX_data(false, fieldNum++, &mVal3, &mVal4, sizeof(uint64_t));
        addIPFIX_data(fieldNum++, ((uint8_t*)&mT1), sizeof(uint32_t));
        addIPFIX_data(fieldNum++, ((uint8_t*)&mT2), sizeof(uint32_t));
    }
}

void IpFlow::toFile(ostream& fout)
{
    if  (fout != NULL)
    {
        string mysqlStart;
        string mysqlEnd;
        string mysqlT1;
        string mysqlT2;
        // convert time to mysql timestamp
        DbUtils::convertFromUnixTimeToMySqlString(mStartTime, &mysqlStart);
        DbUtils::convertFromUnixTimeToMySqlString(mEndTime, &mysqlEnd);
        DbUtils::convertFromUnixTimeToMySqlString(mT1, &mysqlT1);
        DbUtils::convertFromUnixTimeToMySqlString(mT2, &mysqlT2);

        try
        {
            fout << mId << "\t" << mysqlStart << "\t" << mysqlEnd << "\t" << mHWPort << "\t" << src_is_ipv6 << "\t"
                 << ms_src_ip << "\t" << ls_src_ip << "\t" << dst_is_ipv6 << "\t" << ms_dst_ip << "\t" << ls_dst_ip << "\t"
                 << mProtocol << "\t" << mSrcPort << "\t" << mDstPort << '\t' << mIpTOS << '\t'
                 << mSrcBytes << '\t' << mDstBytes << '\t' << mSrcFrames << '\t' << mDstFrames << '\t'
                 << mPrev << '\t' << mNext << '\t'
                 << mysqlT1 << '\t' <<  mysqlT2 << '\t' << mVlan << '\t'
                 << mVal1 << '\t' << mVal2 << '\t' << mVal3 << '\t' << mVal4
                 << endl;
        }
        catch (const exception & ex)
        {
            LOG_ERROR(mLogId,"toFile: Failure to write to file, ostream write failure.");
        }
    }
    else
    {
        LOG_ERROR(mLogId,"toFile: Failure to write to file, NULL ostream found.");
    }
}

// toSummaryFile()
// Generates recprds on the Ip Flow "Summary" file which is a customer readable format with less information.
void IpFlow::toSummaryFile(ostream& fout)
{
    if  (fout != NULL)
    {
        string mysqlStart;
        string mysqlEnd;
        string mysqlT1;
        string mysqlT2;
        // convert time to mysql timestamp
        DbUtils::convertFromUnixTimeToMySqlString(mStartTime, &mysqlStart);
        DbUtils::convertFromUnixTimeToMySqlString(mEndTime, &mysqlEnd);
//        DbUtils::convertFromUnixTimeToMySqlString(mT1, &mysqlT1);
//        DbUtils::convertFromUnixTimeToMySqlString(mT2, &mysqlT2);

        try
        {
            fout << mId << ',' << mysqlStart << ',' << mysqlEnd << ','
                 //  << mHWPort << ',' << src_is_ipv6 << ','
                 //<< ms_src_ip << "\t" << ls_src_ip << "\t" << dst_is_ipv6 << "\t" << ms_dst_ip << "\t" << ls_dst_ip << "\t"
                 << mVlan << ','
                 << (ls_src_ip >> 24) << "." << ((ls_src_ip >> 16) & 0xFF) << "." << ((ls_src_ip >> 8) & 0xFF) << "." << (ls_src_ip & 0xFF) << ','
                 << (ls_dst_ip >> 24) << "." << ((ls_dst_ip >> 16) & 0xFF) << "." << ((ls_dst_ip >> 8) & 0xFF) << "." << (ls_dst_ip & 0xFF) << ','
                 << mProtocol << ',' << mSrcPort << ',' << mDstPort << ',' // << mIpTOS << ','
                 << mSrcBytes << ',' << mDstBytes << ',' << mSrcFrames << ',' << mDstFrames << ','
//                 << mPrev << ',' << mNext << ','
//                 << mysqlT1 << ',' <<  mysqlT2 << ',' << mVlan << ','
                 << mVal1 << ',' << mVal2 // << ','
//                 << mVal3 << ',' << mVal4
                 << endl;
        }
        catch (const exception & ex)
        {
            LOG_ERROR(mLogId,"toFile: Failure to write to file, ostream write failure.");
        }
    }
    else
    {
        LOG_ERROR(mLogId,"toFile: Failure to write to file, NULL ostream found.");
    }
}

void IpFlow::addIPFIX_field(IPFIX_fields_t &fields, uint32_t enumber, uint16_t type, uint16_t length)
{
    IPFIX_field_t field;
    field.enterprise_number = enumber;
    field.type = type;
    field.length = length;
    fields.push_back(field);
}

void IpFlow::addIPFIX_data(bool isIPV6, uint16_t index, void *ptrA, void *ptrB, uint16_t length)
{
    if(isIPV6)
    {
        m_IPV6FIXArrayA[index] = ptrA;
        m_IPV6FIXArrayB[index] = ptrB;
        m_IPV6FIXArrayLengths[index] = length;
    }
    else
    {
        m_IPV4FIXArrayA[index] = ptrA;
        m_IPV4FIXArrayB[index] = ptrB;
        m_IPV4FIXArrayLengths[index] = length;
    }
}

void IpFlow::addIPFIX_data(uint16_t index, void* ptr, uint16_t length)
{
    addIPFIX_data(true, index, ptr, ptr, length);
    addIPFIX_data(false, index, ptr, ptr, length);
}

IPFIX_fields_t IpFlow::getIPV4FIXFields(void)
{
    IPFIX_fields_t fields;
    addIPFIX_field(fields, 0, IPFIX_FT_FLOWSTARTSECONDS, sizeof(uint32_t));
    addIPFIX_field(fields, 0, IPFIX_FT_FLOWENDSECONDS, sizeof(uint32_t));
    addIPFIX_field(fields, 0, IPFIX_FT_PORTID, sizeof(uint16_t));
    addIPFIX_field(fields, 0, IPFIX_FT_SOURCEIPV4ADDRESS, sizeof(uint8_t)*4);
    addIPFIX_field(fields, 0, IPFIX_FT_DESTINATIONIPV4ADDRESS, sizeof(uint8_t)*4);
    addIPFIX_field(fields, 0, IPFIX_FT_PROTOCOLIDENTIFIER, sizeof(uint16_t));
    addIPFIX_field(fields, 0, IPFIX_FT_SOURCETRANSPORTPORT, sizeof(uint16_t));
    addIPFIX_field(fields, 0, IPFIX_FT_DESTINATIONTRANSPORTPORT, sizeof(uint16_t));
    addIPFIX_field(fields, 0, IPFIX_FT_IPCLASSOFSERVICE, sizeof(uint16_t));
    addIPFIX_field(fields, 0, IPFIX_FT_OCTETDELTACOUNT, sizeof(uint64_t));
    addIPFIX_field(fields, 0, IPFIX_FT_PACKETDELTACOUNT, sizeof(uint64_t));
    addIPFIX_field(fields, 0, IPFIX_FT_VLANID, sizeof(uint16_t));
    return fields;
}

IPFIX_fields_t IpFlow::getIPV6FIXFields(void)
{
    IPFIX_fields_t fields;
    addIPFIX_field(fields, 0, IPFIX_FT_FLOWSTARTSECONDS, sizeof(uint32_t));
    addIPFIX_field(fields, 0, IPFIX_FT_FLOWENDSECONDS, sizeof(uint32_t));
    addIPFIX_field(fields, 0, IPFIX_FT_PORTID, sizeof(uint16_t));
    addIPFIX_field(fields, 0, IPFIX_FT_SOURCEIPV6ADDRESS, sizeof(uint8_t)*16);
    addIPFIX_field(fields, 0, IPFIX_FT_DESTINATIONIPV6ADDRESS, sizeof(uint8_t)*16);
    addIPFIX_field(fields, 0, IPFIX_FT_PROTOCOLIDENTIFIER, sizeof(uint16_t));
    addIPFIX_field(fields, 0, IPFIX_FT_SOURCETRANSPORTPORT, sizeof(uint16_t));
    addIPFIX_field(fields, 0, IPFIX_FT_DESTINATIONTRANSPORTPORT, sizeof(uint16_t));
    addIPFIX_field(fields, 0, IPFIX_FT_IPCLASSOFSERVICE, sizeof(uint16_t));
    addIPFIX_field(fields, 0, IPFIX_FT_OCTETDELTACOUNT, sizeof(uint64_t));
    addIPFIX_field(fields, 0, IPFIX_FT_PACKETDELTACOUNT, sizeof(uint64_t));
    addIPFIX_field(fields, 0, IPFIX_FT_VLANID, sizeof(uint16_t));
    return fields;
}

void **IpFlow::getIPV4FIXArrayA(void)
{
    return m_IPV4FIXArrayA;
}

void **IpFlow::getIPV4FIXArrayB(void)
{
    return m_IPV4FIXArrayB;
}

uint16_t *IpFlow::getIPV4FIXArrayLengths(void)
{
    return m_IPV4FIXArrayLengths;
}

void **IpFlow::getIPV6FIXArrayA(void)
{
    return m_IPV6FIXArrayA;
}

void **IpFlow::getIPV6FIXArrayB(void)
{
    return m_IPV6FIXArrayB;
}

uint16_t *IpFlow::getIPV6FIXArrayLengths(void)
{
    return m_IPV6FIXArrayLengths;
}

/*
 * DbRealTimeData
 */

DbRealTimeData::DbRealTimeData() :
    mType(DbRealTimeData::UNDEFINED),
    mIsUpdate(false)
{
    mLogId = LOG_ID("DbRealTimeData");
}

DbRealTimeData::~DbRealTimeData()
{
}

// reset is called by the populate methods.
// reset will set done to false, so that the instance is marked in-use.
void DbRealTimeData::reset()
{
    mType = DbRealTimeData::UNDEFINED;
    mIsUpdate = false;
    mNewCall.reset();
    mTunnel.reset();
    mUe.reset();
    mUeUpdate.reset();
    mUeIp.reset();
    mUeIpPart.reset();
    mIp.reset();
    mCallTraceEnd.reset();
    mTunnelEnd.reset();
    mApn.reset();
    mIpFlow.reset();
}


void DbRealTimeData::setType(eInsertTaskType inType)
{
    mType = inType;
}

DbRealTimeData::eInsertTaskType DbRealTimeData::getType()
{
    return mType;
}

void DbRealTimeData::setIsUpdate(bool value)
{
    mIsUpdate = value;
}

bool DbRealTimeData::isUpdate() const
{
    return mIsUpdate;
}


void DbRealTimeData::populateNewCall( uint64_t callTraceId,
                                      time_t callStartTime,
                                      uint64_t msgListOnDisk,
                                      uint64_t ueId)
{
    reset();
    mType = DbRealTimeData::INSERT_NEWCALL;
    // call_trace
    mNewCall.mCallTrace.mId = callTraceId;
    mNewCall.mCallTrace.mStartTime = callStartTime;
    mNewCall.mCallTrace.mMsgListOnDisk = msgListOnDisk;
    mNewCall.mCallTrace.mUeId = ueId;
}

void DbRealTimeData::populateTunnel(uint64_t tunnelId,
                                    uint64_t tunnelEndpointId,
                                    uint64_t callTraceId,
                                    uint64_t tunnelIpPairId,
                                    int		 interfaceType,
                                    time_t tunnelStartTime)
{
    reset();
    mType = DbRealTimeData::INSERT_TUNNEL;
    // tunnel
    mTunnel.mId = tunnelId;
    mTunnel.mTunnelEndpointId = tunnelEndpointId;
    mTunnel.mCallTraceId = callTraceId;
    mTunnel.mTunnelIpPairId = tunnelIpPairId;
    mTunnel.mInterfaceType = interfaceType;
    mTunnel.mStartTime = tunnelStartTime;
}


void DbRealTimeData::populateUe(uint64_t ueId,
                                string imsi,
                                string imei,
                                string msisdn,
                                time_t detectTime)
{
    reset();
    mType = DbRealTimeData::INSERT_UE;
    mUe.mId = ueId;
    mUe.mImsi = imsi;
    mUe.mImei = imei;
    mUe.mMsisdn = msisdn;
    mUe.mDetectTime = detectTime;
}

void DbRealTimeData::populateUeUpdate(uint64_t ueUpdateId,
                                      uint64_t ueId,
                                      uint64_t newUeId,
                                      string   imsi,
                                      string   imei,
                                      string   msisdn)
{
    reset();
    mType = DbRealTimeData::INSERT_UE_UPDATE;
    mUeUpdate.mId = ueUpdateId;
    mUeUpdate.mUeId = ueId;
    mUeUpdate.mNewUeId = newUeId;
    mUeUpdate.mImsi = imsi;
    mUeUpdate.mImei = imei;
    mUeUpdate.mMsisdn = msisdn;
}

void DbRealTimeData::populateUeIp(uint64_t ueIpId,
                                  uint64_t ueId,
                                  bool isIpv6,
                                  uint64_t msIpAddr,
                                  uint64_t lsIpAddr,
                                  int		 interfaceType,
                                  time_t detectTime)
{
    reset();
    mType = DbRealTimeData::INSERT_UE_IP;
    mUeIp.mId = ueIpId;
    mUeIp.mUeId = ueId;
    mUeIp.mIsIpv6 = isIpv6;
    mUeIp.mMsIpAddr = msIpAddr;
    mUeIp.mLsIpAddr = lsIpAddr;
    mUeIp.mInterfaceType = interfaceType;
    mUeIp.mDetectTime = detectTime;
}

void DbRealTimeData::populateUeIpPart(uint64_t ueIpPartId,
                                      uint64_t ueId,
                                      uint64_t callTraceId,
                                      bool     isIpv6,
                                      uint64_t msIpAddr,
                                      uint64_t lsIpAddr,
                                      int		 interfaceType,
                                      time_t   detectTime,
                                      uint64_t apnId,
                                      int      bearerId)
{
    reset();
    mType = DbRealTimeData::INSERT_UE_IP_PART;
    mUeIpPart.mId = ueIpPartId;
    mUeIpPart.mUeId = ueId;
    mUeIpPart.mCallTraceId = callTraceId;
    mUeIpPart.mIsIpv6 = isIpv6;
    mUeIpPart.mMsIpAddr = msIpAddr;
    mUeIpPart.mLsIpAddr = lsIpAddr;
    mUeIpPart.mInterfaceType = interfaceType;
    mUeIpPart.mDetectTime = detectTime;
    mUeIpPart.mApnId = apnId;
    mUeIpPart.mBearerId = bearerId;
}

void DbRealTimeData::populateIp(uint64_t ipId,
                                bool isIpv6,
                                uint64_t msIpAddr,
                                uint64_t lsIpAddr)
{
    reset();
    mType = DbRealTimeData::INSERT_IP;
    mIp.mId = ipId;
    mIp.mIsIpv6 = isIpv6;
    mIp.mMsIpAddr = msIpAddr;
    mIp.mLsIpAddr = lsIpAddr;
}

void DbRealTimeData::populateCallTraceEnd(uint64_t callTraceEndId,
        uint16_t reason,
        time_t endTime)
{
    reset();
    mType = DbRealTimeData::INSERT_CALL_END;
    mCallTraceEnd.mId = callTraceEndId;
    mCallTraceEnd.mReason = reason;
    mCallTraceEnd.mEndTime = endTime;
}

void DbRealTimeData::populateTunnelEnd(uint64_t tunnelEndId,
                                       uint16_t reason,
                                       time_t endTime,
                                       uint64_t tunnelEndpointId,
                                       uint64_t callTraceId)
{
    reset();
    mType = DbRealTimeData::INSERT_TUNNEL_END;
    mTunnelEnd.mId = tunnelEndId;
    mTunnelEnd.mReason = reason;
    mTunnelEnd.mEndTime = endTime;
    mTunnelEnd.mTunnelEndpointId = tunnelEndpointId;
    mTunnelEnd.mCallTraceId = callTraceId;
}

void DbRealTimeData::populateApn(uint64_t apnId,
                                 string apn)
{
    reset();
    mType = DbRealTimeData::INSERT_APN;
    mApn.mId = apnId;
    mApn.mApn = apn;
}

void DbRealTimeData::populateIpFlow(uint64_t ipFlowId,
                                    time_t startTime,
                                    time_t endTime,
                                    uint16_t hWPort,
                                    bool src_ip_is_ipv6,
                                    uint64_t ms_src_ip,
                                    uint64_t ls_src_ip,
                                    bool dst_ip_is_ipv6,
                                    uint64_t ms_dst_ip,
                                    uint64_t ls_dst_ip,
                                    uint16_t protocol,
                                    uint16_t srcPort,
                                    uint16_t dstPort,
                                    uint16_t ipTOS,
                                    uint64_t src_bytes,
                                    uint64_t dst_bytes,
                                    uint64_t src_frames,
                                    uint64_t dst_frames,
                                    bool prev,
                                    bool next,
                                    time_t t1,
                                    time_t t2,
                                    uint16_t vlan,
                                    uint64_t val1,
                                    uint64_t val2,
                                    uint64_t val3,
                                    uint64_t val4 )
{
    reset();
    mType = DbRealTimeData::INSERT_IP_FLOW;
    mIpFlow.mId = ipFlowId;
    mIpFlow.mStartTime = startTime;
    mIpFlow.mEndTime = endTime;
    mIpFlow.mHWPort = hWPort;
    mIpFlow.src_is_ipv6 = src_ip_is_ipv6;
    mIpFlow.ms_src_ip = ms_src_ip;
    mIpFlow.ls_src_ip = ls_src_ip;
    mIpFlow.dst_is_ipv6 = dst_ip_is_ipv6;
    mIpFlow.ms_dst_ip = ms_dst_ip;
    mIpFlow.ls_dst_ip = ls_dst_ip;
    mIpFlow.mProtocol = protocol;
    mIpFlow.mSrcPort = srcPort;
    mIpFlow.mDstPort = dstPort;
    mIpFlow.mIpTOS = ipTOS;
    mIpFlow.mSrcBytes = src_bytes;
    mIpFlow.mDstBytes = dst_bytes;
    mIpFlow.mSrcFrames = src_frames;
    mIpFlow.mDstFrames = dst_frames;
    mIpFlow.mPrev = prev;
    mIpFlow.mNext = next;
    mIpFlow.mT1 = t1;
    mIpFlow.mT2 = t2;
    mIpFlow.mVlan = vlan;
    mIpFlow.mVal1 = val1;
    mIpFlow.mVal2 = val2;
    mIpFlow.mVal3 = val3;
    mIpFlow.mVal4 = val4;
}

void DbRealTimeData::writeCallDataToFile(DbFile& access)
{
    mNewCall.toFile(access);
}

void DbRealTimeData::writeTunnelDataToFile(DbFile& access)
{
    mTunnel.toFile(*access.mTunnelFile);
}

void DbRealTimeData::writeUeDataToFile(DbFile& access)
{
    mUe.toFile(*access.mUeFile);
}

void DbRealTimeData::writeUeUpdateDataToFile(DbFile& access)
{
    mUeUpdate.toFile(*access.mUeUpdateFile);
}

void DbRealTimeData::writeUeIpDataToFile(DbFile& access)
{
    mUeIpPart.toFile(*access.mUeIpFile);
}

void DbRealTimeData::writeIpDataToFile(DbFile& access)
{
    mIp.toFile(*access.mIpFile);
}

void DbRealTimeData::writeCallTraceEndToFile(DbFile& access)
{
    mCallTraceEnd.toFile(*access.mCallTraceEndFile);
}

void DbRealTimeData::writeTunnelEndToFile(DbFile& access)
{
    mTunnelEnd.toFile(*access.mTunnelEndFile);
}

void DbRealTimeData::writeApnDataToFile(DbFile& access)
{
    mApn.toFile(*access.mApnFile);
}

void DbRealTimeData::writeIpFlowToFile(DbFile& access)
{
    mIpFlow.toFile(*access.mIpFlowFile);
    // NSP - Do not write to the summary file since it is disabled
    //mIpFlow.toSummaryFile(*access.mIpFlowSummaryFile);
}

void **DbRealTimeData::getIPFIXArrayA(void)
{
    if(mIpFlow.src_is_ipv6)
        return mIpFlow.getIPV6FIXArrayA();
    return mIpFlow.getIPV4FIXArrayA();
}

void **DbRealTimeData::getIPFIXArrayB(void)
{
    if(mIpFlow.src_is_ipv6)
        return mIpFlow.getIPV6FIXArrayB();
    return mIpFlow.getIPV4FIXArrayB();
}

uint16_t *DbRealTimeData::getIPFIXArrayLengths(void)
{
    if(mIpFlow.src_is_ipv6)
        return mIpFlow.getIPV6FIXArrayLengths();
    return mIpFlow.getIPV4FIXArrayLengths();
}

bool DbRealTimeData::isIPV6(void)
{
    if(mIpFlow.src_is_ipv6)
        return true;
    return false;
}

uint64_t DbRealTimeData::getPtrToTime(void)
{
    return (uint64_t)&(mIpFlow.mStartTime);
}

string DbRealTimeData::toString() const
{
    // depending on the type, writes the output to a string.
    stringstream myss;
    switch(mType)
    {
    case DbRealTimeData::INSERT_NEWCALL:
        myss << "DbRealTimeData.mType = " << mType << " INSERT_NEWCALL" << endl;
        myss << "mNewCall.mCallTrace.mId = " << mNewCall.mCallTrace.mId << endl;
        myss << "mNewCall.mCallTrace.mStartTime = " <<  mNewCall.mCallTrace.mStartTime << endl;
        myss << "mNewCall.mCallTrace.mMsgListOnDisk = "  << mNewCall.mCallTrace.mMsgListOnDisk << endl;
        myss << "mNewCall.mCallTrace.mUeId = "  << mNewCall.mCallTrace.mUeId << endl;
        break;
    case DbRealTimeData::INSERT_TUNNEL:
        myss << "DbRealTimeData.mType = " << mType << " INSERT_TUNNEL" << endl;
        myss << "mTunnel.mId = " <<  mTunnel.mId << endl;
        myss << "mTunnel.mTunnelEndpointId = " <<  mTunnel.mTunnelEndpointId << endl;
        myss << "mTunnel.mCallTraceId = " << mTunnel.mCallTraceId <<  endl;
        myss << "mTunnel.mTunnelIpPairId = " <<  mTunnel.mTunnelIpPairId << endl;
        myss << "mTunnel.mInterfaceType = " <<  mTunnel.mInterfaceType << endl;
        myss << "mTunnel.mStartTime = " << mTunnel.mStartTime << endl;
        break;
    case DbRealTimeData::INSERT_UE:
        myss << "DbRealTimeData.mType = " << mType << " INSERT_UE" << endl;
        myss << "mUe.mId = " << mUe.mId << endl;
        myss << "mUe.mImsi = " << mUe.mImsi <<  endl;
        myss << "mUe.mImei = " << mUe.mImei << endl;
        myss << "mUe.mMsisdn = " << mUe.mMsisdn << endl;
        myss << "mUe.mDetectTime = " << mUe.mDetectTime << endl;
        myss << "DbRealTimeData.mIsUpdate = " << isUpdate() << endl;
        break;
    case DbRealTimeData::INSERT_UE_UPDATE:
        myss << "DbRealTimeData.mType = " << mType << " INSERT_UE_UPDATE" << endl;
        myss << "mUeUpdate.mId = " << mUeUpdate.mId << endl;
        myss << "mUeUpdate.mUeId = " << mUeUpdate.mUeId <<  endl;
        myss << "mUeUpdate.mNewUeId = " << mUeUpdate.mNewUeId <<  endl;
        myss << "mUeUpdate.mImsi = " << mUeUpdate.mImsi <<  endl;
        myss << "mUeUpdate.mImei = " << mUeUpdate.mImei << endl;
        myss << "mUeUpdate.mMsisdn = " << mUeUpdate.mMsisdn << endl;
        break;
    case DbRealTimeData::INSERT_UE_IP:
        myss << "DbRealTimeData.mType = " << mType << " INSERT_UE_IP" << endl;
        myss << "mUeIp.mId = " << mUeIp.mId << endl;
        myss << "mUeIp.mIsIpv6 = " << mUeIp.mIsIpv6 << endl;
        myss << "mUeIp.mMsIpAddr = " << mUeIp.mMsIpAddr << endl;
        myss << "mUeIp.mLsIpAddr = " << mUeIp.mLsIpAddr << endl;
        myss << "mUeIp.mInterfaceType = " << mUeIp.mInterfaceType << endl;
        myss << "mUeIp.mDetectTime = " << mUeIp.mDetectTime << endl;
        break;
    case DbRealTimeData::INSERT_UE_IP_PART:
        myss << "DbRealTimeData.mType = " << mType << " INSERT_UE_IP_PART" << endl;
        myss << "mUeIpPart.mId = " << mUeIpPart.mId << endl;
        myss << "mUeIpPart.mCallTraceId = " << mUeIpPart.mCallTraceId << endl;
        myss << "mUeIpPart.mIsIpv6 = " << mUeIpPart.mIsIpv6 << endl;
        myss << "mUeIpPart.mMsIpAddr = " << mUeIpPart.mMsIpAddr << endl;
        myss << "mUeIpPart.mLsIpAddr = " << mUeIpPart.mLsIpAddr << endl;
        myss << "mUeIpPart.mInterfaceType = " << mUeIpPart.mInterfaceType << endl;
        myss << "mUeIpPart.mDetectTime = " << mUeIpPart.mDetectTime << endl;
        myss << "mUeIpPart.mApnId = " << mUeIpPart.mApnId << endl;
        myss << "mUeIpPart.mBearerId = " << mUeIpPart.mBearerId << endl;
        break;
    case DbRealTimeData::INSERT_IP:
        myss << "DbRealTimeData.mType = " << mType << " INSERT_IP" << endl;
        myss << "mIp.mId = " << mIp.mId << endl;
        myss << "mIp.mIsIpv6 = " << mIp.mIsIpv6 << endl;
        myss << "mIp.mMsIpAddr = " << mIp.mMsIpAddr << endl;
        myss << "mIp.mLsIpAddr = " << mIp.mLsIpAddr << endl;
        break;
    case DbRealTimeData::INSERT_CALL_END:
        myss << "DbRealTimeData.mType = " << mType << " INSERT_CALL_END" << endl;
        myss << "mCallTraceEnd.mId = " <<  mCallTraceEnd.mId << endl;
        myss << "mCallTraceEnd.mReason = " <<  mCallTraceEnd.mReason << endl;
        myss << "mCallTraceEnd.mEndTime = " << mCallTraceEnd.mEndTime << endl;
        break;
    case DbRealTimeData::INSERT_TUNNEL_END:
        myss << "DbRealTimeData.mType = " << mType << " INSERT_TUNNEL_END" << endl;
        myss << "mTunnelEnd.mId = " <<  mTunnelEnd.mId << endl;
        myss << "mTunnelEnd.mReason = " <<  mTunnelEnd.mReason << endl;
        myss << "mTunnelEnd.mEndTime = " << mTunnelEnd.mEndTime << endl;
        myss << "mTunnelEnd.mTunnelEndpointId = " <<  mTunnelEnd.mTunnelEndpointId << endl;
        myss << "mTunnelEnd.mCallTraceId = " << mTunnelEnd.mCallTraceId <<  endl;
        break;
    case DbRealTimeData::INSERT_APN:
        myss << "DbRealTimeData.mType = " << mType << " INSERT_APN" << endl;
        myss << "DbRealTimeData.mId = " << mApn.mId << endl;
        myss << "DbRealTimeData.mApn = " << mApn.mApn << endl;
        break;
    case DbRealTimeData::INSERT_IP_FLOW:
        myss << "DbRealTimeData.mType = " << mType << " INSERT_IP_FLOW" << endl;
        myss << "mIpFlow.mId = " << mIpFlow.mId << endl;
        myss << "mIpFlow.mStartTime = " << mIpFlow.mStartTime << endl;
        myss << "mIpFlow.mEndTime = " << mIpFlow.mEndTime << endl;
        myss << "mIpFlow.mHWPort = " << mIpFlow.mHWPort << endl;
        myss << "mIpFlow.src_is_ipv6 = " << mIpFlow.src_is_ipv6 << endl;
        myss << "mIpFlow.ms_src_ip = " << mIpFlow.ms_src_ip << endl;
        myss << "mIpFlow.ls_src_ip = " << mIpFlow.ls_src_ip << endl;
        myss << "mIpFlow.dst_is_ipv6 = " << mIpFlow.dst_is_ipv6 << endl;
        myss << "mIpFlow.ms_dst_ip = " << mIpFlow.ms_dst_ip << endl;
        myss << "mIpFlow.ls_dst_ip = " << mIpFlow.ls_dst_ip << endl;
        myss << "mIpFlow.mProtocol = " << mIpFlow.mProtocol << endl;
        myss << "mIpFlow.mSrcPort = " << mIpFlow.mSrcPort << endl;
        myss << "mIpFlow.mDstPort = " << mIpFlow.mDstPort << endl;
        myss << "mIpFlow.mIpTOS = " << mIpFlow.mIpTOS << endl;
        myss << "mIpFlow.mSrcBytes = " << mIpFlow.mSrcBytes << endl;
        myss << "mIpFlow.mDstBytes = " << mIpFlow.mDstBytes << endl;
        myss << "mIpFlow.mSrcFrames = " << mIpFlow.mSrcFrames << endl;
        myss << "mIpFlow.mDStFrames = " << mIpFlow.mDstFrames << endl;
        myss << "mIpFlow.mPrev = " << mIpFlow.mPrev << endl;
        myss << "mIpFlow.mNext = " << mIpFlow.mNext << endl;
        break;
    default:
        myss <<  "undefined type" << endl;
    }
    return myss.str();
}

bool DbRealTimeData::unit_test()
{


    DbRealTimeData calltrace;
    calltrace.populateNewCall(1,time(NULL),2,1);
    LOG_TRACE(mLogId,"unit_test: call_trace: %s.",(calltrace.toString()).c_str());

    //call trace
    if (!((calltrace.mNewCall.mCallTrace.mId == 1) &&
            (calltrace.mNewCall.mCallTrace.mUeId == 1) &&
            (calltrace.mNewCall.mCallTrace.mMsgListOnDisk == 2)))
    {
        return false;
    }

    DbRealTimeData tunnel;
    tunnel.populateTunnel(1,2,3,4,5,time(NULL));
    LOG_TRACE(mLogId,"unit_test: tunnel: %s.",(tunnel.toString()).c_str());
    // tunnel
    if (!((tunnel.mTunnel.mId == 1) &&
            (tunnel.mTunnel.mTunnelEndpointId == 2)  &&
            (tunnel.mTunnel.mCallTraceId == 3) &&
            (tunnel.mTunnel.mTunnelIpPairId == 4) &&
            (tunnel.mTunnel.mInterfaceType == 5)))
    {
        return false;
    }

    // ue
    DbRealTimeData ue;
    ue.populateUe(1,"imsi1","imei1","7196353833",time(NULL));
    LOG_TRACE(mLogId,"unit_test: ue: %s.",(ue.toString()).c_str());


    if (!((ue.mUe.mId == 1) &&
            (ue.mUe.mImsi.compare("imsi1") == 0) &&
            (ue.mUe.mImei.compare("imei1") == 0) &&
            (ue.mUe.mMsisdn.compare("7196353833") == 0)))
    {
        return false;
    }

    // callend
    DbRealTimeData callend;
    time_t tempTime = time(NULL);
    callend.populateCallTraceEnd(1,false, tempTime);
    LOG_TRACE(mLogId,"unit_test: callend: %s.",(callend.toString()).c_str());


    if (!((callend.mCallTraceEnd.mId == 1) &&
            (callend.mCallTraceEnd.mEndTime == tempTime)))
    {
        return false;
    }

    // tunnelend
    DbRealTimeData tunnelend;
    time_t tempTime2 = time(NULL);
    tunnelend.populateTunnelEnd(1,false, tempTime2,1,1);
    LOG_TRACE(mLogId,"unit_test: tunnelend: %s.",(tunnelend.toString()).c_str());


    if (!((callend.mTunnelEnd.mId == 1) &&
            (callend.mTunnelEnd.mEndTime == tempTime2)))
    {
        return false;
    }

    return true;
}







