프로젝트

일반

사용자정보

통계
| 브랜치(Branch): | 개정판:

markus / ConvertService / ServiceBase / Markus.Service.Station / ServiceStation.cs @ a9e86f7a

이력 | 보기 | 이력해설 | 다운로드 (17.6 KB)

1 53c9637d taeseongkim
using log4net;
2 60723dc9 taeseongkim
using Markus.EntityModel;
3 53c9637d taeseongkim
using Markus.Service.Extensions;
4
using Markus.Service.Helper;
5
using Markus.Service.IWcfService;
6
using Markus.Service.WcfService;
7
using Salaros.Configuration;
8
using System;
9
using System.Collections.Generic;
10
using System.ComponentModel;
11
using System.Data;
12
using System.Diagnostics;
13
using System.Globalization;
14
using System.IO;
15
using System.Linq;
16
using System.Runtime.InteropServices;
17
using System.ServiceModel;
18 1ae729e4 taeseongkim
using System.ServiceModel.Channels;
19
using System.ServiceModel.Dispatcher;
20 53c9637d taeseongkim
using System.ServiceProcess;
21
using System.Text;
22
using System.Threading.Tasks;
23
using System.Timers;
24
using static Markus.Service.Extensions.Encrypt;
25
26
namespace Markus.Service
27
{
28
    public partial class ServiceStation : ServiceBase
29
    {
30
        protected ILog logger = LogManager.GetLogger(typeof(ServiceStation));
31
        protected ServiceHost gWcfServiceHost;
32 60723dc9 taeseongkim
        private SERVICE_PROPERTIES ServiceProperty;
33 53c9637d taeseongkim
34 ff4b1e6e taeseongkim
        private static System.Timers.Timer timer;
35 06f13e11 taeseongkim
        
36 0157b158 taeseongkim
        private string ServiceID;
37
        private List<SubStationServiceItem> StationServiceList;
38
        private List<string> StationServiceIDList;
39 60723dc9 taeseongkim
        private Service.WcfClient.StationServiceTask.StationServiceClient StationClient;
40 06f13e11 taeseongkim
        private bool IsStation;
41 53c9637d taeseongkim
42
        private Uri gServiceHostAddress;
43
44
        private string MarkusDBConnectionString;
45
        private string DownloadTempFolder;
46
        private int MultiThreadMaxPages;
47
        private int MinFontSize;
48 2091a7e5 taeseongkim
        private int UseResolution;
49 53c9637d taeseongkim
        private bool CreateProcessWindow;
50 8feb21df taeseongkim
        private long ReleaseWorkMemory;
51 53c9637d taeseongkim
52
        private int SaveStatusInterval;
53
54 06f13e11 taeseongkim
        private static bool IsReleaseItems;
55
56 53c9637d taeseongkim
        private List<string> RunProjectList = new List<string>();
57
58
        /// <summary>
59
        /// 프로세스 카운터 자주 람다식을 사용해서 list<int>로 함.
60
        /// </summary>
61
        private List<Int64> ProcessorAffinityList;
62
63
        private string configFileName;
64
65
        public ServiceStation()
66
        {
67
            InitializeComponent();
68
        }
69
70 a53dfe45 taeseongkim
        /// <summary>
71
        /// Config 파일 
72
        /// </summary>
73 53c9637d taeseongkim
        public void GetApplicationConfig()
74
        {
75
            try
76
            {
77
                ConfigParser config = null;
78
79
                try
80
                {
81
                    configFileName = $"{typeof(ServiceStation).Name}.ini";
82
                    config = ConfigHelper.AppConfig(this.configFileName);
83
                }
84 150747cb taeseongkim
                catch (Exception ex)
85 53c9637d taeseongkim
                {
86 150747cb taeseongkim
                    throw new Exception("Config Read Error.", ex);
87 53c9637d taeseongkim
                }
88
89
                if (config != null)
90
                {
91 0157b158 taeseongkim
                    // CONVERT DATABASE 연결 문자열
92
                    MarkusDBConnectionString = AESEncrypter.Decrypt(config.GetValue(CONFIG_DEFINE.SERVICE, CONFIG_DEFINE.MARKUS_CONNECTION_STRING));
93
94 06f13e11 taeseongkim
                    IsStation = System.Convert.ToBoolean(config.GetValue(CONFIG_DEFINE.SERVICE, CONFIG_DEFINE.IS_STATAION, "false"));
95 0157b158 taeseongkim
96 06f13e11 taeseongkim
                    ServiceID = config.GetValue(CONFIG_DEFINE.SERVICE, CONFIG_DEFINE.SERVICE_ID, Guid.Empty.ToString());
97 0157b158 taeseongkim
98 06f13e11 taeseongkim
                    if (IsStation)
99 0157b158 taeseongkim
                    {
100 06f13e11 taeseongkim
                        var servicetList = config.GetValue(CONFIG_DEFINE.SERVICE, CONFIG_DEFINE.SERVICE_LIST, "");
101 0157b158 taeseongkim
102 06f13e11 taeseongkim
                        if (!servicetList.IsNullOrEmpty())
103
                        {
104
                            StationServiceIDList = servicetList.Split(',').ToList();
105
                        }
106
                    }
107
                    else
108
                    {
109
                        var address = config.GetValue(CONFIG_DEFINE.SERVICE, CONFIG_DEFINE.STATAION_ADDRESS,"");
110 0157b158 taeseongkim
111 06f13e11 taeseongkim
                        if (!address.IsNullOrEmpty())
112
                        {
113
                            BasicHttpBinding myBinding = new BasicHttpBinding();
114
                            EndpointAddress myEndpoint = new EndpointAddress(UriHelper.UriCreate(address));
115 60723dc9 taeseongkim
                            StationClient = new WcfClient.StationServiceTask.StationServiceClient(myBinding, myEndpoint);
116 06f13e11 taeseongkim
                        }
117
                    }
118 53c9637d taeseongkim
119
                    CreateProcessWindow = System.Convert.ToBoolean(config.GetValue(CONFIG_DEFINE.SERVICE, CONFIG_DEFINE.CREATE_WINDOW, "false"));
120
121
                    // PDF 임시 다운로드 폴더
122 2091a7e5 taeseongkim
                    DownloadTempFolder = config.GetValue(CONFIG_DEFINE.SERVICE, CONFIG_DEFINE.DOWNLOAD_TEMP_FOLDER,"C:\\temp");
123 53c9637d taeseongkim
124 2bbea412 taeseongkim
                    // pThraed를 이용한 컨버팅 설정.
125
                    //최대 페이지가 MultiThreadMaxPages설정까지 pThread를 적용하여 컨버팅함.
126 53c9637d taeseongkim
                    MultiThreadMaxPages = System.Convert.ToInt16(config.GetValue(CONFIG_DEFINE.SERVICE, CONFIG_DEFINE.MULTI_TRHEAD_MAX_PAGE, "500"));
127
128 2bbea412 taeseongkim
                    // 서비스 상태 Log 저장간격
129 53c9637d taeseongkim
                    SaveStatusInterval = System.Convert.ToInt16(config.GetValue(CONFIG_DEFINE.SERVICE, CONFIG_DEFINE.SAVE_STATUS_INTERVAL, "5"));
130
131 2bbea412 taeseongkim
                    //PDF에 폰트가 최소 폰트 사이즈보다 작은 사이증의 폰트가 있으면 해상도를 높여서 컨버팅함.
132 53c9637d taeseongkim
                    MinFontSize = System.Convert.ToInt16(config.GetValue(CONFIG_DEFINE.SERVICE, CONFIG_DEFINE.MIN_FONT_SIZE, "10"));
133
134 2bbea412 taeseongkim
                    // 사용자 설정의 해상도
135
                    // MinFontSize를 -1로 하고 UseResolution를 설정하면 해당 해상도로 컨버팅됨
136 2091a7e5 taeseongkim
                    UseResolution = System.Convert.ToInt16(config.GetValue(CONFIG_DEFINE.SERVICE, CONFIG_DEFINE.USE_RESOLUTION, "0"));
137
138 2bbea412 taeseongkim
                    // 각 프로세스의 최대 메모리 사용량
139 0157b158 taeseongkim
                    var workingMemory = System.Convert.ToDouble(config.GetValue(CONFIG_DEFINE.SERVICE, CONFIG_DEFINE.RELEASE_WORK_MEMORY, "1.5"));
140 8feb21df taeseongkim
141
                    ReleaseWorkMemory = MathBytes.Bytes(workingMemory, DataSizeType.GB);
142
143 2bbea412 taeseongkim
                    // 서비스 사용 프로젝트
144 2091a7e5 taeseongkim
                    var projectList = config.GetValue(CONFIG_DEFINE.SERVICE, CONFIG_DEFINE.FITER_PROCECT,"");
145 53c9637d taeseongkim
146
                    if(!projectList.IsNullOrEmpty())
147
                    {
148
                        RunProjectList = projectList.Split(',').ToList();
149
                    }
150
151
                    // 서비스 ENDPOINT
152
                    // http://localhost/
153
                    var endpointName = config.GetValue(CONFIG_DEFINE.WCF_ENDPOINT, CONFIG_DEFINE.STATION_SERVICE_NAME);
154
                    var port = config.GetValue(CONFIG_DEFINE.WCF_ENDPOINT, CONFIG_DEFINE.STATION_PORT);
155
156
                    if (!string.IsNullOrWhiteSpace(endpointName) && port.IsNumber())
157
                    {
158
                        gServiceHostAddress = UriHelper.UriCreate($"http://localhost:{port}/{endpointName}");
159
                    }
160 60723dc9 taeseongkim
161 2bbea412 taeseongkim
                    // 각  ConvertService의 원격 관리를 위한 서비스 설정 로드
162 60723dc9 taeseongkim
                    using (Markus.Service.DataBase.ConvertDatabase db = new Markus.Service.DataBase.ConvertDatabase(MarkusDBConnectionString))
163
                    {
164
                        ServiceProperty = db.GetServiceProperties(ServiceID);
165
                    }
166 53c9637d taeseongkim
                }
167
            }
168
            catch (Exception ex)
169
            {
170
                throw new Exception("ApplicationConfig ", ex);
171
            }
172
        }
173
174
        protected override void OnStart(string[] args)
175
        {
176
            try
177
            {
178
                StartService();
179
            }
180
            catch (Exception ex)
181
            {
182
                logger.Error("ServiceStation Start Error - ", ex);
183
            }
184
        }
185 2bbea412 taeseongkim
        
186 06f13e11 taeseongkim
        /// <summary>
187
        /// alivequeue와 process를 비교하여 정리하고
188
        /// 대기중인 아이템을 분배한다.
189
        /// </summary>
190
        private void ReleaseItems()
191
        {
192 0157b158 taeseongkim
            try
193 53c9637d taeseongkim
            {
194 06f13e11 taeseongkim
                IsReleaseItems = true;
195
196
                CleanUpAliveQueueItems();
197
198
                if (IsStation)
199
                {
200 60723dc9 taeseongkim
                    //if (IsDataBaseWaitingList(1))
201
                    //{
202 1ae729e4 taeseongkim
                    System.Diagnostics.Debug.WriteLine("ReleaseItems start");
203
                    ReflashSubServiceAsync();
204
205
                    if (StationServiceList.All(x => x.IsOnline))
206
                    {
207 ff4b1e6e taeseongkim
                        CleanUpDataBaseItems();
208
                        setDataBaseWaitingList();
209 1ae729e4 taeseongkim
                    }
210
                    else
211
                    {
212
                        System.Diagnostics.Debug.WriteLine("Service Any Offline");
213
                    }
214
215
                    System.Diagnostics.Debug.WriteLine("ReleaseItems end");
216 60723dc9 taeseongkim
                    //}
217 06f13e11 taeseongkim
                }
218 53c9637d taeseongkim
            }
219 0157b158 taeseongkim
            catch (Exception ex)
220 53c9637d taeseongkim
            {
221 0157b158 taeseongkim
                logger.Error("get Wating Item error", ex);
222 53c9637d taeseongkim
            }
223
224 06f13e11 taeseongkim
            IsReleaseItems = false;
225 53c9637d taeseongkim
        }
226
227 a53dfe45 taeseongkim
        /// <summary>
228
        /// System.Diagnostics.Process의 ProcessorAffinity Core 선호도를 위한 초기화
229
        /// 설정된 MultiProcessCount에 대해서 프로세스의 코어의 선호도를 지정 한다.
230
        /// 코어의 선택은 비트로 이루어 진다.
231
        /// 8코어에서 1번 코어 00000001
232
        /// 8코어에서 1번 3번 코어 00000101
233
        /// 8코어에서 1번 3번 코어 00000101
234
        /// 8코어에서 1,2,3 선택   00000111
235
        /// https://dotnetgalactics.wordpress.com/2009/10/20/how-to-set-the-processor-affinity-programatically/
236
        /// </summary>
237 53c9637d taeseongkim
        private void ProcessorAffinityInit()
238
        {
239
            ProcessorAffinityList = new List<long>();
240
241
            int processCount = Environment.ProcessorCount;
242
            int AffinityScope = 1;
243
244 60723dc9 taeseongkim
            if (processCount > ServiceProperty.PROCESS_COUNT)
245 53c9637d taeseongkim
            {
246 60723dc9 taeseongkim
                AffinityScope = processCount / ServiceProperty.PROCESS_COUNT;
247 53c9637d taeseongkim
            }
248
249
            for (int i = 0; i < processCount - AffinityScope; i += AffinityScope)
250
            {
251
                var bits = new int[processCount];
252
253
                for (int j = i; j < i + AffinityScope; j++)
254
                {
255
                    bits[j] = 1;
256
                }
257
258
                var affinity = System.Convert.ToInt64(string.Join("", bits), 2);
259
260
                ProcessorAffinityList.Add(affinity);
261
            }
262
        }
263
264
        public bool StartService()
265
        {
266
          
267 2bbea412 taeseongkim
            /// 서비스 설정 로드
268 53c9637d taeseongkim
            try
269
            {
270
                this.GetApplicationConfig();
271
                logger.Info("Read Config");
272
273 60723dc9 taeseongkim
                if (ServiceProperty != null)
274
                {
275
                    ProcessorAffinityInit();
276
                }
277
                else
278
                {
279
                    throw new Exception("StartService Error. ServiceProperty is Null");
280
                }
281 53c9637d taeseongkim
282
            }
283
            catch (Exception e)
284
            {
285 60723dc9 taeseongkim
                throw new Exception("StartService Error. ", e);
286 53c9637d taeseongkim
            }
287 60723dc9 taeseongkim
288 2bbea412 taeseongkim
            /// pThread.dll을 리소스에서 Service 실행 디렉토리로 복사.
289 53c9637d taeseongkim
            try
290
            {
291 a53dfe45 taeseongkim
                // MarkusPDF.dll에서 pThread lib 사용을 위해 Insatll
292 53c9637d taeseongkim
                if (!File.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "libpthread.dll")))
293
                {
294
                    Markus.Library.Installer.Install();
295
                    logger.Info("Markus.Library.Installer Install");
296
                }
297
                else
298
                {
299
                    logger.Info("Markus.Library.Installer Exists.");
300
                }
301
                
302
            }
303
            catch (Exception e)
304
            {
305
                throw new Exception("Stop Installer Error. ", e);
306
            }
307
308 2bbea412 taeseongkim
            /// 컨버터 프로세스가 실행중인 경우 모두 중지 시킨다.
309 53c9637d taeseongkim
            try
310
            {
311 a53dfe45 taeseongkim
                // 기존에 실행 중이던 프로세스 종료
312 53c9637d taeseongkim
                Stopprocess();
313
                logger.Info("Stopprocess");
314
            }
315
            catch (Exception e)
316
            {
317
                throw new Exception("Stop Process Error. ", e);
318
            }
319
320 2bbea412 taeseongkim
            /// wcf 서비스 실행
321 53c9637d taeseongkim
            try
322
            {
323 a53dfe45 taeseongkim
                // WCF 실행
324 53c9637d taeseongkim
                StartWcfService();
325
326
                if (gWcfServiceHost.BaseAddresses?.Count() > 0)
327
                {
328
                    gServiceHostAddress = gWcfServiceHost.BaseAddresses.First();
329
                }
330
331 0157b158 taeseongkim
                //  각 서비스에 컨버터 아이템을 보내기 위한 서비스 초기화
332 06f13e11 taeseongkim
                if (IsStation)
333 0157b158 taeseongkim
                {
334
                    SetServiceList(this.StationServiceIDList);
335
                }
336
337 53c9637d taeseongkim
                logger.Info($"StartWcfService {gServiceHostAddress}");
338
            }
339
            catch (Exception e)
340
            {
341
                throw new Exception("start Wcf Service Error. ", e);
342
            }
343
344 0157b158 taeseongkim
            //try
345
            //{
346
            //    // Status가 4이하인 Convert Item을 다시 Convert 함. 
347
            //    setDataBaseWaitingList();
348
            //    logger.Info("setDataBaseWaitingList");
349
            //}
350
            //catch (Exception e)
351
            //{
352
            //    throw new Exception("Database Waiting List Error . ", e);
353
            //}
354 53c9637d taeseongkim
355
356
            logger.Info("Start ServiceStation");
357 60723dc9 taeseongkim
            var autoEvent = new System.Threading.AutoResetEvent(false);
358
359 1ae729e4 taeseongkim
            stateTimer = new System.Threading.Timer(new System.Threading.TimerCallback(TimerCallBack), null, 0, 500);
360 60723dc9 taeseongkim
            //timer = new System.Timers.Timer(new TimeSpan(0, 0, 0, 10).TotalMilliseconds);
361
            //timer.Elapsed += Timer_Elapsed;
362
            //timer.AutoReset = true;
363
            //timer.Start();
364
            //Timer_Elapsed(null, null);
365 53c9637d taeseongkim
            return true;
366
        }
367
368 60723dc9 taeseongkim
        System.Threading.Timer stateTimer;
369
        DateTime logTime;
370 1ae729e4 taeseongkim
        DateTime ReleaseTime;
371 60723dc9 taeseongkim
372
        private void TimerCallBack(object state)
373
        {
374
            System.Threading.AutoResetEvent autoEvent = (System.Threading.AutoResetEvent)state;
375
            //stateTimer.Change(-1, -1);
376
            try
377
            {
378 1ae729e4 taeseongkim
               
379
                if ((DateTime.Now - ReleaseTime) >= new TimeSpan(0, 0,15))
380 60723dc9 taeseongkim
                {
381 1ae729e4 taeseongkim
                    if (!IsReleaseItems)
382
                    {
383
                        ReleaseItems();
384
                    }
385
                    ReleaseTime = DateTime.Now;
386 60723dc9 taeseongkim
                }
387 1ae729e4 taeseongkim
              
388 60723dc9 taeseongkim
389 150747cb taeseongkim
                if ((DateTime.Now - logTime) >= new TimeSpan(0, 5,0))
390 60723dc9 taeseongkim
                {
391
                    logTime = DateTime.Now;
392
                    logger.Info("StationService Alive Check");
393
                }
394
395 1ae729e4 taeseongkim
396 60723dc9 taeseongkim
            }
397
            catch (Exception ex)
398
            {
399
                logger.Error("Timer Error ", ex);
400
            }
401 1ae729e4 taeseongkim
402
            ///System.Threading.Thread.SpinWait(100000);
403
            //stateTimer.Change(0, 10000);
404 60723dc9 taeseongkim
        }
405
406 0157b158 taeseongkim
        public void SetServiceList(List<string> serviceList)
407
        {
408
            StationServiceList = new List<SubStationServiceItem>();
409
410
            using (DataBase.ConvertDatabase database = new DataBase.ConvertDatabase(MarkusDBConnectionString))
411
            {
412
                foreach (var item in serviceList)
413
                {
414
                    try
415
                    {
416
                        var prop = database.GetServiceProperties(item);
417
418
                        if (prop != null)
419
                        {
420 1ae729e4 taeseongkim
                            BasicHttpBinding httpbinding = new BasicHttpBinding();
421
                            httpbinding.CloseTimeout = new TimeSpan(0, 10, 0);
422
                            httpbinding.ReceiveTimeout = new TimeSpan(0, 10, 0);
423
                            httpbinding.SendTimeout = new TimeSpan(0, 10, 0);
424
                            httpbinding.OpenTimeout = new TimeSpan(0, 10, 0);
425
426 0157b158 taeseongkim
                            EndpointAddress myEndpoint = new EndpointAddress(UriHelper.UriCreate(prop.SERVICE_ADDRESS));
427 1ae729e4 taeseongkim
                            var StationServiceClient = new WcfClient.StationServiceTask.StationServiceClient(httpbinding, myEndpoint);
428 0157b158 taeseongkim
                        
429
                       
430
                                //var items = StationServiceClient.AliveConvertList();
431
                            
432
                                StationServiceList.Add(new SubStationServiceItem
433
                                {
434
                                    Properties = prop,
435
                                    Service = StationServiceClient
436
                                });
437
                        }
438
439
                    }
440
                    catch (Exception ex)
441
                    {
442 06f13e11 taeseongkim
                        logger.Error($"Service Properties Error  ID : { item }",ex);
443 0157b158 taeseongkim
                    }
444
                }
445
            }
446
        }
447 53c9637d taeseongkim
448
        protected override void OnStop()
449
        {
450
            try
451
            {
452 1ae729e4 taeseongkim
                if (timer != null)
453
                {
454
                    timer.Stop();
455
                }
456
457 53c9637d taeseongkim
                StopWcfService();
458
                Stopprocess();
459
460
                logger.Info("ServiceStation Stop");
461
            }
462
            catch (Exception e)
463
            {
464
                logger.Error("OnStop Error . ", e);
465
            }
466
        }
467
468
        #region Sleep 방지
469
        //[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
470
        //static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);
471
        //[FlagsAttribute]
472
        //public enum EXECUTION_STATE : uint
473
        //{
474
        //    ES_AWAYMODE_REQUIRED = 0x00000040,
475
        //    ES_CONTINUOUS = 0x80000000,
476
        //    ES_DISPLAY_REQUIRED = 0x00000002,
477
        //    ES_SYSTEM_REQUIRED = 0x00000001
478
        //    // Legacy flag, should not be used.
479
        //    // ES_USER_PRESENT = 0x00000004
480
        //}
481
        //public static void PreventScreenAndSleep()
482
        //{
483
        //    SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS |
484
        //                            EXECUTION_STATE.ES_SYSTEM_REQUIRED |
485
        //                            EXECUTION_STATE.ES_AWAYMODE_REQUIRED |
486
        //                            EXECUTION_STATE.ES_DISPLAY_REQUIRED);
487
        //} 
488
        #endregion
489
    }
490
}
클립보드 이미지 추가 (최대 크기: 500 MB)