using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.IO;    // Directory
using System.Threading; // Thread

namespace Post
{
    public class TracingFunc
    {
        public string logMessage;

        // tracing 처리 전역변수
        public string traceAlias;
        public string tracePath;
        public string traceFile;
        public long traceTotalLength;
        public long traceCurPosition;
        public int traceIndex;
        public byte[] traceData;
        public Struct.TracingFileHeader constTracingFileHeader;

        // log 전역변수
        public string loggerType;
        public string loggerAlias;
        public object loggerConfig;

        public TracingFunc(string loggerType, string loggerAlias, object loggerConfig)
        {
            traceAlias = "";
            tracePath = "";
            traceFile = "";
            traceTotalLength = 0;
            traceCurPosition = 0;
            traceIndex = 0;
            this.loggerType = loggerType;
            this.loggerAlias = loggerAlias;
            this.loggerConfig = loggerConfig;
        }


        #region InitActLoader() : tracing file 존재 체크하고 position 초기화 => load 에 사용
        public int InitActLoader(string alias, string path)
        {
            Console.WriteLine("InitActLoader in");
            int result = 1;
            try
            {
                ConstValues constValues = new ConstValues();
                ConstValuesTracing constValuesTracing = new ConstValuesTracing();
                string[] arrPath = null;
                try
                {
                    arrPath = Directory.GetFiles(path);
                }
                catch (Exception e)
                {
                    Console.WriteLine("trc path error : " + e.ToString());
                }

                if (arrPath != null && arrPath.Length > 0)
                {
                    Console.WriteLine("arrPath length : " + arrPath.Length);
                    Array.Sort(arrPath, StringComparer.InvariantCulture);
                    for (int i = 0; i < arrPath.Length; i++)
                    {
                        string[] arr = arrPath[i].Split('\\');
                        string[] arrFile = arr.Last().Split('_');
                        string fileName = arrFile.First().ToString();

                        if (fileName.Equals(alias))
                        {
                            result = 1;
                            traceAlias = alias;
                            tracePath = path + "\\";
                            traceCurPosition = constValuesTracing.CONST_STRUCT_SIZE_FILEHEADER;
                            break;
                        }

                        arr = null;
                        arrFile = null;
                        fileName = null;
                    }
                }

                arrPath = null;
            }
            catch (Exception e)
            {
                //logMessage = "[System Exception] TracingFunc InitActLoader() exception : " + ex.Message.ToString();
                //constFunc.WriteLog(constValues.CONST_LOGGER_TYPE_FATAL, logMessage, loggerType, loggerAlias, loggerConfig);
                result = -99;
            }

            Console.WriteLine("InitActLoader out");
            return result;
        }
        #endregion

        #region SearchFileSCN() : dsn 에 해당하는 file 찾음
        public long SearchFileSCN(UInt32 high, UInt32 wrap, UInt32 base_n, uint txIndex, bool isReadingTx, int inputNum = 0)
        {
            ConstFunc constFunc = new ConstFunc();
            ConstValues constValues = new ConstValues();
            ConstValuesTracing constValuesTracing = new ConstValuesTracing();

            // isReadingTx : 새로 시작하거나 tx 끝을 처리했으면 더큰 scn 의 record 를 읽고 transaction 처리중이면 더큰 tx_index 값을 가진 record 찾음
            long result = -1;
            try
            {
                Struct.ACDSN dsn = new Struct.ACDSN(high, wrap, base_n);
                // 파일리스트 구함
                List<string> pathList = new List<string>();

                Console.WriteLine("==============================");
                if (tracePath != null && tracePath.Length > 0)
                {
                    string[] arrPath = Directory.GetFiles(tracePath);
                    Console.WriteLine("arrpath len : " + arrPath.Length);
                    if (arrPath != null)
                    {
                        Array.Sort(arrPath, StringComparer.InvariantCulture);

                        int fileNum;
                        if (!isReadingTx)
                        {
                            if (traceFile.Length == 0)
                            {
                                // 처음 시작
                                fileNum = 0;
                            }
                            else
                            {
                                // commit 이후
                                string[] arr_1 = traceFile.Split('_');
                                string[] arr_2 = arr_1.Last().Split('.');
                                fileNum = Int32.Parse(arr_2[0]);     // commit 이후 delay 로 인한 경우도 있으므로 현재 파일을 가리킴

                                arr_1 = null;
                                arr_2 = null;
                            }
                        }
                        else
                        {
                            if (traceFile.Length == 0)
                            {
                                fileNum = 0;
                            }
                            else
                            {
                                // commit 미처리
                                string[] arr_1 = traceFile.Split('_');
                                string[] arr_2 = arr_1.Last().Split('.');
                                fileNum = Int32.Parse(arr_2[0]) + 1;      // commit 미처리인 경우는 파일이어서 작성된 경우이므로 다음 파일을 가리킴

                                arr_1 = null;
                                arr_2 = null;
                            }
                        }

                        for (int i = 0; i < arrPath.Length; i++)
                        {
                            string[] arr = arrPath[i].Split('\\');
                            string[] arrTemp = arr.Last().Split('.');
                            string[] arrFile = arrTemp.First().Split('_');
                            string fileName = arrFile.First().ToString();
                            int tempNum = Int32.Parse(arrFile.Last().ToString());

                            if (fileName.Equals(traceAlias))
                            {
                                if (inputNum > 0)
                                {
                                    if (inputNum == tempNum)
                                        pathList.Add(arrPath[i]);     // 특정 번호 파일 로드함
                                }
                                else
                                {
                                    pathList.Add(arrPath[i]);
                                }
                            }

                            arr = null;
                            arrTemp = null;
                            arrFile = null;
                            fileName = null;
                        }

                        byte[] arrData = null;
                        Console.WriteLine("pathList count : " + pathList.Count);
                        for (int i = 0; i < pathList.Count; i++)
                        {
                            Console.WriteLine("pathList : " + pathList[i]);
                            string[] arrAll = pathList[i].Split('\\');
                            string[] arrTemp = arrAll.Last().Split('.');
                            string[] arrFile = arrTemp.First().Split('_');
                            int tempNum = Int32.Parse(arrFile.Last().ToString());
                            Console.WriteLine("tempNum : " + tempNum);

                            // 1. 이전 파일은 패스함
                            // 2. 다음 파일없는 마지막 파일인 경우
                            if (tempNum >= fileNum || i == pathList.Count - 1)
                            {
                                // trace file stream 읽음
                                arrData = null;

                                if (!File.Exists(pathList[i]))
                                {
                                    constFunc.WriteLog(constValues.CONST_LOGGER_TYPE_DEBUG, "SearchFileSCN() : Trace file is not exist. Path : " + pathList[i], loggerType, loggerAlias, loggerConfig);
                                    break;
                                }

                                bool isRead = false;
                                while (!isRead)
                                {
                                    while (!constFunc.IsFileReady(pathList[i]))
                                    {
                                        // wait for trace file ready
                                        Thread.Sleep(100);
                                    }

                                    try
                                    {
                                        using (var fs = File.Open(pathList[i], FileMode.Open, FileAccess.Read, FileShare.Read))
                                        {
                                            arrData = new byte[fs.Length];
                                            fs.Read(arrData, 0, (int)fs.Length);
                                            Console.WriteLine("file read");
                                            isRead = true;
                                        }
                                    }
                                    catch
                                    {
                                        isRead = false;
                                        Thread.Sleep(100);
                                    }
                                }

                                traceTotalLength = arrData.Length;
                                Struct.TracingRecordHeaderTransaction recordIncludeHeaderTransaction = new Struct.TracingRecordHeaderTransaction();
                                while ((traceTotalLength == constValuesTracing.CONST_STRUCT_SIZE_FILEHEADER) || (traceCurPosition < traceTotalLength))
                                {
                                    Console.WriteLine("arrData.Length : " + arrData.Length);
                                    // trace file header 구함     
                                    if (arrData != null && arrData.Length > 0)
                                    {
                                        Struct.TracingRecordBracket bracket = GetTracingRecordBracket(arrData, constValues.CONST_BRACKET_TYPE_OPENER, 0, traceCurPosition);

                                        if (bracket != null)
                                        {
                                            Console.WriteLine("bracket.length : " + bracket.length);
                                            recordIncludeHeaderTransaction = GetTracingRecordHeaderTransaction(arrData, bracket.length);
                                            Console.WriteLine("333333 : " + recordIncludeHeaderTransaction);
                                            if (recordIncludeHeaderTransaction != null)
                                            {
                                                if (!isReadingTx)
                                                {
                                                    // 새로 모듈 start 하거나 commit 되면 같거나 작은 dsn은 패스함
                                                    if (CompareDsn(dsn, recordIncludeHeaderTransaction.transaction.commit_dsn) == -1)
                                                    {
                                                        result = (long)recordIncludeHeaderTransaction.transaction.commit_dsn.base_n;
                                                        string[] arr = pathList[i].Split('\\');
                                                        traceFile = arr.Last().TrimStart().TrimEnd();

                                                        arr = null;
                                                        break;
                                                    }
                                                    else
                                                    {
                                                        traceCurPosition += (constValuesTracing.CONST_STRUCT_SIZE_BRACKET * 2) + bracket.length;
                                                        traceIndex = bracket.index;
                                                    }
                                                }
                                                else
                                                {
                                                    int compare = CompareDsn(dsn, recordIncludeHeaderTransaction.transaction.commit_dsn);
                                                    if (compare == -1)
                                                    {
                                                        // commit 미완료인 경우 큰 dsn 이면 확정함
                                                        result = (long)recordIncludeHeaderTransaction.transaction.commit_dsn.base_n;
                                                        string[] arr = pathList[i].Split('\\');
                                                        traceFile = arr.Last().TrimStart().TrimEnd();

                                                        arr = null;
                                                        break;
                                                    }
                                                    else if (compare == 0)
                                                    {
                                                        if (traceCurPosition == constValuesTracing.CONST_STRUCT_SIZE_FILEHEADER)
                                                        {
                                                            // transaction 중간에서 trace file 의 첫 레코드이면 이어서 read 하고 있음
                                                            result = (long)recordIncludeHeaderTransaction.transaction.commit_dsn.base_n;
                                                            string[] arr = pathList[i].Split('\\');
                                                            traceFile = arr.Last().TrimStart().TrimEnd();

                                                            arr = null;
                                                            break;
                                                        }
                                                        else
                                                        {
                                                            // 이전에 마지막까지 read 한것 tracefile 크기가 최대 크기가 아니고
                                                            // commit 미완료인 경우 같은 dsn 이면 index 가 크면 확정함
                                                            // definition, lob record 는 tx_index 가 고정되어 있음
                                                            byte recordType = recordIncludeHeaderTransaction.header.trc_record_type;
                                                            if (recordType != null && recordType != constValuesTracing.CONST_RECORD_TYPE_DEFINITION && recordType != constValuesTracing.CONST_RECORD_TYPE_LOB)
                                                            {
                                                                if (recordIncludeHeaderTransaction.header.tx_index > txIndex)
                                                                {
                                                                    // commit 미완료인 경우 큰 txindex 이면 확정함                                                            
                                                                    result = (long)recordIncludeHeaderTransaction.transaction.commit_dsn.base_n;
                                                                    string[] arr = pathList[i].Split('\\');
                                                                    traceFile = arr.Last().TrimStart().TrimEnd();

                                                                    arr = null;
                                                                    break;
                                                                }
                                                                else
                                                                {
                                                                    traceCurPosition += (constValuesTracing.CONST_STRUCT_SIZE_BRACKET * 2) + bracket.length;
                                                                    traceIndex = bracket.index;
                                                                }
                                                            }
                                                            else if (recordType != null && (recordType == constValuesTracing.CONST_RECORD_TYPE_DEFINITION || recordType == constValuesTracing.CONST_RECORD_TYPE_LOB))
                                                            {
                                                                // commit 미완료이고 definition 이나 lob 는 tx_index 고정되어 있으므로 확정함
                                                                result = (long)recordIncludeHeaderTransaction.transaction.commit_dsn.base_n;
                                                                string[] arr = pathList[i].Split('\\');
                                                                traceFile = arr.Last().TrimStart().TrimEnd();

                                                                arr = null;
                                                                break;
                                                            }
                                                            else
                                                            {
                                                                traceCurPosition += (constValuesTracing.CONST_STRUCT_SIZE_BRACKET * 2) + bracket.length;
                                                                traceIndex = bracket.index;
                                                            }
                                                        }
                                                    }
                                                    else
                                                    {
                                                        traceCurPosition += (constValuesTracing.CONST_STRUCT_SIZE_BRACKET * 2) + bracket.length;
                                                        traceIndex = bracket.index;
                                                    }
                                                }
                                            }
                                            else
                                            {
                                                break;
                                            }
                                        }
                                        else
                                        {
                                            break;
                                        }

                                        bracket = null;
                                    }
                                    else
                                    {
                                        constFunc.WriteLog(constValues.CONST_LOGGER_TYPE_DEBUG, "SearchFileSCN() : Trace data length is 0.", loggerType, loggerAlias, loggerConfig);
                                        break;
                                    }
                                }
                                if (result == -1)
                                {
                                    traceCurPosition = constValuesTracing.CONST_STRUCT_SIZE_FILEHEADER;
                                    traceIndex = 0;
                                    traceData = null;
                                }
                                else
                                {
                                    break;
                                }

                                recordIncludeHeaderTransaction = null;
                            }

                            arrAll = null;
                            arrTemp = null;
                            arrFile = null;
                        }

                        arrData = null;
                    }
                    else
                    {
                        constFunc.WriteLog(constValues.CONST_LOGGER_TYPE_DEBUG, "SearchFileSCN() : Trace file directory get failed. Path : " + tracePath, loggerType, loggerAlias, loggerConfig);
                    }

                    arrPath = null;
                }
                else
                {
                    return -1;
                }

                dsn = null;
                pathList = null;
            }
            catch (Exception ex)
            {
                logMessage = "[System Exception] TracingFunc SearchFileSCN() exception : " + ex.Message.ToString();
                constFunc.WriteLog(constValues.CONST_LOGGER_TYPE_FATAL, logMessage, loggerType, loggerAlias, loggerConfig);
                return -99;
            }

            return result;
        }
        #endregion

        #region GetTracingRecordBracket() : tracing bracket 구함
        public Struct.TracingRecordBracket GetTracingRecordBracket(byte[] arrData, string type, long recordDataSize, long tracePosition)    // recordDataSize 는 closer 구할때 쓰임
        {
            ConstValues constValues = new ConstValues();
            ConstValuesTracing constValuesTracing = new ConstValuesTracing();
            Struct.TracingRecordBracket result = new Struct.TracingRecordBracket();

            try
            {
                byte[] buffer;
                byte[] temp;
                int position = 0;

                if (type.Equals(constValues.CONST_BRACKET_TYPE_OPENER))
                {
                    unsafe
                    {
                        if (arrData.Length < (tracePosition + constValuesTracing.CONST_STRUCT_SIZE_BRACKET))
                        {
                            return null;
                        }

                        buffer = new byte[constValuesTracing.CONST_STRUCT_SIZE_BRACKET];
                        for (int i = 0; i < constValuesTracing.CONST_STRUCT_SIZE_BRACKET; i++)
                            buffer[i] = arrData[tracePosition + i];

                        // index
                        temp = new byte[4];
                        for (int i = 0; i < 4; i++)
                        {
                            temp[i] = buffer[position];
                            position++;
                        }
                        result.index = BitConverter.ToInt32(temp, 0);

                        // flag
                        temp = new byte[2];
                        for (int i = 0; i < 2; i++)
                        {
                            temp[i] = buffer[position];
                            position++;
                        }
                        result.flag = BitConverter.ToInt16(temp, 0);

                        // unused
                        temp = new byte[2];
                        for (int i = 0; i < 2; i++)
                        {
                            temp[i] = buffer[position];
                            position++;
                        }
                        result.unused = BitConverter.ToInt16(temp, 0);

                        // length
                        temp = new byte[4];
                        for (int i = 0; i < 4; i++)
                        {
                            temp[i] = buffer[position];
                            position++;
                        }
                        result.length = BitConverter.ToUInt32(temp, 0);
                    }
                }
                else if (type.Equals(constValues.CONST_BRACKET_TYPE_CLOSER))
                {
                    unsafe
                    {
                        if (arrData.Length < (tracePosition + constValuesTracing.CONST_STRUCT_SIZE_BRACKET + recordDataSize + constValuesTracing.CONST_STRUCT_SIZE_BRACKET))
                        {
                            return null;
                        }

                        buffer = new byte[constValuesTracing.CONST_STRUCT_SIZE_BRACKET];
                        for (int i = 0; i < constValuesTracing.CONST_STRUCT_SIZE_BRACKET; i++)
                            buffer[i] = arrData[tracePosition + constValuesTracing.CONST_STRUCT_SIZE_BRACKET + recordDataSize + i];

                        // index
                        temp = new byte[4];
                        for (int i = 0; i < 4; i++)
                        {
                            temp[i] = buffer[position];
                            position++;
                        }
                        result.index = BitConverter.ToInt32(temp, 0);

                        // flag
                        temp = new byte[2];
                        for (int i = 0; i < 2; i++)
                        {
                            temp[i] = buffer[position];
                            position++;
                        }
                        result.flag = BitConverter.ToInt16(temp, 0);

                        // unused
                        temp = new byte[2];
                        for (int i = 0; i < 2; i++)
                        {
                            temp[i] = buffer[position];
                            position++;
                        }
                        result.unused = BitConverter.ToInt16(temp, 0);

                        // length
                        temp = new byte[4];
                        for (int i = 0; i < 4; i++)
                        {
                            temp[i] = buffer[position];
                            position++;
                        }
                        result.length = BitConverter.ToUInt32(temp, 0);
                    }
                }

                buffer = null;
                temp = null;
            }
            catch (Exception e)
            {
                return null;
            }

            return result;
        }
        #endregion

        #region GetTracingRecordHeaderTransaction() : tracing record header-transaction 를 구함
        public Struct.TracingRecordHeaderTransaction GetTracingRecordHeaderTransaction(byte[] arrData, long size)
        {
            Console.WriteLine("----GetTracingRecordHeaderTransaction----");
            ConstFunc constFunc = new ConstFunc();
            ConstValues constValues = new ConstValues();
            ConstValuesTracing constValuesTracing = new ConstValuesTracing();
            Struct.TracingRecordHeaderTransaction result = new Struct.TracingRecordHeaderTransaction();
            try
            {
                byte[] buffer;    // 디버깅부분

                unsafe
                {
                    Console.WriteLine("arrData.Length : " + arrData.Length);
                    Console.WriteLine("### " + (traceCurPosition + constValuesTracing.CONST_STRUCT_SIZE_BRACKET + size));
                    if (arrData.Length < (traceCurPosition + constValuesTracing.CONST_STRUCT_SIZE_BRACKET + size))
                    {
                        return null;
                    }

                    buffer = new byte[size];
                    for (int i = 0; i < size; i++)
                    {

                        buffer[i] = arrData[traceCurPosition + constValuesTracing.CONST_STRUCT_SIZE_BRACKET + i];
                    }

                    StructMessagepack.TracingRecordHeaderTransaction record = MessagePack.MessagePackSerializer.Deserialize<StructMessagepack.TracingRecordHeaderTransaction>(buffer);
                    Console.WriteLine("!!!! schema : " + Encoding.Default.GetString(record.header.schema));
                    result = ConvertHeaderTransactionMsgpackStructToConstStruct(record);

                    record.header.object_n = null;
                    record.header.schema = null;
                    record.transaction.rowid = null;
                    record.transaction.tx_id = null;
                }

                buffer = null;
            }
            catch (Exception ex)
            {
                logMessage = "[System Exception] TracingFunc GetTracingRecordHeaderTransaction() exception : " + ex.Message.ToString();
                constFunc.WriteLog(constValues.CONST_LOGGER_TYPE_FATAL, logMessage, loggerType, loggerAlias, loggerConfig);
                return null;
            }

            return result;
        }
        #endregion

        #region CompareDsn() : dsn 을 비교함
        public int CompareDsn(Struct.ACDSN srcDsn, Struct.ACDSN tarDsn)
        {
            ConstFunc constFunc = new ConstFunc();
            ConstValues constValues = new ConstValues();
            // src > tar 1, 같으면 0, src < tar -1 리턴

            int result = -99;
            try
            {
                if (srcDsn.high > tarDsn.high)
                {
                    result = 1;
                }
                else if (srcDsn.high < tarDsn.high)
                {
                    result = -1;
                }
                else
                {
                    if (srcDsn.wrap > tarDsn.wrap)
                    {
                        result = 1;
                    }
                    else if (srcDsn.wrap < tarDsn.wrap)
                    {
                        result = -1;
                    }
                    else
                    {
                        if (srcDsn.base_n > tarDsn.base_n)
                        {
                            result = 1;
                        }
                        else if (srcDsn.base_n < tarDsn.base_n)
                        {
                            result = -1;
                        }
                        else
                        {
                            result = 0;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                logMessage = "[System Exception] TracingFunc CompareDsn() exception : " + ex.Message.ToString();
                constFunc.WriteLog(constValues.CONST_LOGGER_TYPE_FATAL, logMessage, loggerType, loggerAlias, loggerConfig);
                return -99;
            }

            return result;
        }
        #endregion

        #region ConvertHeaderTransactionMsgpackStructToConstStruct() : header-transaction msgpack 구조체를 const 구조체로 변환
        public unsafe Struct.TracingRecordHeaderTransaction ConvertHeaderTransactionMsgpackStructToConstStruct(StructMessagepack.TracingRecordHeaderTransaction record)
        {
            ConstFunc constFunc = new ConstFunc();
            ConstValues constValues = new ConstValues();
            Struct.TracingRecordHeaderTransaction result = new Struct.TracingRecordHeaderTransaction();

            try
            {
                #region convert tracing record header
                // command 
                result.header.command = record.header.command;
                // trc_record_type                
                result.header.trc_record_type = record.header.trc_record_type;
                // capture_type
                result.header.capture_type = record.header.capture_type;
                // partition
                result.header.partition = record.header.partition;
                // length
                result.header.length = record.header.length;
                // timestamp
                result.header.timestamp.tv_sec = record.header.timestamp.tv_sec;
                result.header.timestamp.tv_nsec = record.header.timestamp.tv_nsec;
                // redo_thread_node
                result.header.redo_thread_node = record.header.redo_thread_node;
                // redo_sequence
                result.header.redo_sequence = record.header.redo_sequence;
                // redo_block
                result.header.redo_block = record.header.redo_block;
                // redo_offset
                result.header.redo_offset = record.header.redo_offset;
                // tx_index
                result.header.tx_index = record.header.tx_index;
                // tx_indicator
                result.header.tx_indicator = record.header.tx_indicator;
                // record_columns
                result.header.record_columns = record.header.record_columns;
                // record_continued
                result.header.record_continued = record.header.record_continued;
                // record_count
                result.header.record_count = record.header.record_count;
                // schema
                if (record.header.schema != null && record.header.schema.Length > 0)
                    result.header.schema = System.Text.Encoding.UTF8.GetString(record.header.schema).TrimEnd((Char)0).Trim();
                // object (table)
                if (record.header.object_n != null && record.header.object_n.Length > 0)
                    result.header.object_n = System.Text.Encoding.UTF8.GetString(record.header.object_n).TrimEnd((Char)0).Trim();
                #endregion

                #region convert tracing record transaction
                // rowid
                if (record.transaction.rowid != null && record.transaction.rowid.Length > 0)
                    result.transaction.rowid = System.Text.Encoding.UTF8.GetString(record.transaction.rowid).TrimEnd((Char)0).Trim();
                // commit_dsn
                // 8자리, 8자리, 4자리의 int 값으로 변환되므로 처리가 필요함                
                result.transaction.commit_dsn.high = record.transaction.commit_dsn.high;
                result.transaction.commit_dsn.wrap = record.transaction.commit_dsn.wrap;
                result.transaction.commit_dsn.base_n = record.transaction.commit_dsn.base_n;
                // tx_id
                if (record.transaction.tx_id != null && record.transaction.tx_id.Length > 0)
                    result.transaction.tx_id = System.Text.Encoding.UTF8.GetString(record.transaction.tx_id).TrimEnd((Char)0).Trim();
                #endregion
            }
            catch (Exception ex)
            {
                logMessage = "[System Exception] TracingFunc ConvertHeaderTransactionMsgpackStructToConstStruct() exception : " + ex.Message.ToString();
                constFunc.WriteLog(constValues.CONST_LOGGER_TYPE_FATAL, logMessage, loggerType, loggerAlias, loggerConfig);
            }

            return result;
        }
        #endregion

        #region SeekScn() : dsn 으로 찾음
        public bool SeekScn(ref UInt32 high, ref UInt32 wrap, ref UInt32 base_n, uint txIndex, bool isReadingTx)
        {
            bool result = false;
            ConstFunc constFunc = new ConstFunc();
            ConstValues constValues = new ConstValues();
            ConstValuesTracing constValuesTracing = new ConstValuesTracing();

            try
            {
                Struct.ACDSN dsn = new Struct.ACDSN(high, wrap, base_n);
                string path = tracePath + traceFile;
                // trace file stream 읽음
                byte[] arrData = null;

                if (!File.Exists(path))
                {
                    constFunc.WriteLog(constValues.CONST_LOGGER_TYPE_DEBUG, "SeekScn() : Trace file is not exist. Path : " + path, loggerType, loggerAlias, loggerConfig);
                    return result;
                }

                bool isRead = false;
                while (!isRead)
                {
                    while (!constFunc.IsFileReady(path))
                    {
                        // wait for trace file ready
                        Thread.Sleep(100);
                    }

                    try
                    {
                        using (var fs = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read))
                        {
                            arrData = new byte[fs.Length];
                            fs.Read(arrData, 0, (int)fs.Length);
                            isRead = true;
                        }
                    }
                    catch
                    {
                        isRead = false;
                        Thread.Sleep(100);
                    }
                }

                traceTotalLength = arrData.Length;
                while (traceCurPosition < traceTotalLength)
                {
                    // trace file header 구함
                    Struct.TracingRecordBracket bracket = GetTracingRecordBracket(arrData, constValues.CONST_BRACKET_TYPE_OPENER, 0, traceCurPosition);
                    if (bracket != null)
                    {
                        Struct.TracingRecordHeaderTransaction recordIncludeHeaderTransaction = GetTracingRecordHeaderTransaction(arrData, bracket.length);
                        Console.WriteLine("recordIncludeHeaderTransaction : " + recordIncludeHeaderTransaction);
                        if (recordIncludeHeaderTransaction != null)
                        {
                            if (!isReadingTx)
                            {
                                if (CompareDsn(dsn, recordIncludeHeaderTransaction.transaction.commit_dsn) == -1)
                                {
                                    high = recordIncludeHeaderTransaction.transaction.commit_dsn.high;
                                    wrap = recordIncludeHeaderTransaction.transaction.commit_dsn.wrap;
                                    base_n = recordIncludeHeaderTransaction.transaction.commit_dsn.base_n;

                                    result = true;
                                    traceData = arrData;
                                    break;
                                }
                            }
                            else
                            {
                                int compare = CompareDsn(dsn, recordIncludeHeaderTransaction.transaction.commit_dsn);
                                if (compare == -1)
                                {
                                    // commit 미완료인 경우 큰 dsn 이면 확정함                                                        
                                    high = recordIncludeHeaderTransaction.transaction.commit_dsn.high;
                                    wrap = recordIncludeHeaderTransaction.transaction.commit_dsn.wrap;
                                    base_n = recordIncludeHeaderTransaction.transaction.commit_dsn.base_n;

                                    result = true;
                                    traceData = arrData;
                                    break;
                                }
                                else if (compare == 0)
                                {
                                    if (traceCurPosition == constValuesTracing.CONST_STRUCT_SIZE_FILEHEADER)
                                    {
                                        // transaction 중간에서 trace file 의 첫 레코드이면 이어서 read 하고 있음
                                        high = recordIncludeHeaderTransaction.transaction.commit_dsn.high;
                                        wrap = recordIncludeHeaderTransaction.transaction.commit_dsn.wrap;
                                        base_n = recordIncludeHeaderTransaction.transaction.commit_dsn.base_n;

                                        result = true;
                                        traceData = arrData;
                                        break;
                                    }
                                    else
                                    {
                                        // 이전에 마지막까지 read 한것 tracefile 크기가 최대 크기가 아니고
                                        // commit 미완료인 경우 같은 dsn 이면 index 가 크면 확정함
                                        // definition, lob record 는 tx_index 가 고정되어 있음
                                        if (recordIncludeHeaderTransaction.header.trc_record_type != constValuesTracing.CONST_RECORD_TYPE_DEFINITION &&
                                           recordIncludeHeaderTransaction.header.trc_record_type != constValuesTracing.CONST_RECORD_TYPE_LOB)
                                        {
                                            if (recordIncludeHeaderTransaction.header.tx_index > txIndex)
                                            {
                                                // commit 미완료인 경우 큰 tx_index 이면 확정함
                                                high = recordIncludeHeaderTransaction.transaction.commit_dsn.high;
                                                wrap = recordIncludeHeaderTransaction.transaction.commit_dsn.wrap;
                                                base_n = recordIncludeHeaderTransaction.transaction.commit_dsn.base_n;

                                                result = true;
                                                traceData = arrData;
                                                break;
                                            }
                                        }
                                        else if (recordIncludeHeaderTransaction.header.trc_record_type == constValuesTracing.CONST_RECORD_TYPE_DEFINITION ||
                                                recordIncludeHeaderTransaction.header.trc_record_type == constValuesTracing.CONST_RECORD_TYPE_LOB)
                                        {
                                            // commit 미완료인 경우 definition 이나 lob 는 tx_index 고정되어 있으므로 확정함
                                            high = recordIncludeHeaderTransaction.transaction.commit_dsn.high;
                                            wrap = recordIncludeHeaderTransaction.transaction.commit_dsn.wrap;
                                            base_n = recordIncludeHeaderTransaction.transaction.commit_dsn.base_n;

                                            result = true;
                                            traceData = arrData;
                                            break;
                                        }
                                    }
                                }
                            }
                            traceCurPosition += (constValuesTracing.CONST_STRUCT_SIZE_BRACKET * 2) + bracket.length;
                            traceIndex = bracket.index;
                        }
                        else
                        {
                            result = false;
                            break;
                        }

                        recordIncludeHeaderTransaction = null;
                    }
                    else
                    {
                        constFunc.WriteLog(constValues.CONST_LOGGER_TYPE_DEBUG, "SeekScn() : Trace bracket data is null.", loggerType, loggerAlias, loggerConfig);
                        result = false;
                        break;
                    }

                    bracket = null;
                }

                dsn = null;
                arrData = null;
                path = null;
            }
            catch (Exception ex)
            {
                logMessage = "[System Exception] TracingFunc SeekScn() exception : " + ex.Message.ToString();
                constFunc.WriteLog(constValues.CONST_LOGGER_TYPE_FATAL, logMessage, loggerType, loggerAlias, loggerConfig);
                return false;
            }

            return result;
        }
        #endregion

        #region GetDefinitionInfoFromTraceFile() : trace file 에서 definition 정보 구함
        public List<Struct.TracingRecordDataDefinition> GetDefinitionInfoFromTraceFile(string alias, string path)
        {
            ConstFunc constFunc = new ConstFunc();
            ConstValues constValues = new ConstValues();
            ConstValuesTracing constValuesTracing = new ConstValuesTracing();
            List<Struct.TracingRecordDataDefinition> result = new List<Struct.TracingRecordDataDefinition>();

            try
            {
                List<string> pathList = new List<string>();
                // 파일리스트 구함
                string[] arrPath = Directory.GetFiles(path);

                for (int i = 0; i < arrPath.Length; i++)
                {
                    string[] arr = arrPath[i].Split('\\');
                    string[] arrFile = arr.Last().Split('_');
                    string fileName = arrFile.First().ToString();
                    if (fileName.Equals(alias))
                    {
                        pathList.Add(arrPath[i]);
                    }

                    arr = null;
                    arrFile = null;
                    fileName = null;
                }

                for (int z = 0; z < pathList.Count; z++)
                {
                    byte[] arrData = null;
                    bool isRead = false;
                    while (!isRead)
                    {
                        while (!constFunc.IsFileReady(pathList[z]))
                        {
                            // wait for trace file ready
                            Thread.Sleep(100);
                        }

                        try
                        {
                            using (var fs = File.Open(pathList[z], FileMode.Open, FileAccess.Read, FileShare.Read))
                            {
                                arrData = new byte[fs.Length];
                                fs.Read(arrData, 0, (int)fs.Length);
                                isRead = true;
                            }
                        }
                        catch
                        {
                            isRead = false;
                            Thread.Sleep(100);
                        }
                    }

                    long position = constValuesTracing.CONST_STRUCT_SIZE_FILEHEADER;
                    while (position < arrData.Length)
                    {
                        // TracingRecordBuffer 구함
                        Struct.TracingRecordBracket openerBracket = GetTracingRecordBracket(arrData, constValues.CONST_BRACKET_TYPE_OPENER, 0, position);

                        byte[] buffer = new byte[openerBracket.length];
                        for (int i = 0; i < openerBracket.length; i++)
                        {
                            buffer[i] = arrData[position + constValuesTracing.CONST_STRUCT_SIZE_BRACKET + i];
                        }

                        // definition TracingRecord 구함
                        StructMessagepack.TracingRecordHeaderTransaction tracingRecordHeaderTransaction = MessagePack.MessagePackSerializer.Deserialize<StructMessagepack.TracingRecordHeaderTransaction>(buffer);
                        if (tracingRecordHeaderTransaction.header.trc_record_type == constValuesTracing.CONST_RECORD_TYPE_DEFINITION)
                        {
                            StructMessagepack.TracingRecordDefinition messagepack = MessagePack.MessagePackSerializer.Deserialize<StructMessagepack.TracingRecordDefinition>(buffer);
                            Struct.TracingRecordDefinition definitionRecord = ConvertDefinitionMsgpackStructToConstStruct(messagepack);
                            definitionRecord.data.table_def.table_name = definitionRecord.header.schema + "." + definitionRecord.header.object_n;

                            // definition list 에 동일한 테이블 존재하면 삭제하고 새로 추가함
                            for (int i = 0; i < result.Count; i++)
                            {
                                if (result[i].table_def.table_name.Equals(definitionRecord.data.table_def.table_name, StringComparison.OrdinalIgnoreCase))
                                {
                                    result.RemoveAt(i);
                                    break;
                                }
                            }
                            result.Add(definitionRecord.data);

                            definitionRecord = null;
                            messagepack.header.object_n = null;
                            messagepack.header.schema = null;
                            messagepack.transaction.rowid = null;
                            messagepack.transaction.tx_id = null;
                            messagepack.data = null;
                        }
                        position += (constValuesTracing.CONST_STRUCT_SIZE_BRACKET * 2) + openerBracket.length;

                        openerBracket = null;
                        buffer = null;
                        tracingRecordHeaderTransaction.header.object_n = null;
                        tracingRecordHeaderTransaction.header.schema = null;
                        tracingRecordHeaderTransaction.transaction.rowid = null;
                        tracingRecordHeaderTransaction.transaction.tx_id = null;
                    }

                    arrData = null;
                }

                pathList = null;
                arrPath = null;
            }
            catch (Exception ex)
            {
                logMessage = "[System Exception] TracingFunc GetDefinitionInfoFromTraceFile() exception : " + ex.Message.ToString();
                constFunc.WriteLog(constValues.CONST_LOGGER_TYPE_FATAL, logMessage, loggerType, loggerAlias, loggerConfig);
            }

            return result;
        }
        #endregion

        #region ConvertDefinitionMsgpackStructToConstStruct() : definition msgpack 구조체를 const 구조체로 변환
        public unsafe Struct.TracingRecordDefinition ConvertDefinitionMsgpackStructToConstStruct(StructMessagepack.TracingRecordDefinition record)
        {
            Struct.TracingRecordDefinition result = new Struct.TracingRecordDefinition();
            ConstFunc constFunc = new ConstFunc();
            ConstValues constValues = new ConstValues();

            try
            {
                #region convert tracing record header
                // command 
                result.header.command = record.header.command;
                // trc_record_type                
                result.header.trc_record_type = record.header.trc_record_type;
                // capture_type
                result.header.capture_type = record.header.capture_type;
                // partition
                result.header.partition = record.header.partition;
                // length
                result.header.length = record.header.length;
                // timestamp
                result.header.timestamp.tv_sec = record.header.timestamp.tv_sec;
                result.header.timestamp.tv_nsec = record.header.timestamp.tv_nsec;
                // redo_thread_node
                result.header.redo_thread_node = record.header.redo_thread_node;
                // redo_sequence
                result.header.redo_sequence = record.header.redo_sequence;
                // redo_block
                result.header.redo_block = record.header.redo_block;
                // redo_offset
                result.header.redo_offset = record.header.redo_offset;
                // tx_index
                result.header.tx_index = record.header.tx_index;
                // tx_indicator
                result.header.tx_indicator = record.header.tx_indicator;
                // record_columns
                result.header.record_columns = record.header.record_columns;
                // record_continued
                result.header.record_continued = record.header.record_continued;
                // record_count
                result.header.record_count = record.header.record_count;
                // definition_id
                result.header.definition_id = record.header.definition_id;
                // schema
                if (record.header.schema != null && record.header.schema.Length > 0)
                    result.header.schema = System.Text.Encoding.UTF8.GetString(record.header.schema).TrimEnd((Char)0).Trim();
                // object (table)
                if (record.header.object_n != null && record.header.object_n.Length > 0)
                    result.header.object_n = System.Text.Encoding.UTF8.GetString(record.header.object_n).TrimEnd((Char)0).Trim();
                #endregion

                #region convert tracing record transaction
                // rowid
                if (record.transaction.rowid != null && record.transaction.rowid.Length > 0)
                    result.transaction.rowid = System.Text.Encoding.UTF8.GetString(record.transaction.rowid).TrimEnd((Char)0).Trim();
                // commit_dsn
                // 8자리, 8자리, 4자리의 int 값으로 변환되므로 처리가 필요함                
                result.transaction.commit_dsn.high = record.transaction.commit_dsn.high;
                result.transaction.commit_dsn.wrap = record.transaction.commit_dsn.wrap;
                result.transaction.commit_dsn.base_n = record.transaction.commit_dsn.base_n;
                // tx_id
                if (record.transaction.tx_id != null && record.transaction.tx_id.Length > 0)
                    result.transaction.tx_id = System.Text.Encoding.UTF8.GetString(record.transaction.tx_id).TrimEnd((Char)0).Trim();
                #endregion

                #region convert tracing definition data
                // definition table
                Struct.TracingRecordDataDefinitionTable definitionTable = new Struct.TracingRecordDataDefinitionTable();
                definitionTable.definition_id = record.data.table_def.definition_id;
                definitionTable.num_columns = record.data.table_def.num_columns;
                definitionTable.num_key_columns = record.data.table_def.num_key_columns;
                definitionTable.num_use_columns = record.data.table_def.num_use_columns;
                if (record.data.table_def.table_name != null && record.data.table_def.table_name.Length > 0)
                    definitionTable.table_name = System.Text.Encoding.UTF8.GetString(record.data.table_def.table_name);
                result.data.table_def = definitionTable;

                definitionTable = null;

                // definition column
                for (int i = 0; i < record.data.column_def.Length; i++)
                {
                    Struct.TracingRecordDataDefinitionColumn definitionColumn = new Struct.TracingRecordDataDefinitionColumn();
                    definitionColumn.col_no = record.data.column_def[i].col_no;
                    definitionColumn.segcol_no = record.data.column_def[i].segcol_no;
                    definitionColumn.internal_no = record.data.column_def[i].internal_no;
                    definitionColumn.name = System.Text.Encoding.UTF8.GetString(record.data.column_def[i].name);
                    definitionColumn.datatype = record.data.column_def[i].datatype;
                    definitionColumn.sub_datatype = record.data.column_def[i].sub_datatype;
                    definitionColumn.native_datatype = record.data.column_def[i].native_datatype;
                    definitionColumn.extern_length = record.data.column_def[i].extern_length;
                    definitionColumn.internal_length = record.data.column_def[i].internal_length;
                    definitionColumn.is_nullable = record.data.column_def[i].is_nullable;
                    definitionColumn.is_hidden = record.data.column_def[i].is_hidden;
                    definitionColumn.key_column = record.data.column_def[i].key_column;
                    definitionColumn.precision = record.data.column_def[i].precision;
                    definitionColumn.scale = record.data.column_def[i].scale;
                    definitionColumn.property = record.data.column_def[i].property;
                    definitionColumn.character_set = record.data.column_def[i].character_set;
                    definitionColumn.is_lob = record.data.column_def[i].is_lob;
                    result.data.column_def.Add(definitionColumn);

                    definitionColumn = null;
                }

                #endregion
            }
            catch (Exception ex)
            {
                logMessage = "[System Exception] TracingFunc ConvertDefinitionMsgpackStructToConstStruct() exception : " + ex.Message.ToString();
                constFunc.WriteLog(constValues.CONST_LOGGER_TYPE_FATAL, logMessage, loggerType, loggerAlias, loggerConfig);
            }

            return result;
        }
        #endregion

        #region GetNextRecordWithBufferImported() : 다음 레코드 데이터 가져옴
        public long GetNextRecordWithBufferImported(ref object record, ref object recordMsgpack, ref Struct.TracingRecordBuffer recordBuffer)
        {
            ConstFunc constFunc = new ConstFunc();
            ConstValues constValues = new ConstValues();
            ConstValuesTracing constValuesTracing = new ConstValuesTracing();
            long result = 0;

            try
            {
                unsafe
                {
                    if (traceCurPosition < traceTotalLength)
                    {
                        // TracingRecordBuffer 구함
                        Struct.TracingRecordBracket openerBracket = GetTracingRecordBracket(traceData, constValues.CONST_BRACKET_TYPE_OPENER, 0, traceCurPosition);
                        Struct.TracingRecordBracket closerBracket = GetTracingRecordBracket(traceData, constValues.CONST_BRACKET_TYPE_CLOSER, openerBracket.length, traceCurPosition);

                        if (traceData.Length < (traceCurPosition + constValuesTracing.CONST_STRUCT_SIZE_BRACKET + openerBracket.length))
                        {
                            return -98;
                        }

                        byte[] buffer = new byte[openerBracket.length];
                        for (int i = 0; i < openerBracket.length; i++)
                        {
                            buffer[i] = traceData[traceCurPosition + constValuesTracing.CONST_STRUCT_SIZE_BRACKET + i];
                        }

                        recordBuffer.opener = openerBracket;
                        recordBuffer.closer = closerBracket;
                        recordBuffer.data = buffer;

                        // TracingRecord 구함
                        StructMessagepack.TracingRecordHeaderTransaction tracingRecordHeaderTransaction = new StructMessagepack.TracingRecordHeaderTransaction();
                        GetTracingRecord(buffer, ref recordMsgpack, ref tracingRecordHeaderTransaction, true);
                        buffer = null;

                        short recordType = tracingRecordHeaderTransaction.header.trc_record_type;
                        Console.WriteLine("recordType : " + recordType);

                        if (recordType == constValuesTracing.CONST_RECORD_TYPE_DML_UNKNOWN || recordType == constValuesTracing.CONST_RECORD_TYPE_DML_INSERT)
                        {
                            record = ConvertDmlMsgpackStructToConstStruct((StructMessagepack.TracingRecordDml)recordMsgpack);
                        }
                        else if (recordType == constValuesTracing.CONST_RECORD_TYPE_DEFINITION)
                        {
                            record = ConvertDefinitionMsgpackStructToConstStruct((StructMessagepack.TracingRecordDefinition)recordMsgpack);
                        }

                        result = openerBracket.length;
                        traceCurPosition += (constValuesTracing.CONST_STRUCT_SIZE_BRACKET * 2) + openerBracket.length;
                        traceIndex = openerBracket.index;

                        openerBracket = null;
                        closerBracket = null;
                        tracingRecordHeaderTransaction.header.object_n = null;
                        tracingRecordHeaderTransaction.header.schema = null;
                        tracingRecordHeaderTransaction.transaction.rowid = null;
                        tracingRecordHeaderTransaction.transaction.tx_id = null;
                    }
                    else
                    {
                        result = 0;
                    }
                }
            }
            catch (Exception ex)
            {
                logMessage = "[System Exception] TracingFunc GetNextRecordWithBufferImported() exception : " + ex.Message.ToString();
                constFunc.WriteLog(constValues.CONST_LOGGER_TYPE_FATAL, logMessage, loggerType, loggerAlias, loggerConfig);
                return -99;
            }

            return result;
        }
        #endregion

        #region GetTracingRecord() : tracing record data 를 구함
        public void GetTracingRecord(byte[] arrData, ref object recordMsgpack, ref StructMessagepack.TracingRecordHeaderTransaction tracingRecordHeaderTransaction, bool isGetAll)
        {
            ConstFunc constFunc = new ConstFunc();
            ConstValues constValues = new ConstValues();
            ConstValuesTracing constValuesTracing = new ConstValuesTracing();

            try
            {
                unsafe
                {
                    tracingRecordHeaderTransaction = MessagePack.MessagePackSerializer.Deserialize<StructMessagepack.TracingRecordHeaderTransaction>(arrData);

                    if (isGetAll)
                    {
                        short recordType = tracingRecordHeaderTransaction.header.trc_record_type;
                        if (recordType == constValuesTracing.CONST_RECORD_TYPE_DML_UNKNOWN || recordType == constValuesTracing.CONST_RECORD_TYPE_DML_INSERT)
                        {
                            StructMessagepack.TracingRecordDml messagepack = new StructMessagepack.TracingRecordDml();
                            messagepack = MessagePack.MessagePackSerializer.Deserialize<StructMessagepack.TracingRecordDml>(arrData);
                            recordMsgpack = messagepack;
                        }
                        else if (recordType == constValuesTracing.CONST_RECORD_TYPE_DEFINITION)
                        {
                            StructMessagepack.TracingRecordDefinition messagepack = new StructMessagepack.TracingRecordDefinition();
                            messagepack = MessagePack.MessagePackSerializer.Deserialize<StructMessagepack.TracingRecordDefinition>(arrData);
                            recordMsgpack = messagepack;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                logMessage = "[System Exception] TracingFunc GetTracingRecord() exception : " + ex.Message.ToString();
                constFunc.WriteLog(constValues.CONST_LOGGER_TYPE_FATAL, logMessage, loggerType, loggerAlias, loggerConfig);
            }

        }
        #endregion

        #region ConvertDmlMsgpackStructToConstStruct() : dml msgpack 구조체를 const 구조체로 변환
        public unsafe Struct.TracingRecordDml ConvertDmlMsgpackStructToConstStruct(StructMessagepack.TracingRecordDml record)
        {
            ConstFunc constFunc = new ConstFunc();
            ConstValues constValues = new ConstValues();
            Struct.TracingRecordDml result = new Struct.TracingRecordDml();
            ConstValuesTracing constValuesTracing = new ConstValuesTracing();

            try
            {
                #region convert tracing record header
                // command 
                result.header.command = record.header.command;
                // trc_record_type                
                result.header.trc_record_type = record.header.trc_record_type;
                // capture_type
                result.header.capture_type = record.header.capture_type;
                // partition
                result.header.partition = record.header.partition;
                // length
                result.header.length = record.header.length;
                // timestamp
                result.header.timestamp.tv_sec = record.header.timestamp.tv_sec;
                result.header.timestamp.tv_nsec = record.header.timestamp.tv_nsec;
                // redo_thread_node
                result.header.redo_thread_node = record.header.redo_thread_node;
                // redo_sequence
                result.header.redo_sequence = record.header.redo_sequence;
                // redo_block
                result.header.redo_block = record.header.redo_block;
                // redo_offset
                result.header.redo_offset = record.header.redo_offset;
                // tx_index
                result.header.tx_index = record.header.tx_index;
                // tx_indicator
                result.header.tx_indicator = record.header.tx_indicator;
                // record_columns
                result.header.record_columns = record.header.record_columns;
                // record_continued
                result.header.record_continued = record.header.record_continued;
                // record_count
                result.header.record_count = record.header.record_count;
                // definition_id
                result.header.definition_id = record.header.definition_id;
                // schema
                if (record.header.schema != null && record.header.schema.Length > 0)
                    result.header.schema = System.Text.Encoding.UTF8.GetString(record.header.schema).TrimEnd((Char)0).Trim();
                // object (table)
                if (record.header.object_n != null && record.header.object_n.Length > 0)
                    result.header.object_n = System.Text.Encoding.UTF8.GetString(record.header.object_n).TrimEnd((Char)0).Trim();
                #endregion

                #region convert tracing record transaction
                // rowid
                if (record.transaction.rowid != null && record.transaction.rowid.Length > 0)
                    result.transaction.rowid = System.Text.Encoding.UTF8.GetString(record.transaction.rowid).TrimEnd((Char)0).Trim();
                // commit_dsn
                // 8자리, 8자리, 4자리의 int 값으로 변환되므로 처리가 필요함                
                result.transaction.commit_dsn.high = record.transaction.commit_dsn.high;
                result.transaction.commit_dsn.wrap = record.transaction.commit_dsn.wrap;
                result.transaction.commit_dsn.base_n = record.transaction.commit_dsn.base_n;
                // tx_id
                if (record.transaction.tx_id != null && record.transaction.tx_id.Length > 0)
                    result.transaction.tx_id = System.Text.Encoding.UTF8.GetString(record.transaction.tx_id).TrimEnd((Char)0).Trim();
                #endregion

                #region convert tracing record data
                for (int i = 0; i < record.data.Length; i++)
                {
                    Struct.TracingRecordData item = new Struct.TracingRecordData();
                    item.colno = record.data[i].colno;
                    item.flag = record.data[i].flag;
                    item.is_null = record.data[i].is_null;
                    item.length = record.data[i].length;
                    item.type = record.data[i].type;

                    if (item.type == constValuesTracing.CONST_COL_TYPE_BLOB || item.type == constValuesTracing.CONST_COL_TYPE_RAW || item.type == constValuesTracing.CONST_COL_TYPE_LONGRAW)
                    {
                        if (record.data[i].str != null && record.data[i].str.Length > 0)
                            item.str = System.Text.Encoding.Default.GetString(record.data[i].str).TrimEnd((Char)0).Trim();
                    }
                    else
                    {
                        if (record.data[i].str != null && record.data[i].str.Length > 0)
                            item.str = System.Text.Encoding.UTF8.GetString(record.data[i].str).TrimEnd((Char)0);
                    }
                    item.bytes = record.data[i].str;

                    result.dataList.Add(item);

                    item = null;
                }
                #endregion
            }
            catch (Exception ex)
            {
                logMessage = "[System Exception] TracingFunc ConvertDmlMsgpackStructToConstStruct() exception : " + ex.Message.ToString();
                constFunc.WriteLog(constValues.CONST_LOGGER_TYPE_FATAL, logMessage, loggerType, loggerAlias, loggerConfig);
            }

            return result;
        }
        #endregion

    }
}