ulysseskao
2016-04-29 b0c18d369abd06075c83759b0e19823c2a11d716
CCSTrace/CCS/CCSMain.cs
@@ -1,162 +1,174 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml;
using System.Data.OracleClient;
using System.IO;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Web;
using System.Xml;
using Amib.Threading;
using CCSTrace.CCS.Domain;
using CCSTrace.CCS.Object;
using NLog;
namespace CCSTrace.CCS
{
    public class CCSMain
    public class CcsMain
    {
        private static CCSMain _instance;
        public static CCS.Object.CCSCodelist CCSCodelist;
        public static CCS.Object.EOSCodelist EOSCodelist;
        public static System.Collections.ArrayList DBConnList = new System.Collections.ArrayList();
        public static System.Collections.ArrayList ProcessCases = new System.Collections.ArrayList();
        private const string DbConfigFilename = "DBConfig.xml";
        private string LoadFilename = "DBConfig.xml";
        private string ConnectionString = String.Empty;
        private string traceConnectionString = String.Empty;
        private int ConnectionCount = 1;
        public static System.Data.OracleClient.OracleConnection MainConn = null;
        static SEventLog _MainLog = null;
        private static Logger _logger = LogManager.GetCurrentClassLogger();
        private static CcsMain _instance;
        public static System.Collections.Hashtable ProcessFDR = new System.Collections.Hashtable();//Record the processing FDR
        public static System.Collections.ArrayList WaitingCases = new System.Collections.ArrayList();//Record the case when the case's FDR processed by another
        public static ArrayList ProcessCases = new ArrayList();
        public static Queue<int> ProcessCaseQueue = new Queue<int>();
        public static Hashtable ProcessFdr = new Hashtable();//Record the processing FDR
        public static ArrayList WaitingCases = new ArrayList();//Record the case when the case's FDR processed by another
        public CCSMain()
        private int _connectionCount = 1;
        private OracleConnection _mainConn = null;
        private SEventLog _mainLog = null;
        private SmartThreadPool _mainjobThreadPool = null;
        private readonly object _syncDbQueue = new object();
        private readonly Queue<OracleConnection> _dbQueue = new Queue<OracleConnection>();
        public CcsMain()
        {
            Initial();
            _mainjobThreadPool = new SmartThreadPool();
            // Startup();
        }
        public static CCSMain Instance()
        {
        public string AppDataPath { get; set; }
        public static CcsMain Instance()
        {
            // Uses lazy initialization.
            // Note: this is not thread safe.
            if (_instance == null)
            {
                _instance = new CCSMain();
                _instance = new CcsMain();
            }
            return _instance;
        }
        private void Initial()
        public void Startup()
        {
            _MainLog = new SEventLog();
            _mainLog = new SEventLog();
            try
            {
                ReadXML();
                ReadXml();
                if (MainConn == null)
                    MainConn = CreateConnection();
                    //MainConn = CreateMainConnection();
                if (_mainConn == null)
                    _mainConn = CreateConnection();
                //MainConn = CreateMainConnection();
                CCSCodelist = new CCSTrace.CCS.Object.CCSCodelist(MainConn);
                EOSCodelist = new CCSTrace.CCS.Object.EOSCodelist(MainConn);
                GlobalVariable.CcsCodelist = new CcsCodelist(_mainConn);
                GlobalVariable.EosCodelist = new EosCodelist(_mainConn);
                for (int i = 0; i < ConnectionCount; i++)
                    DBConnList.Add(CreateConnection());
                for (int i = 0; i < _connectionCount; i++)
                {
                    lock (_syncDbQueue) _dbQueue.Enqueue(CreateConnection());
                }
            }
            catch(Exception e)
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                Console.WriteLine(e.StackTrace);
                _MainLog.Error(e.Message);
                _mainLog.Error(e.Message);
                if (LocalVariable.ShowError)
                    _MainLog.Error(e.StackTrace);
                if (GlobalVariable.ShowError)
                    _mainLog.Error(e.StackTrace);
                throw e;
                throw;
            }
            finally
            {
                _MainLog.Close();
                _mainLog.Close();
            }
            Object.CCSRecord m_Record = getWaitRecord();
            CcsRecord mRecord = GetWaitRecord(_mainConn);
            if (m_Record != null)
            if (mRecord != null)
            {
                System.Data.OracleClient.OracleConnection _Conn = (System.Data.OracleClient.OracleConnection)DBConnList[0];
                DBConnList.Remove(_Conn);
                ProcessCase(m_Record, _Conn);
                OracleConnection conn = null;
                lock (_syncDbQueue) conn = _dbQueue.Dequeue();
                ProcessCase(mRecord, conn);
            }
            STPStartInfo stpStartInfo = new STPStartInfo();
            stpStartInfo.IdleTimeout = GlobalVariable.IdleTimeout * 1000;
            stpStartInfo.MaxWorkerThreads = GlobalVariable.MaxThreadSize;
            stpStartInfo.MinWorkerThreads = GlobalVariable.MinThreadSize;
            _mainjobThreadPool = new SmartThreadPool(stpStartInfo);
        }
        public void AcceptEvent(Object.CCSRecord _Record)
        public void Shutdown()
        {
            _mainjobThreadPool.Shutdown(true, 1000);
            _mainjobThreadPool.Dispose();
            _mainjobThreadPool = null;
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }
        public void AcceptEvent(CcsRecord record)
        {
            int i = 0;
            int ReConnectCount = 1;
            int reConnectCount = 1;
            while ( i <= ReConnectCount )
            while (i <= reConnectCount)
            {
                try
                {
                    if (InsertEventRecord(_Record))
                    if (InsertEventRecord(record, _mainConn))
                    {
                        if (DBConnList.Count > 0)
                        if (_dbQueue.Count > 0)
                        {
                            //將EVETNQUERY的案件狀態改為開始處理
                            Object.CCSRecord m_Record = getWaitRecord();
                            CcsRecord mRecord = GetWaitRecord(_mainConn);
                            if (m_Record != null)
                            if (mRecord != null)
                            {
                                System.Data.OracleClient.OracleConnection _Conn = (System.Data.OracleClient.OracleConnection)DBConnList[0];
                                DBConnList.Remove(_Conn);
                                ProcessCase(m_Record, _Conn);
                                OracleConnection conn = _dbQueue.Dequeue();
                                ProcessCase(mRecord, conn);
                            }
                        }
                        break;
                    }
                }
                catch (Exception ex)
                catch (Exception)
                {
                    if (MainConn.State.ToString().Equals("Closed"))
                    if (_mainConn.State == ConnectionState.Closed)
                    {
                        i++;
                        if (i > ReConnectCount)
                            throw ex;
                        if (i > reConnectCount)
                            throw;
                    }
                    else
                        throw ex;
                        throw;
                }
            }
        }
        private void ReadXML()
        private void ReadXml()
        {
            XmlReader reader = null;
            try
            {
                string file = Path.Combine(AppDataPath, DbConfigFilename);
                // 建立 XML 讀取器
                XmlReaderSettings settings = new XmlReaderSettings();
                settings.IgnoreComments = true; // 不處理註解
                settings.IgnoreWhitespace = true; // 跳過空白
                settings.ValidationType = ValidationType.None; // 不驗證任何資料
                reader = XmlTextReader.Create(System.AppDomain.CurrentDomain.BaseDirectory + "\\" + LoadFilename, settings);
                reader = XmlReader.Create(file, settings);
                // 進入讀取主要部分
                while (reader.Read())
@@ -164,273 +176,290 @@
                    switch (reader.NodeType)
                    {
                        case XmlNodeType.Element:
                            string LocalName = reader.LocalName; // 取得標籤名稱
                            string localName = reader.LocalName; // 取得標籤名稱
                            // Step 3: 讀取 FileInfo 標籤的屬性
                            if (LocalName.Equals("DBSetting"))
                            if (localName.Equals("DBSetting"))
                            {
                                ConnectionString = String.Format("Data source={0};User Id={1};Password={2};", reader["DataSource"], reader["UserId"], reader["Password"]) ;
                                traceConnectionString = String.Format("{0}/{1}@{2}", reader["UserId"], reader["Password"], reader["DataSource"]);
                                ConnectionCount = Int32.Parse(reader["ConnectionCount"]);
                                LocalVariable.ShowError = bool.Parse(reader["ShowError"]);
                                GlobalVariable.ConnectionString =
                                    $"Data source={reader["DataSource"]};User Id={reader["UserId"]};Password={reader["Password"]};";
                                GlobalVariable.TraceConnectionString =
                                    $"{reader["UserId"]}/{reader["Password"]}@{reader["DataSource"]}";
                                string token = reader["ConnectionCount"];
                                if (token != null)
                                {
                                    GlobalVariable.MaxConnectionCount = int.Parse(token);
                                }
                                token = reader["ShowError"];
                                if (token != null)
                                {
                                    GlobalVariable.ShowError = bool.Parse(token);
                                }
                            } else if (localName.Equals("ThreadSetting"))
                            {
                                string token = reader["maxThreadSize"];
                                if (token != null)
                                {
                                    GlobalVariable.MaxThreadSize = int.Parse(token);
                                }
                                token = reader["minThreadSize"];
                                if (token != null)
                                {
                                    GlobalVariable.MinThreadSize = int.Parse(token);
                                }
                            }
                            break;
                    }
                }
                reader.Close();
            }
            catch (System.Xml.XmlException xe)
            catch (XmlException xe)
            {
                Console.WriteLine(xe.StackTrace);
                reader.Close();
                reader?.Close();
            }
        }
        private System.Data.OracleClient.OracleConnection CreateConnection()
        private OracleConnection CreateConnection()
        {
            System.Data.OracleClient.OracleConnection DBConn = new System.Data.OracleClient.OracleConnection(ConnectionString);
            DBConn.Open();
            OracleConnection dbConn = new OracleConnection(GlobalVariable.ConnectionString);
            return DBConn;
            dbConn.Open();
            return dbConn;
        }
        [MethodImpl(MethodImplOptions.Synchronized)]
        private bool InsertEventRecord(Object.CCSRecord _Record)
        private bool InsertEventRecord(CcsRecord record, OracleConnection conn)
        {
            Object.EventQuery _EventQuery = null;
            System.Data.OracleClient.OracleTransaction _Transaction = null;
            OracleTransaction transaction = null;
            try
            {
                _MainLog = new SEventLog();
                _mainLog = new SEventLog();
                if (MainConn.State.ToString().Equals("Closed"))
                    MainConn.Open();
                if (conn.State.ToString().Equals("Closed"))
                    conn.Open();
                _Transaction = MainConn.BeginTransaction();
                transaction = conn.BeginTransaction();
                if (_Record.InsertDB(MainConn, _Transaction, _MainLog))
                if (record.InsertDb(conn, transaction, _mainLog))
                {
                    _EventQuery = new CCSTrace.CCS.Object.EventQuery();
                    var eventQuery = new EventQuery
                    {
                        CcsId = record.CcsId,
                        Meter = record.Meter,
                        CaseStatus = (int) CCSCaseState.EventInitial,
                        ChangeTime = record.AcceptTime
                    };
                    _EventQuery.setCCSID(_Record.getCCSID());
                    _EventQuery.setMeter(_Record.getMeter());
                    _EventQuery.setCaseStatus(LocalVariable.EventInitial);
                    _EventQuery.setChangeTime(_Record.getAcceptTime());
                    if (_EventQuery.Insert(_MainLog, MainConn, _Transaction))
                        _Transaction.Commit();
                    if (eventQuery.Insert(_mainLog, conn, transaction))
                        transaction.Commit();
                    else
                    {
                        if (_Transaction.Connection.State.ToString().Equals("Open"))
                            _Transaction.Rollback();
                        if (transaction.Connection.State.ToString().Equals("Open"))
                            transaction.Rollback();
                        throw new Exception("案件未受理成功。");
                    }
                }
                else
                {
                    if (_Transaction.Connection.State.ToString().Equals("Open"))
                        _Transaction.Rollback();
                    if (transaction.Connection.State.ToString().Equals("Open"))
                        transaction.Rollback();
                    throw new Exception("案件未受理成功。");
                }
            }
            catch (System.Data.OracleClient.OracleException e)
            catch (OracleException e)
            {
                Console.WriteLine(e.Message);
                Console.WriteLine(e.StackTrace);
                _MainLog.Error(e.Message);
                _mainLog.Error(e.Message);
                if (LocalVariable.ShowError)
                    _MainLog.Error(e.StackTrace);
                if (GlobalVariable.ShowError)
                    _mainLog.Error(e.StackTrace);
                if (_Transaction != null && _Transaction.Connection.State.ToString().Equals("Open") )
                    _Transaction.Rollback();
                if (transaction != null && transaction.Connection.State.ToString().Equals("Open"))
                    transaction.Rollback();
                throw e;
                throw;
            }
            catch(Exception ex)
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.StackTrace);
                _MainLog.Error(ex.Message);
                _mainLog.Error(ex.Message);
                if (LocalVariable.ShowError)
                    _MainLog.Error(ex.StackTrace);
                if (GlobalVariable.ShowError)
                    _mainLog.Error(ex.StackTrace);
                if (_Transaction != null && _Transaction.Connection.State.ToString().Equals("Open") )
                    _Transaction.Rollback();
                if (transaction != null && transaction.Connection.State.ToString().Equals("Open"))
                    transaction.Rollback();
                throw ex;
                throw;
            }
            finally
            {
                _MainLog.Close();
                _mainLog.Close();
            }
            return true;
        }
        delegate void WorkerThreadHandler();
        private delegate void WorkerThreadHandler();
        private void ProcessCase(Object.CCSRecord _Record, System.Data.OracleClient.OracleConnection _Conn)
        private void ProcessCase(CcsRecord record, OracleConnection conn)
        {
            try
            {
                if (_Conn.State.ToString().Equals("Closed"))
                    _Conn.Open();
                if (conn.State.ToString().Equals("Closed"))
                    conn.Open();
                ProcessEvent _ProcessEvent = new ProcessEvent(_Record, _Conn, traceConnectionString);
                _ProcessEvent.ThreadFinish += new ThreadEndEventHandler(ThreadEndEventProcess);
                ProcessEvent processEvent = new ProcessEvent(record, conn, GlobalVariable.TraceConnectionString);
                processEvent.ThreadFinish += ThreadEndEventProcess;
                System.Threading.ThreadStart _ThreadStart = new System.Threading.ThreadStart(_ProcessEvent.Run);
                System.Threading.Thread _Thread = new System.Threading.Thread(_ThreadStart);
                _Thread.Start();
                ThreadStart threadStart = processEvent.Run;
                Thread thread = new Thread(threadStart);
                thread.Start();
            }
            catch
            {
                DBConnList.Add(_Conn);
                lock (_syncDbQueue) _dbQueue.Enqueue(conn);
            }
        }
        private void ThreadEndEventProcess(object sender, ThreadEndEvent e)
        {
            //將EVETNQUERY的案件狀態改為開始處理
            Object.CCSRecord m_Record = getWaitRecord();
            CcsRecord mRecord = GetWaitRecord(e.GetConnection());
            try
            {
                if (m_Record != null)
                    ProcessCase(m_Record, e.getConnection());
                else
                    DBConnList.Add(e.getConnection());
                if (mRecord != null)
                    ProcessCase(mRecord, e.GetConnection());
            }
            catch
            finally
            {
                DBConnList.Add(e.getConnection());
                lock (_syncDbQueue) _dbQueue.Enqueue(e.GetConnection());
            }
        }
        }
        [MethodImpl(MethodImplOptions.Synchronized)]
        private Object.CCSRecord getWaitRecord()
        private CcsRecord GetWaitRecord(OracleConnection conn)
        {
            String ProcessCCSID = "";
            String CCSID = "";
            Object.CCSRecord _Record = null;
            string processCcsid = "";
            string ccsid = "";
            CcsRecord record = null;
            foreach (String[] Obj in WaitingCases)
            foreach (string[] obj in WaitingCases)
            {
                String _CCSID = Obj[0];
                String _FDRID = Obj[1];
                string ccsId = obj[0];
                string fdrid = obj[1];
                if (ProcessFDR.ContainsKey(_FDRID)) //該條饋線仍有案件在處理中
                    ProcessCCSID = ProcessCCSID + "'" + _CCSID + "',";
                if (ProcessFdr.ContainsKey(fdrid)) //該條饋線仍有案件在處理中
                    processCcsid = processCcsid + "'" + ccsid + "',";
                else
                {
                    CCSID = _CCSID;
                    WaitingCases.Remove(Obj);
                    ccsid = ccsId;
                    WaitingCases.Remove(obj);
                    break;
                }
            }
            if (CCSID.Length == 0)  //沒有因同饋線而在等候中的案件
            if (ccsid.Length == 0)  //沒有因同饋線而在等候中的案件
            {
                String SqlStmt = "SELECT Q.CCSID AS CCSID FROM CCS.EVENTQUERY Q,CCS.EVENTRECORD R WHERE Q.CASESTATUS IN (" + LocalVariable.EventInitial + "," + LocalVariable.EventProcess + ")";
                System.Collections.IEnumerator Enum = ProcessCases.GetEnumerator();
                string sqlStmt = "SELECT Q.CCSID AS CCSID FROM CCS.EVENTQUERY Q,CCS.EVENTRECORD R WHERE Q.CASESTATUS IN (" + (int) CCSCaseState.EventInitial + "," + (int) CCSCaseState.EventProcess + ")";
                IEnumerator Enum = ProcessCases.GetEnumerator();
                while (Enum.MoveNext())
                    ProcessCCSID = ProcessCCSID + "'" + Enum.Current.ToString() + "',";
                    if (Enum.Current != null) processCcsid = processCcsid + "'" + Enum.Current + "',";
                if (ProcessCCSID.Length != 0)
                    SqlStmt = SqlStmt + " AND Q.CCSID NOT IN (" + ProcessCCSID.Substring(0, ProcessCCSID.Length - 1) + ")";
                if (processCcsid.Length != 0)
                    sqlStmt = sqlStmt + " AND Q.CCSID NOT IN (" + processCcsid.Substring(0, processCcsid.Length - 1) + ")";
                SqlStmt = SqlStmt + " AND Q.CCSID = R.CCSID AND ROWNUM < 2 ORDER BY Q.ChangeTime";
                System.Data.OracleClient.OracleCommand Command = new System.Data.OracleClient.OracleCommand(SqlStmt, MainConn);
                System.Data.OracleClient.OracleDataReader reader = Command.ExecuteReader();
                sqlStmt = sqlStmt + " AND Q.CCSID = R.CCSID AND ROWNUM < 2 ORDER BY Q.ChangeTime";
                OracleCommand command = new OracleCommand(sqlStmt, conn);
                OracleDataReader reader = command.ExecuteReader();
                try
                {
                    if (reader.Read())
                        CCSID = reader["CCSID"].ToString();
                        ccsid = reader["CCSID"].ToString();
                }
                catch (Exception e)
                {
                    Log(e.Message);
                    _MainLog.Error("無法取得等候處理CCS案件資料。錯誤訊息 = " + e.Message);
                    _mainLog.Error("無法取得等候處理CCS案件資料。錯誤訊息 = " + e.Message);
                    if (LocalVariable.ShowError)
                        _MainLog.Error(e.StackTrace);
                    if (GlobalVariable.ShowError)
                        _mainLog.Error(e.StackTrace);
                }
                finally
                {
                    reader.Close();
                    Command.Dispose();
                    command.Dispose();
                }
            }
            if (CCSID.Length != 0)
                _Record = new Object.CCSRecord(CCSID, MainConn, _MainLog);
            if (ccsid.Length != 0)
                record = new CcsRecord(ccsid, conn, _mainLog);
            if (_Record != null)
            if (record != null)
            {
                CCS.Object.EventQuery EventQuery = new CCSTrace.CCS.Object.EventQuery();
                EventQuery eventQuery = new EventQuery();
                //先將EVETNQUERY的案件狀態改為開始處理
                EventQuery.setCCSID(_Record.getCCSID());
                EventQuery.setCaseStatus(LocalVariable.EventProcess);
                eventQuery.CcsId = record.CcsId;
                eventQuery.CaseStatus = (int) CCSCaseState.EventProcess;
                System.Data.OracleClient.OracleTransaction _Transaction = MainConn.BeginTransaction();
                OracleTransaction transaction = conn.BeginTransaction();
                try
                {
                    if (EventQuery.UpdateCaseStatus(_MainLog, MainConn, _Transaction))
                    if (eventQuery.UpdateCaseStatus(_mainLog, conn, transaction))
                    {
                        _MainLog.Info("更新EVENTQUERY的案件狀態為處理中.(CCSID = " + _Record.getCCSID() + ")");
                        _Transaction.Commit();
                        ProcessCases.Add(_Record.getCCSID());
                        _mainLog.Info("更新EVENTQUERY的案件狀態為處理中.(CCSID = " + record.CcsId + ")");
                        transaction.Commit();
                        ProcessCases.Add(record.CcsId);
                    }
                    else
                    {
                        _MainLog.Error("無法更新EVENTQUERY的案件狀態.(CCSID = " + _Record.getCCSID() + ")");
                        _mainLog.Error("無法更新EVENTQUERY的案件狀態.(CCSID = " + record.CcsId + ")");
                        if (_Transaction.Connection.State.ToString().Equals("Open"))
                            _Transaction.Rollback();
                        if (transaction.Connection.State.ToString().Equals("Open"))
                            transaction.Rollback();
                    }
                }
                catch (Exception e)
                {
                    if (_Transaction.Connection.State.ToString().Equals("Open"))
                        _Transaction.Rollback();
                    if (transaction.Connection.State.ToString().Equals("Open"))
                        transaction.Rollback();
                    Log(e.Message);
                    _Record = null;
                    record = null;
                }
            }
            return _Record;
            return record;
        }
        private void Log(String message)
        private void Log(string message)
        {
            RecordLog _PLog = null;
            RecordLog pLog = null;
            try
            {
                _PLog = new RecordLog(CCS.LocalVariable.CCS_ListPath + "MAIN.txt");
                _PLog.Error(message);
                pLog = new RecordLog(GlobalVariable.CcsListPath + "MAIN.txt");
                pLog.Error(message);
            }
            finally
            {
                if (_PLog != null)
                if (pLog != null)
                {
                    _PLog.Close();
                    pLog.Close();
                }
            }
        }
    }
}
}