// <summary>ソースコード：ＨＹＭＣＯ 伝送データプールクラス</summary>
// <author>CommonMP</author>

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

using CommonMP.HYSSOP.Interface.HSData;
using CommonMP.HYSSOP.CoreImpl.HSData;
using CommonMP.HYSSOP.CoreImpl.HSTools;

using CommonMP.HYMCO.Interface;
using CommonMP.HYMCO.Interface.Data;

namespace CommonMP.HYMCO.CoreImpl.Data.TranInfo
{
    /// <summary><para>class outline:</para>
    /// <para>HYMCO 伝送データプールクラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>
    /// [CommonMP][ver 1.0.0][2008/10/01][新規作成]
    /// [CommonMP][ver 1.4.0][2013/12/06][修正]
    /// </para>
    /// <para>remarks:</para>
    /// <para>　オブジェクトの　new/delete　は　処理時間がかかる。
    /// この為、 使用する伝送データを予めプールしておき、new/dele を繰り返さない様にする。
    /// new/delete を繰り返す伝送データ以外は、このクラスを使用する必要は無い
    /// サーバーに使用する場合、どこかで、メモリを削除する機能が必要（例えば、定期的に使用されていないデータタイプのみを解放する等）
    /// </para>
    /// </remarks>
    public static class McTranInfoDataPool //: McRoot
    {
        /// <summary>伝送データ本体を保持するリンクリストを保持するハッシュテーブル</summary>
        static private Hashtable m_csDataListTable = new Hashtable();
        /// <summary>伝送データ型紙を保持するリンクリストを保持するハッシュテーブル</summary>
        static private Hashtable m_csDataTypeTable = new Hashtable();

        //★★★★★★★★★★★★★★★★★
        // Ver1.4で追加(伝送情報の事前作成)
        //★★★★★★★★★★★★★★★★★
        /// <summary>伝送データのオブジェクトサイズ(KB)を保持するハッシュテーブル</summary>
        static private Hashtable m_csDataSizeTable = new Hashtable();
        /// <summary>伝送データの必要レコード数を保持するハッシュテーブル</summary>
        static private Hashtable m_csDataCountTable = new Hashtable();
        /// <summary>伝送データの必要接続線数を保持するハッシュテーブル</summary>
        static private Hashtable m_csDataLineTable = new Hashtable();
        /// <summary>伝送データのタイプを保持するリスト管理テーブル（プロジェクト毎）</summary>
        static private Hashtable m_csDataTypeListTable = new Hashtable();
        /// <summary>伝送データオブジェクトの必要数を保持するハッシュテーブル</summary>
        static private Hashtable m_csDataNumTable = new Hashtable();
        /// <summary>計算期間</summary>
        static private Hashtable m_csSimTermTable = new Hashtable();// 複数プロジェクトへの対応
        /// <summary>全体系タイムステップ</summary>
        static private Hashtable m_csSimTimeStepTable = new Hashtable();// 複数プロジェクトへの対応
        /// <summary>パフォーマンスカウンタ</summary>
        static private System.Diagnostics.PerformanceCounter m_csPCounter = new System.Diagnostics.PerformanceCounter();
        /// <summary>プロジェクトID管理ハッシュテーブル</summary>
        static private Hashtable m_csPrjIDTable = new Hashtable();

        //★★★★★★★★★★★★★★★★★★
        // Ver1.4で追加(インスタンスの共有化)
        //★★★★★★★★★★★★★★★★★★
        /// <summary>共有化判断用ハッシュテーブル（プロジェクト毎管理テーブル）</summary>
        static private Hashtable m_csCommonInstTablePrjID = new Hashtable();
        /// <summary>共有化OKハッシュテーブル</summary>
        static private Hashtable m_csCommonInstOKTable = new Hashtable();
        /// <summary>共有インスタンスハッシュテーブル</summary>
        static private Hashtable m_csCommonTable = new Hashtable();
        /// <summary>共有インスタンス数</summary>
        static private long m_lNum = 0;
        //★★★★★★★★★★★★★★
        // Ver1.4で追加(共有化の選択)
        //★★★★★★★★★★★★★★
        /// <summary>共有化実施用フラグ</summary>
        static public bool m_bCommonUseFlg = true;

        /// <summary>排他用</summary>
        static private HySMutex m_csMutex = new HySMutex();
        //★★★修正 ここから★★★
        /// <summary>共有化接続線専用のハッシュ領域KeyName</summary>
        static private List<string> m_csClearObjNameList = new List<string>();
        //★★★修正 ここから★★★

        ///// <summary>ワークリスト</summary>
        //static private LinkedList<McTranInfo> m_ListWork = null;
        ///// <summary>ワークノード</summary>
        //static private LinkedListNode<McTranInfo> m_NodeWork = null;

        /// <summary><para>method outline:</para>
        /// <para>プールしておく情報を設定する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>RegisterDataType(csDataKind, csData) </para>
        /// </example>
        /// <param name="csDataKind">プールする伝送データの識別子</param>
        /// <param name="csData">プールする伝送データ</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public void RegisterDataType(HySObjectKind csDataKind, McTranInfo csData)
        {
            RegisterDataType(csDataKind, csData, 16);
        }

        // 生成するデータの型を登録する
        /// <summary><para>method outline:</para>
        /// <para>プールしておく情報を設定する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>RegisterDataType(csDataKind, csData, lIncrementNum) </para>
        /// </example>
        /// <param name="csDataKind">プールする伝送データの識別子</param>
        /// <param name="csData">プールする伝送データ</param>
        /// <param name="lIncrementNum">プールした伝送データが無くなったときにインスタンスを自動的に増やす数</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public void RegisterDataType(HySObjectKind csDataKind, McTranInfo csData, long lIncrementNum)
        {
            string ObjName = csDataKind.GetString().ToString();
            LinkedList<McTranInfo> csListWork = null;

            if (m_csDataListTable[ObjName] == null)
                {   // 未だ登録されていない
                m_csDataTypeTable.Add(ObjName, csData);

                csListWork = new LinkedList<McTranInfo>();
                m_csDataListTable.Add(ObjName, csListWork);

                //m_csDataIncrementNum.Add(ObjName, lIncrementNum);
                // 予め所定数生成しておく
                for (long lCnt = 0; lCnt < lIncrementNum; lCnt++)
                {
                    csListWork.AddFirst(csData.Clone());
                }
            }
            else
            {
                // 既に登録されている（何もしない）
            }
        }

        //★★★★★★★★★★★★★★★★★
        // Ver1.4で追加(伝送情報の事前作成)
        //★★★★★★★★★★★★★★★★★
        /// <summary><para>method outline:</para>
        /// <para>伝送情報の種類とマスタデータ及びサイズを登録する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>RegistData(sPrjID, csDataKind, csData) </para>
        /// </example>
        /// <param name="sPrjID">プロジェクト識別子</param>
        /// <param name="csDataKind">種別情報</param>
        /// <param name="csData">伝送情報</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public void RegistData(string sPrjID, HySObjectKind csDataKind, McTranInfo csData)
        {
            string ObjName = csDataKind.GetString().ToString() + sPrjID;
            List<HySObjectKind> csDataTypeList = null;
            if (m_csDataTypeTable[ObjName] == null)
            {   // 未だ登録されていない
                m_csDataTypeTable.Add(ObjName, csData);
                //m_csDataTypeList.Add(csDataKind);
                if (m_csDataTypeListTable[sPrjID] == null)
                {
                    csDataTypeList = new List<HySObjectKind>();
                    csDataTypeList.Add(csDataKind);
                    m_csDataTypeListTable[sPrjID] = csDataTypeList;
                }
                else
                {
                    csDataTypeList = (List<HySObjectKind>)m_csDataTypeListTable[sPrjID];
                    csDataTypeList.Add(csDataKind);
                }
            }
            else
            {
                // 何もしない
            }
            if (m_csDataSizeTable[ObjName] == null)
            {
                // オブジェクトのサイズを測る
                using (System.IO.MemoryStream str = new System.IO.MemoryStream())
                {
                    using (System.IO.BinaryWriter bin = new System.IO.BinaryWriter(str))
                    {
                        (new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter()).Serialize(bin.BaseStream, csData.Clone());
                        bin.Flush();
                        long size = str.Length;
                        str.Close();
                        m_csDataSizeTable[ObjName] = size;// / 1024;
                    }
                }
            }
        }

        //★★★★★★★★★★★★★★★★★
        // Ver1.4で追加(伝送情報の事前作成)
        //★★★★★★★★★★★★★★★★★
        /// <summary><para>method outline:</para>
        /// <para>伝送情報の事前作成</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>RegisterDataType(sPrjID) </para>
        /// </example>
        /// <param name="sPrjID">プロジェクトID</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public void RegisterDataType(string sPrjID)
        {
            //m_csDataTypeList = (List<HySObjectKind>)m_csDataTypeListTable[sPrjID];
            List<HySObjectKind> csDataTypeList = (List<HySObjectKind>)m_csDataTypeListTable[sPrjID];
            if (csDataTypeList != null)
            {
                for (int iLp = 0; iLp < csDataTypeList.Count; iLp++)
                {
                    HySObjectKind csDataKind = csDataTypeList[iLp];
                    // 必要な量を確保
                    string ObjName = csDataKind.GetString().ToString() + sPrjID;

                    // ◆此処で一時ファイル出力設定を確認
                    bool bOutFlg = false;
                    HySString csString = HySEnvInf.GetEnvInf("HYMCO_D2_CELL_SERIAL_FILEOUT");
                    if ((object)csString != null)
                    {
                        bOutFlg = Convert.ToBoolean(csString.ToString());
                    }

                    long lMaxNum = 0;
                    long lIncrementNum = 0;

                    if (csDataKind.ToString().StartsWith(typeof(McD2CellArrayTranInfo).FullName) == true && bOutFlg == true)
                    {// ◆2次元配列情報かつ、一時ファイル有効の場合
                        // ◆設定ファイルの利用可能な容量を取得
                        long lsize = 0;
                        csString = HySEnvInf.GetEnvInf("HYMCO_D2_CELL_SERIAL_LINE_AVAILABLE_MBYTES");
                        if ((object)csString != null)
                        {
                            lsize = Convert.ToInt64(csString.ToString());
                        }
                        // ◆オブジェクトのサイズを取得
                        long lobjsize = (long)m_csDataSizeTable[ObjName];
                        // ◆利用可能な容量分の個数を算出してlIncrementNumに設定する
                        long ltotalNum = (lsize * 1000000) / lobjsize;
                        lIncrementNum = ltotalNum;
                    }
                    else
                    {
                        // オブジェクト数
                        lMaxNum = (long)m_csDataNumTable[ObjName];
                        lIncrementNum = lMaxNum;
                    }

                    LinkedList<McTranInfo> csListWork = null;

                    if (m_csDataListTable[ObjName] == null)
                    {   // 未だ登録されていない
                        csListWork = new LinkedList<McTranInfo>();
                        m_csDataListTable.Add(ObjName, csListWork);
                        // 予め所定数生成しておく
                        McTranInfo csData = (McTranInfo)m_csDataTypeTable[ObjName];
                        for (long lCnt = 0; lCnt < lIncrementNum; lCnt++)
                        {// メモリ量が閾値を超えたらメッセージ。確保できない分は一時ファイル化
                            csListWork.AddFirst(csData.Clone());
                        }
                    }
                    else
                    {
                        // 何もしない
                    }
                }
            }
        }

        //★★★★★★★★★★★★★★★★★
        // Ver1.4で追加(伝送情報の事前作成)
        //★★★★★★★★★★★★★★★★★
        /// <summary><para>method outline:</para>
        /// <para>計算期間及び全体系タイムステップの情報設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>SetSimInfo(sPrjID, csSimStart, csSimEnd, csSimTimeStep) </para>
        /// </example>
        /// <param name="sPrjID">プロジェクト識別子</param>
        /// <param name="csSimStart">開始時刻</param>
        /// <param name="csSimEnd">終了時刻</param>
        /// <param name="csSimTimeStep">全体系タイムステップ</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public void SetSimInfo(string sPrjID, HySTime csSimStart, HySTime csSimEnd, HySTime csSimTimeStep)
        {
            m_csSimTermTable[sPrjID] = (csSimEnd.GetTime() - csSimStart.GetTime());
            m_csSimTimeStepTable[sPrjID] = csSimTimeStep.GetTime();
        }

        //★★★★★★★★★★★★★★★★★★★★★★★★★★★★
        // Ver1.4で追加(伝送情報の事前作成、インスタンスの共有化)
        //★★★★★★★★★★★★★★★★★★★★★★★★★★★★
        /// <summary><para>method outline:</para>
        /// <para>上流側要素モデルタイムステップの設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>SetUpperElmTimeStep(sPrjID, csDataKind, csTimeStep, lMaxDataNum, csCommonInfo) </para>
        /// </example>
        /// <param name="sPrjID">プロジェクトID</param>
        /// <param name="csDataKind">データ種別</param>
        /// <param name="csTimeStep">上流要素のタイムステップ</param>
        /// <param name="lMaxDataNum">最大レコード保持数</param>
        /// <param name="csCommonInfo">共通情報</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public void SetUpperElmTimeStep(string sPrjID, HySObjectKind csDataKind, HySTime csTimeStep, long lMaxDataNum, McTranInfoCommon csCommonInfo)
        {
            try
            {
                //★★★★★★★★★★★★★★
                // Ver1.4で追加(共有化の選択)
                //★★★★★★★★★★★★★★
                string ObjName = csDataKind.GetString().ToString() + "";
                if (m_bCommonUseFlg == true)
                {
                    Hashtable csCommonInstTable = null;
                    if (m_csCommonInstTablePrjID[sPrjID] == null)
                    {
                        csCommonInstTable = new Hashtable();
                        m_csCommonInstTablePrjID[sPrjID] = csCommonInstTable;
                    }
                    else
                    {
                        csCommonInstTable = (Hashtable)m_csCommonInstTablePrjID[sPrjID];
                    }
                    ObjName = csDataKind.GetString().ToString() + sPrjID;
                    // Start of TestCode インスタンスの共有化
                    if (csCommonInstTable.Contains(csCommonInfo.GetUpperElementID().ToString() + sPrjID) == true)// GetUpperElementID + PrjID
                    {
                        // 送信元要素が他の接続線と同一である
                        string sID = (string)csCommonInstTable[csCommonInfo.GetUpperElementID().ToString() + sPrjID];// GetUpperElementID + PrjID
                        string sCompID = csCommonInfo.GetSendCellData().GetSendPatternID().ToString() + csDataKind.GetString().ToString() + lMaxDataNum.ToString();
                        if (sID.Equals(sCompID) == true)
                        {
                            // 送信パターンも同一である => インスタンスの共有化ができるため、接続線及びレコード数のカウントはしない
                            //m_csCommonInstOKTable.Add(csCommonInfo.GetUpperElementID().ToString(), csCommonInfo.GetSendCellData().GetSendPatternID());
                            m_csCommonInstOKTable[csCommonInfo.GetUpperElementID().ToString() + sPrjID] = csCommonInfo.GetSendCellData().GetSendPatternID();      // キー(GetUpperElementID + PrjID)がすでに存在する場合: 対応する値の置き換え
                            m_lNum += 1;
                            // まずは、最大レコード保持数が同一であることを条件とする。
                            return;
                        }
                    }
                    else
                    {
                        // 送信元要素、送信パターン、配列数及び最大レコード保持数が同一であることを条件とする為、Val値へ情報を付与する
                        string sVal = csCommonInfo.GetSendCellData().GetSendPatternID().ToString() + csDataKind.GetString().ToString() + lMaxDataNum.ToString();
                        csCommonInstTable.Add(csCommonInfo.GetUpperElementID().ToString() + sPrjID, sVal);// csCommonInstTableのkeyとしてPrjIDも追加する（異なるプロジェクトで要素IDが同一というケースがある為）
                                                                                                          //m_csCommonInstTablePrjID[sPrjID] = m_csCommonInstTable;
                    }
                    // End of TestCode
                }

                // 最大レコード保持数
                //long lMaxNum = (long)m_csDataCountTable[ObjName];
                long lMaxNum = lMaxDataNum;
                // タイムステップは全体系と要素モデルの比較を行う
                double m_dSimTimeStep = (double)m_csSimTimeStepTable[sPrjID];
                long lSimTimeStep = (long)m_dSimTimeStep;
                long lElmTimeStep = 0;
                if (csTimeStep != null)
                {
                    lElmTimeStep = (long)csTimeStep.GetTime();
                }
                else
                {
                    // Gr要素内で中継端子に接している場合は取得できない為、全体系のタイムステップとする
                    lElmTimeStep = lSimTimeStep;
                }
                long lTimeStep = 0;
                // 比較して少ない方を採用する
                if (lSimTimeStep > lElmTimeStep)
                {
                    lTimeStep = lElmTimeStep;
                }
                else if (lSimTimeStep <= lElmTimeStep)
                {
                    lTimeStep = lSimTimeStep;
                }
                // 計算期間/上流側要素モデルのタイムステップ
                double m_dSimTerm = (double)m_csSimTermTable[sPrjID];
                long lMaxNum2 = 0;
                if (lTimeStep == 0)
                {
                    // 何もしないモデルが該当
                    lMaxNum2 = (long)m_dSimTerm;
                }
                else
                {
                    lMaxNum2 = ((long)m_dSimTerm / lTimeStep);
                }
                // 比較して少ない方を採用する
                if (lMaxNum > lMaxNum2)
                {
                    // ハッシュ管理する 
                    if (m_csDataNumTable[ObjName] == null)
                    {   // 未だ登録されていない
                        m_csDataNumTable[ObjName] = lMaxNum2;
                    }
                    else
                    {
                        // 既に登録されている（加算していく）
                        long ltmpNum = (long)m_csDataNumTable[ObjName];
                        ltmpNum += lMaxNum2;
                        m_csDataNumTable[ObjName] = ltmpNum;
                    }
                }
                else if (lMaxNum <= lMaxNum2)
                {
                    // ハッシュ管理する 
                    if (m_csDataNumTable[ObjName] == null)
                    {   // 未だ登録されていない
                        m_csDataNumTable[ObjName] = lMaxNum;
                    }
                    else
                    {
                        // 既に登録されている（加算していく）
                        long ltmpNum = (long)m_csDataNumTable[ObjName];
                        ltmpNum += lMaxNum;
                        m_csDataNumTable[ObjName] = ltmpNum;
                    }
                }
            }
            catch(Exception e)
            { }
        }

        //★★★★★★★★★★★★★★★★
        // Ver1.4で追加(一時ファイル作成)
        //★★★★★★★★★★★★★★★★
        /// <summary><para>method outline:</para>
        /// <para>プール残量確認</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>CheckPoolData(sPrjID,csDataKind) </para>
        /// </example>
        /// <param name="sPrjID">プロジェクトID</param>
        /// <param name="csDataKind">種別情報</param>
        /// <returns>bool true:残量無し fasle:残量有り</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public bool CheckPoolData(string sPrjID, HySObjectKind csDataKind)
        {
            LinkedList<McTranInfo> csListWork = null;

            string ObjName = csDataKind.GetString().ToString() + sPrjID;

            csListWork = (LinkedList<McTranInfo>)m_csDataListTable[ObjName];
            if (csListWork.Count == 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        //★★★★★★★★★★★★★★★★★★★★★★★★★★★★
        // Ver1.4で追加(伝送情報の事前作成、インスタンスの共有化)
        //★★★★★★★★★★★★★★★★★★★★★★★★★★★★
        /// <summary><para>method outline:</para>
        /// <para>情報のクリア</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>ClearInfo(sPrjID) </para>
        /// </example>
        /// <param name="sPrjID">プロジェクトID</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public void ClearInfo(string sPrjID)
        {
            // 一度ビルドし、配列数を変えて再度ビルドする場合、
            // m_csCommonInstTable等テーブル類をを空にしなければならない。
            List<HySObjectKind> csDataTypeList = null;
            Hashtable csCommonInstTable = null;
            if (m_csDataTypeListTable[sPrjID] != null)
            {
                csDataTypeList = (List<HySObjectKind>)m_csDataTypeListTable[sPrjID];
            }
            else
            {
                return;
            }
            if (m_csCommonInstTablePrjID[sPrjID] != null)
            {
                csCommonInstTable = (Hashtable)m_csCommonInstTablePrjID[sPrjID];
                csCommonInstTable.Clear();
            }
            else
            {
                //return;
            }
            string ObjName = "";
            for (int iLp = 0; iLp < csDataTypeList.Count; iLp++)
            {
                HySObjectKind csDataKind = csDataTypeList[iLp];
                ObjName = csDataKind.GetString().ToString() + sPrjID;
                LinkedList<McTranInfo> csListWork = (LinkedList<McTranInfo>)m_csDataListTable[ObjName];
                McTranInfo csData = (McTranInfo)m_csDataTypeTable[ObjName];
                csData = null;
                if (csListWork != null)
                {
                    csListWork.Clear();
                }
            }
            csDataTypeList.Clear();
            m_csDataListTable.Remove(ObjName);
            //★★★修正 ここから★★★
            for (int iLp = 0; iLp < m_csClearObjNameList.Count; iLp++)
            {
                string ClearObjName = m_csClearObjNameList[iLp];
                LinkedList<McTranInfo> csListWork = (LinkedList<McTranInfo>)m_csDataListTable[ClearObjName];
                if (csListWork != null)
                {
                    csListWork.Clear();
                }
                m_csDataListTable.Remove(ClearObjName);
            }
            //★★★修正 ここまで★★★
            m_csDataTypeTable.Remove(ObjName);
            m_csDataNumTable.Remove(ObjName);
            // ここで明示的な解放(1回目)
            GC.Collect();//2回目(回収対象としてマークしたオブジェクトの破棄)は別スレッドである画面側で実施する必要がある
        }

        // 所望のデータを取得する
        /// <summary><para>method outline:</para>
        /// <para>データインスタンス取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>McTranInfo csInfo = GetNewData(csDataKind) </para>
        /// </example>
        /// <param name="csDataKind">生成する伝送データの識別子</param>
        /// <returns> McTranInfo　インスタンス（登録されていない識別子を与えるとnullが返る）</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>new McTranInfo() の代わりに使用する</para>
        /// </remarks>
        static public McTranInfo GetNewData(HySObjectKind csDataKind)
        {
            McTranInfo bRtnObj = null;
            LinkedList<McTranInfo> csListWork = null;
            LinkedListNode<McTranInfo> csNodeWork = null;

            m_csMutex.Wait();
            string ObjName = csDataKind.GetString().ToString();

            csListWork = (LinkedList<McTranInfo>)m_csDataListTable[ObjName];

            if (csListWork != null)
            {
                csNodeWork = csListWork.First;
                if (csNodeWork != null)
                {   // 空きデータが存在する場合
                    bRtnObj = csNodeWork.Value;
                    csListWork.RemoveFirst();
                }
                else
                {   // 空きデータが存在しない場合
                    // 生成する
                    McTranInfo csObjType = (McTranInfo)m_csDataTypeTable[ObjName];
                    if (csObjType != null)
                    {   // 登録済みのデータであれば
                        //long lIncrementNum = (long)m_csDataIncrementNum[ObjName];
                        bRtnObj = csObjType.Clone();
                        // 予め生成しておく
                        //for (long lCnt = 0; lCnt < lIncrementNum; lCnt++)
                        //{
                        //    csListWork.AddFirst(csObjType.Clone());
                        //}
                    }
                    else
                    {
                        // 何もしない
                        // 必要に応じてLog取得等の処理を追加してください
                    }
                }
            }
            m_csMutex.Release();

            return bRtnObj;
        }

        //★★★★★★★★★★★★★★★★★★
        // Ver1.4で追加(インスタンスの共有化)
        //★★★★★★★★★★★★★★★★★★
        /// <summary><para>method outline:</para>
        /// <para>データインスタンス取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>McTranInfo csInfo = GetNewData(sPrjID, csDataKind, csCommonInfo) </para>
        /// </example>
        /// <param name="sPrjID">プロジェクト識別子</param>
        /// <param name="csDataKind">生成する伝送データの識別子</param>
        /// <param name="csCommonInfo">伝送データの共通情報</param>
        /// <returns> McTranInfo　インスタンス（登録されていない識別子を与えるとnullが返る）</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>new McTranInfo() の代わりに使用する</para>
        /// </remarks>
        static public McTranInfo GetNewData(string sPrjID, HySObjectKind csDataKind, McTranInfoCommon csCommonInfo)
        {
            McTranInfo bRtnObj = null;
            LinkedList<McTranInfo> csListWork = null;
            LinkedListNode<McTranInfo> csNodeWork = null;
            //★★★修正★★★
            LinkedList<McTranInfo> csInstOKListWork = null;
            LinkedListNode<McTranInfo> csInstOKNodeWork = null;

            m_csMutex.Wait();
            Hashtable csCommonInstTable = (Hashtable)m_csCommonInstTablePrjID[sPrjID];
            string ObjName = csDataKind.GetString().ToString() + sPrjID;
            //★★★修正★★★
            string InstOKObjName = csCommonInfo.GetUpperElementID().ToString() + sPrjID;

            csListWork = (LinkedList<McTranInfo>)m_csDataListTable[ObjName];
            //★★★修正★★★
            csInstOKListWork = (LinkedList<McTranInfo>)m_csDataListTable[InstOKObjName];

            if (csListWork != null)
            {
                csNodeWork = csListWork.First;// ←リセットしたらプールに戻す行為をしないと、リセット後もう一度計算する時に、新たに生成されてしまう。
                //★★★修正★★★
                if (csInstOKListWork != null)
                {
                    csInstOKNodeWork = csInstOKListWork.First;
                }
                if (csNodeWork != null || csInstOKNodeWork != null)
                {   // 空きデータが存在する場合
                    if (csCommonInfo.GetSendCellData() == null)
                    {
                        // 共有化対象外の場合（外部から伝送情報型のCloneを行った場合）
                        //// プールからデータ取得
                        //bRtnObj = csNodeWork.Value;
                        //csListWork.RemoveFirst();
                        McTranInfo csObjType = (McTranInfo)m_csDataTypeTable[ObjName];
                        if (csObjType != null)
                        {   // 登録済みのデータであれば
                            bRtnObj = csObjType.Clone();
                        }
                    }
                    else
                    {
                        // Start of TestCode インスタンスの共有化
                        HySTimeSeriesBase csTranInfo = (HySTimeSeriesBase)csCommonInfo.GetSendCellData().GetTranInfo();
                        string sMaxDataNum = "";
                        if (csTranInfo != null)
                        {
                            sMaxDataNum = csTranInfo.GetMaxHoldDataNum().ToString();
                        }
                        string sCompID = csCommonInfo.GetSendCellData().GetSendPatternID().ToString() + csDataKind.GetString().ToString() + sMaxDataNum;
                        if (m_csCommonInstOKTable.Contains(csCommonInfo.GetUpperElementID().ToString() + sPrjID) == true)// GetUpperElementID + PrjID
                        {
                            // 送信元要素が他の接続線と同一である
                            string sID = (string)csCommonInstTable[csCommonInfo.GetUpperElementID().ToString() + sPrjID];// GetUpperElementID + PrjID
                            if (sID.Equals(sCompID) == true)
                            {
                                // キーの生成（上流要素ID＋プロジェクトID＋送信パターンID）
                                string key = csCommonInfo.GetUpperElementID().ToString() + sPrjID + csCommonInfo.GetSendCellData().GetSendPatternID().ToString();
                                // キーで共有インスタンスを時刻単位で格納するハッシュが得られるか確認
                                if (m_csCommonTable[key] == null)
                                {
                                    // 無ければ、共有化対象となっているどの接続線でもよいので追加する
                                    Hashtable csData = new Hashtable();
                                    // プールからデータ取得
                                    //★★★修正 ここから★★★
                                    //string InstOKObjName = csCommonInfo.GetUpperElementID().ToString() + sPrjID;
                                    //LinkedList<McTranInfo> csInstOKListWork = null;
                                    //LinkedListNode<McTranInfo> csInstOKNodeWork = null;
                                    if (m_csDataListTable[InstOKObjName] == null)
                                    {   // 未だ登録されていないのでハッシュ領域を作成し、データはマスタ領域から取得
                                        csInstOKListWork = new LinkedList<McTranInfo>();
                                        m_csDataListTable.Add(InstOKObjName, csInstOKListWork);
                                        m_csClearObjNameList.Add(InstOKObjName);
                                        bRtnObj = csNodeWork.Value;
                                        csListWork.RemoveFirst();
                                    }
                                    else
                                    {
                                        csInstOKListWork = (LinkedList<McTranInfo>)m_csDataListTable[InstOKObjName];
                                        csInstOKNodeWork = csInstOKListWork.First;
                                        if (csInstOKListWork == null)
                                        {
                                            // ハッシュ領域は作成されているものの、データがない為、マスタ領域から取得
                                            bRtnObj = csNodeWork.Value;
                                            csListWork.RemoveFirst();
                                        }
                                        else
                                        {
                                            // ハッシュ領域は作成されていて、データもある為、ハッシュ領域から取得
                                            bRtnObj = csInstOKNodeWork.Value;
                                            csInstOKListWork.RemoveFirst();
                                        }
                                    }
                                    //★★★修正 ここまで★★★
                                    //bRtnObj = csNodeWork.Value;
                                    //csListWork.RemoveFirst();
                                    // 時刻単位データをハッシュ管理
                                    csData.Add(((McSendCellData)csCommonInfo.GetSendCellData()).GetCurrentTime().GetTime(), bRtnObj);
                                    //csData.Add(csSimTime.GetTime(), bRtnObj);
                                    // さらにハッシュを（上流要素ID＋送信パターンID）をキーとしたハッシュで管理
                                    m_csCommonTable.Add(key, csData);
                                }
                                else
                                {
                                    // ある場合、すでに誰かが管理しているので共有化インスタンスを利用する
                                    Hashtable csRtnHash = (Hashtable)m_csCommonTable[key];
                                    if (csRtnHash[((McSendCellData)csCommonInfo.GetSendCellData()).GetCurrentTime().GetTime()] == null)
                                    {
                                        // 次の時刻の共有化データはまだ追加されていない
                                        // プールからデータ取得
                                        //★★★修正 ここから★★★
                                        //string InstOKObjName = csCommonInfo.GetUpperElementID().ToString() + sPrjID;
                                        //LinkedList<McTranInfo> csInstOKListWork = null;
                                        //LinkedListNode<McTranInfo> csInstOKNodeWork = null;
                                        if (m_csDataListTable[InstOKObjName] == null)
                                        {   // 未だ登録されていないのでハッシュ領域を作成し、データはマスタ領域から取得
                                            csInstOKListWork = new LinkedList<McTranInfo>();
                                            m_csDataListTable.Add(InstOKObjName, csInstOKListWork);
                                            m_csClearObjNameList.Add(InstOKObjName);
                                            bRtnObj = csNodeWork.Value;
                                            csListWork.RemoveFirst();
                                        }
                                        else
                                        {
                                            csInstOKListWork = (LinkedList<McTranInfo>)m_csDataListTable[InstOKObjName];
                                            csInstOKNodeWork = csInstOKListWork.First;
                                            if (csInstOKNodeWork == null)
                                            {
                                                // ハッシュ領域は作成されているものの、データがない為、マスタ領域から取得
                                                bRtnObj = csNodeWork.Value;
                                                csListWork.RemoveFirst();
                                            }
                                            else
                                            {
                                                // ハッシュ領域は作成されていて、データもある為、ハッシュ領域から取得
                                                bRtnObj = csInstOKNodeWork.Value;
                                                csInstOKListWork.RemoveFirst();
                                            }
                                        }
                                        //★★★修正 ここまで★★★
                                        //bRtnObj = csNodeWork.Value;
                                        //csListWork.RemoveFirst();
                                        // 時刻単位データをハッシュ管理
                                        csRtnHash.Add(((McSendCellData)csCommonInfo.GetSendCellData()).GetCurrentTime().GetTime(), bRtnObj);
                                    }
                                    else
                                    {
                                        bRtnObj = (McTranInfo)csRtnHash[((McSendCellData)csCommonInfo.GetSendCellData()).GetCurrentTime().GetTime()];
                                    }

                                }
                            }
                            else
                            {
                                // 共有化条件を満たしていない（送信パターン、配列数及び最大レコード保持数が同一）
                                //★★★2014.10.28 修正 ここから★★★
                                if (csNodeWork == null)
                                {
                                    McTranInfo csObjType = (McTranInfo)m_csDataTypeTable[ObjName];
                                    if (csObjType != null)
                                    {   // 空きデータが存在しない場合生成する
                                        bRtnObj = csObjType.Clone();
                                    }
                                }
                                else
                                {
                                    bRtnObj = csNodeWork.Value;
                                    csListWork.RemoveFirst();
                                }
                                //★★★2014.10.28 修正 ここまで★★★
                            }
                            if( bRtnObj == null)
                            {
                                McTranInfo csObjType = (McTranInfo)m_csDataTypeTable[ObjName];
                                if (csObjType != null)
                                {   // 登録済みのデータであれば
                                    bRtnObj = csObjType.Clone();
                                }
                            }
                        }
                        else
                        {
                            // 送信元要素につながる他の接続線との共有化ができない
                            //★★★2014.10.28 修正 ここから★★★
                            if (csNodeWork == null)
                            {
                                McTranInfo csObjType = (McTranInfo)m_csDataTypeTable[ObjName];
                                if (csObjType != null)
                                {   // 空きデータが存在しない場合生成する
                                    bRtnObj = csObjType.Clone();
                                }
                            }
                            else
                            {
                                bRtnObj = csNodeWork.Value;
                                csListWork.RemoveFirst();
                            }
                            //★★★2014.10.28 修正 ここまで★★★
                        }
                    }
                }
                else
                {   // 空きデータが存在しない場合
                    // 生成する
                    McTranInfo csObjType = (McTranInfo)m_csDataTypeTable[ObjName];
                    if (csObjType != null)
                    {   // 登録済みのデータであれば
                        //long lIncrementNum = (long)m_csDataIncrementNum[ObjName];
                        bRtnObj = csObjType.Clone();
                        // 予め生成しておく
                        //for (long lCnt = 0; lCnt < lIncrementNum; lCnt++)
                        //{
                        //    csListWork.AddFirst(csObjType.Clone());
                        //}
                    }
                    else
                    {
                        // 何もしない
                        // 必要に応じてLog取得等の処理を追加してください
                    }
                }
            }
            m_csMutex.Release();

            return bRtnObj;
        }

        //★★★修正 ここから★★★
        //★★★★★★★★★★★★★★★★★★
        // Ver1.4で追加(インスタンスの共有化)
        //★★★★★★★★★★★★★★★★★★
        /// <summary><para>method outline:</para>
        /// <para>不要データインスタンス返却</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> TrashData(sPrjID, csDataKind, csData) </para>
        /// </example>
        /// <param name="sPrjID">プロジェクト識別子</param>
        /// <param name="csDataKind">伝送データの識別子（登録値と同じ）</param>
        /// <param name="lMaxDataNum">最大レコード保持数</param>
        /// <param name="csData">不用となった伝送データ</param>
        /// <param name="csCommonInfo">共通情報</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para></para>
        /// </remarks>
        static public void TrashData(string sPrjID, HySObjectKind csDataKind, long lMaxDataNum, McTranInfo csData, McTranInfoCommon csCommonInfo)
        {   // 不要のデータを　リスト管理へ戻しておく
            if( csData == null) { return; }
            csData.ResetData();  //何も考えずに行うと、演算速度が遅くなる為、外す側が責任を持って管理する
            if (csData is McD1CellArrayTranInfo)
            {
                ((McD1CellArrayTranInfo)csData).ClearData();
            }
            else if (csData is McD2CellArrayTranInfo)
            {
                ((McD2CellArrayTranInfo)csData).ClearData();
            }
            else if (csData is McD3CellArrayTranInfo)
            {
                ((McD3CellArrayTranInfo)csData).ClearData();
            }
            LinkedList<McTranInfo> csListWork = null;
            //★★★2014.10.28 修正 ここから★★★
            string ObjName = "";
            // 共有化有無の確認
            bool bCmnInsFlg = McTranInfoDataPool.CheckCommonInst(sPrjID, csDataKind, lMaxDataNum, csCommonInfo);
            if (bCmnInsFlg == true)
            {// 共有化有
                ObjName = csCommonInfo.GetUpperElementID().ToString() + sPrjID;
                if (m_csDataListTable[ObjName] != null)
                {   // 共有化接続線専用のハッシュ領域に対して返却
                    m_csMutex.Wait();
                    csListWork = (LinkedList<McTranInfo>)m_csDataListTable[ObjName];
                    if (csListWork != null)
                    {
                        csListWork.AddLast(csData);
                    }
                    m_csMutex.Release();
                }
            }
            else
            {// 共有化無
                ObjName = csDataKind.GetString().ToString() + sPrjID;
                m_csMutex.Wait();
                csListWork = (LinkedList<McTranInfo>)m_csDataListTable[ObjName];
                if (csListWork != null)
                {
                    csListWork.AddLast(csData);
                }
                m_csMutex.Release();
            }
            //★★★2014.10.28 修正 ここまで★★★
        }
        //★★★修正 ここまで★★★

        //★★★修正 ここから★★★
        /// <summary><para>method outline:</para>
        /// <para>共有化有無の確認</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>CheckCommonInstOK(sPrjID, csDataKind, lMaxDataNum, csCommonInfo) </para>
        /// </example>
        /// <param name="sPrjID">プロジェクトID</param>
        /// <param name="csDataKind">データ種別</param>
        /// <param name="lMaxDataNum">最大レコード保持数</param>
        /// <param name="csCommonInfo">共通情報</param>
        /// <returns>true:共有化有り, false:共有化無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public bool CheckCommonInst(string sPrjID, HySObjectKind csDataKind, long lMaxDataNum, McTranInfoCommon csCommonInfo)
        {
            return false;
            /*
            // 以下は、改悪となっている。
            string ObjName = csDataKind.GetString().ToString() + sPrjID;
            Hashtable csCommonInstTable = null;
            if (m_csCommonInstTablePrjID[sPrjID] == null)
            {
                // 管理情報が作られていない
                return false;
            }
            else
            {
                csCommonInstTable = (Hashtable)m_csCommonInstTablePrjID[sPrjID];
            }
            if (csCommonInstTable.Contains(csCommonInfo.GetUpperElementID().ToString() + sPrjID) == true)// GetUpperElementID + PrjID
            {
                // 送信元要素が他の接続線と同一である
                string sID = (string)csCommonInstTable[csCommonInfo.GetUpperElementID().ToString() + sPrjID];// GetUpperElementID + PrjID
                string sCompID = csCommonInfo.GetSendCellData().GetSendPatternID().ToString() + csDataKind.GetString().ToString() + lMaxDataNum.ToString();
                if (sID.Equals(sCompID) == true)
                {
                    // 送信パターンも同一である => インスタンスの共有化有り
                    return true;
                }
                else
                {
                    // インスタンスの共有化無し
                    return false;
                }
            }
            // インスタンスの共有化無し
            return false;
            */
        }
        //★★★修正 ここまで★★★

        ////★★★★★★★★★★★★★★★★★★
        //// Ver1.4で追加(インスタンスの共有化)
        ////★★★★★★★★★★★★★★★★★★
        ///// <summary><para>method outline:</para>
        ///// <para>不要データインスタンス返却</para>
        ///// </summary>
        ///// <example><para>usage:</para>
        ///// <para> TrashData(sPrjID, csDataKind, csData) </para>
        ///// </example>
        ///// <param name="sPrjID">プロジェクト識別子</param>
        ///// <param name="csDataKind">伝送データの識別子（登録値と同じ）</param>
        ///// <param name="csData">不用となった伝送データ</param>
        ///// <returns>無し</returns>
        ///// <exception cref="">無し</exception>
        ///// <remarks><para>remarks:</para>
        ///// <para></para>
        ///// </remarks>
        //static public void TrashData(string sPrjID, HySObjectKind csDataKind, McTranInfo csData)
        //{   // 不要のデータを　リスト管理へ戻しておく

        //    //csData.ResetData();  //何も考えずに行うと、演算速度が遅くなる為、外す側が責任を持って管理する

        //    LinkedList<McTranInfo> csListWork = null;
        //    string ObjName = csDataKind.GetString().ToString() + sPrjID;

        //    m_csMutex.Wait();
        //    csListWork = (LinkedList<McTranInfo>)m_csDataListTable[ObjName];
        //    csListWork.AddLast(csData);
        //    m_csMutex.Release();
        //}

        // 不要のデータを 破棄する
        /// <summary><para>method outline:</para>
        /// <para>不要データインスタンス返却</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> TrashData(csDataKind, csData) </para>
        /// </example>
        /// <param name="csDataKind">伝送データの識別子（登録値と同じ）</param>
        /// <param name="csData">不用となった伝送データ</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para></para>
        /// </remarks>
        static public void TrashData(HySObjectKind csDataKind, McTranInfo csData)
        {   // 不要のデータを　リスト管理へ戻しておく

            //csData.ResetData();  //何も考えずに行うと、演算速度が遅くなる為、外す側が責任を持って管理する
            if (csData == null) { return; }

            LinkedList<McTranInfo> csListWork = null;
            string ObjName = csDataKind.GetString().ToString();

            m_csMutex.Wait();
            csListWork = (LinkedList<McTranInfo>)m_csDataListTable[ObjName];
            if (csListWork != null)
            {
                csListWork.AddLast(csData);
            }
            m_csMutex.Release();
        }
    }
}
