프로젝트

일반

사용자정보

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

markus / ConvertService / ServiceBase / Markus.Service.Station / ServiceStation.cs @ 06f13e11

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

1
using log4net;
2
using Markus.Service.Extensions;
3
using Markus.Service.Helper;
4
using Markus.Service.IWcfService;
5
using Markus.Service.WcfService;
6
using Salaros.Configuration;
7
using System;
8
using System.Collections.Generic;
9
using System.ComponentModel;
10
using System.Data;
11
using System.Diagnostics;
12
using System.Globalization;
13
using System.IO;
14
using System.Linq;
15
using System.Runtime.InteropServices;
16
using System.ServiceModel;
17
using System.ServiceProcess;
18
using System.Text;
19
using System.Threading.Tasks;
20
using System.Timers;
21
using static Markus.Service.Extensions.Encrypt;
22

    
23
namespace Markus.Service
24
{
25
    public partial class ServiceStation : ServiceBase
26
    {
27
        protected ILog logger = LogManager.GetLogger(typeof(ServiceStation));
28
        protected ServiceHost gWcfServiceHost;
29

    
30
        System.Timers.Timer timer;
31
        
32
        private int MultiProcessCount = 1;
33
        private string ServiceID;
34
        private List<SubStationServiceItem> StationServiceList;
35
        private List<string> StationServiceIDList;
36
        private Service.WcfClient.StationServiceAsync.StationServiceClient StationClient;
37
        private bool IsStation;
38

    
39
        private Uri gServiceHostAddress;
40

    
41
        private string MarkusDBConnectionString;
42
        private string DownloadTempFolder;
43
        private int MultiThreadMaxPages;
44
        private int MinFontSize;
45
        private int UseResolution;
46
        private bool CreateProcessWindow;
47
        private long ReleaseWorkMemory;
48

    
49
        private int SaveStatusInterval;
50

    
51
        private static bool IsReleaseItems;
52

    
53
        private List<string> RunProjectList = new List<string>();
54

    
55
        /// <summary>
56
        /// 프로세스 카운터 자주 람다식을 사용해서 list<int>로 함.
57
        /// </summary>
58
        private List<Int64> ProcessorAffinityList;
59

    
60
        private string configFileName;
61

    
62
        public ServiceStation()
63
        {
64
            InitializeComponent();
65
        }
66

    
67
        /// <summary>
68
        /// Config 파일 
69
        /// </summary>
70
        public void GetApplicationConfig()
71
        {
72
            try
73
            {
74
                ConfigParser config = null;
75

    
76
                try
77
                {
78
                    configFileName = $"{typeof(ServiceStation).Name}.ini";
79
                    config = ConfigHelper.AppConfig(this.configFileName);
80
                }
81
                catch (Exception)
82
                {
83
                    throw new Exception("Config Read Error.");
84
                }
85

    
86
                if (config != null)
87
                {
88
                    // CONVERT DATABASE 연결 문자열
89
                    MarkusDBConnectionString = AESEncrypter.Decrypt(config.GetValue(CONFIG_DEFINE.SERVICE, CONFIG_DEFINE.MARKUS_CONNECTION_STRING));
90

    
91
                    IsStation = System.Convert.ToBoolean(config.GetValue(CONFIG_DEFINE.SERVICE, CONFIG_DEFINE.IS_STATAION, "false"));
92

    
93
                    ServiceID = config.GetValue(CONFIG_DEFINE.SERVICE, CONFIG_DEFINE.SERVICE_ID, Guid.Empty.ToString());
94

    
95
                    if (IsStation)
96
                    {
97
                        var servicetList = config.GetValue(CONFIG_DEFINE.SERVICE, CONFIG_DEFINE.SERVICE_LIST, "");
98

    
99
                        if (!servicetList.IsNullOrEmpty())
100
                        {
101
                            StationServiceIDList = servicetList.Split(',').ToList();
102
                        }
103
                    }
104
                    else
105
                    {
106
                        var address = config.GetValue(CONFIG_DEFINE.SERVICE, CONFIG_DEFINE.STATAION_ADDRESS,"");
107

    
108
                        if (!address.IsNullOrEmpty())
109
                        {
110
                            BasicHttpBinding myBinding = new BasicHttpBinding();
111
                            EndpointAddress myEndpoint = new EndpointAddress(UriHelper.UriCreate(address));
112
                            StationClient = new WcfClient.StationServiceAsync.StationServiceClient(myBinding, myEndpoint);
113
                        }
114
                    }
115
                    
116
                    MultiProcessCount = System.Convert.ToInt16(config.GetValue(CONFIG_DEFINE.SERVICE, CONFIG_DEFINE.CONVERT_SERVICE_PROCESS,"5"));
117

    
118
                    CreateProcessWindow = System.Convert.ToBoolean(config.GetValue(CONFIG_DEFINE.SERVICE, CONFIG_DEFINE.CREATE_WINDOW, "false"));
119

    
120
                    // PDF 임시 다운로드 폴더
121
                    DownloadTempFolder = config.GetValue(CONFIG_DEFINE.SERVICE, CONFIG_DEFINE.DOWNLOAD_TEMP_FOLDER,"C:\\temp");
122

    
123
                    MultiThreadMaxPages = System.Convert.ToInt16(config.GetValue(CONFIG_DEFINE.SERVICE, CONFIG_DEFINE.MULTI_TRHEAD_MAX_PAGE, "500"));
124

    
125
                    SaveStatusInterval = System.Convert.ToInt16(config.GetValue(CONFIG_DEFINE.SERVICE, CONFIG_DEFINE.SAVE_STATUS_INTERVAL, "5"));
126

    
127
                    MinFontSize = System.Convert.ToInt16(config.GetValue(CONFIG_DEFINE.SERVICE, CONFIG_DEFINE.MIN_FONT_SIZE, "10"));
128

    
129
                    UseResolution = System.Convert.ToInt16(config.GetValue(CONFIG_DEFINE.SERVICE, CONFIG_DEFINE.USE_RESOLUTION, "0"));
130

    
131
                    var workingMemory = System.Convert.ToDouble(config.GetValue(CONFIG_DEFINE.SERVICE, CONFIG_DEFINE.RELEASE_WORK_MEMORY, "1.5"));
132

    
133
                    ReleaseWorkMemory = MathBytes.Bytes(workingMemory, DataSizeType.GB);
134

    
135
                    var projectList = config.GetValue(CONFIG_DEFINE.SERVICE, CONFIG_DEFINE.FITER_PROCECT,"");
136

    
137
                    if(!projectList.IsNullOrEmpty())
138
                    {
139
                        RunProjectList = projectList.Split(',').ToList();
140
                    }
141

    
142
                    // 서비스 ENDPOINT
143
                    // http://localhost/
144
                    var endpointName = config.GetValue(CONFIG_DEFINE.WCF_ENDPOINT, CONFIG_DEFINE.STATION_SERVICE_NAME);
145
                    var port = config.GetValue(CONFIG_DEFINE.WCF_ENDPOINT, CONFIG_DEFINE.STATION_PORT);
146

    
147
                    if (!string.IsNullOrWhiteSpace(endpointName) && port.IsNumber())
148
                    {
149
                        gServiceHostAddress = UriHelper.UriCreate($"http://localhost:{port}/{endpointName}");
150
                    }
151
                }
152
            }
153
            catch (Exception ex)
154
            {
155
                throw new Exception("ApplicationConfig ", ex);
156
            }
157
        }
158

    
159
        protected override void OnStart(string[] args)
160
        {
161
            try
162
            {
163
                StartService();
164
            }
165
            catch (Exception ex)
166
            {
167
                logger.Error("ServiceStation Start Error - ", ex);
168
            }
169
        }
170

    
171
        private void Timer_Elapsed(object sender, ElapsedEventArgs e)
172
        {
173
            timer.Stop();
174

    
175
            if (!IsReleaseItems)
176
            {
177
                ReleaseItems();
178
            }
179

    
180
            System.Threading.Thread.SpinWait(10000);
181

    
182
            timer.Start();
183
        }
184

    
185
        /// <summary>
186
        /// alivequeue와 process를 비교하여 정리하고
187
        /// 대기중인 아이템을 분배한다.
188
        /// </summary>
189
        private void ReleaseItems()
190
        {
191
            try
192
            {
193
                IsReleaseItems = true;
194

    
195
                CleanUpAliveQueueItems();
196

    
197
                if (IsStation)
198
                {
199
                    System.Diagnostics.Debug.WriteLine("ReflashSubService");
200
                    ReflashSubService();
201
                    System.Diagnostics.Debug.WriteLine("ReflashSubService");
202

    
203
                    System.Diagnostics.Debug.WriteLine("CleanUpDataBaseItems");
204
                    CleanUpDataBaseItems();
205
                    System.Diagnostics.Debug.WriteLine("setDataBaseWaitingList");
206
                    setDataBaseWaitingList();
207
                    System.Diagnostics.Debug.WriteLine("ReleaseItems end");
208
                }
209
            }
210
            catch (Exception ex)
211
            {
212
                logger.Error("get Wating Item error", ex);
213
            }
214

    
215
            IsReleaseItems = false;
216
        }
217

    
218
        /// <summary>
219
        /// System.Diagnostics.Process의 ProcessorAffinity Core 선호도를 위한 초기화
220
        /// 설정된 MultiProcessCount에 대해서 프로세스의 코어의 선호도를 지정 한다.
221
        /// 코어의 선택은 비트로 이루어 진다.
222
        /// 8코어에서 1번 코어 00000001
223
        /// 8코어에서 1번 3번 코어 00000101
224
        /// 8코어에서 1번 3번 코어 00000101
225
        /// 8코어에서 1,2,3 선택   00000111
226
        /// https://dotnetgalactics.wordpress.com/2009/10/20/how-to-set-the-processor-affinity-programatically/
227
        /// </summary>
228
        private void ProcessorAffinityInit()
229
        {
230
            ProcessorAffinityList = new List<long>();
231

    
232
            int processCount = Environment.ProcessorCount;
233
            int AffinityScope = 1;
234

    
235
            if (processCount > MultiProcessCount)
236
            {
237
                AffinityScope = processCount / MultiProcessCount;
238
            }
239

    
240
            for (int i = 0; i < processCount - AffinityScope; i += AffinityScope)
241
            {
242
                var bits = new int[processCount];
243

    
244
                for (int j = i; j < i + AffinityScope; j++)
245
                {
246
                    bits[j] = 1;
247
                }
248

    
249
                var affinity = System.Convert.ToInt64(string.Join("", bits), 2);
250

    
251
                ProcessorAffinityList.Add(affinity);
252
            }
253
        }
254

    
255
        public bool StartService()
256
        {
257
          
258
            try
259
            {
260
                this.GetApplicationConfig();
261
                logger.Info("Read Config");
262

    
263
                ProcessorAffinityInit();
264

    
265
            }
266
            catch (Exception e)
267
            {
268
                throw new Exception("Stop StartService Error. ", e);
269
            }
270
            try
271
            {
272
                // MarkusPDF.dll에서 pThread lib 사용을 위해 Insatll
273
                if (!File.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "libpthread.dll")))
274
                {
275
                    Markus.Library.Installer.Install();
276
                    logger.Info("Markus.Library.Installer Install");
277
                }
278
                else
279
                {
280
                    logger.Info("Markus.Library.Installer Exists.");
281
                }
282
                
283
            }
284
            catch (Exception e)
285
            {
286
                throw new Exception("Stop Installer Error. ", e);
287
            }
288

    
289
            try
290
            {
291
                // 기존에 실행 중이던 프로세스 종료
292
                Stopprocess();
293
                logger.Info("Stopprocess");
294
            }
295
            catch (Exception e)
296
            {
297
                throw new Exception("Stop Process Error. ", e);
298
            }
299

    
300
            try
301
            {
302
                // WCF 실행
303
                StartWcfService();
304

    
305
                if (gWcfServiceHost.BaseAddresses?.Count() > 0)
306
                {
307
                    gServiceHostAddress = gWcfServiceHost.BaseAddresses.First();
308
                }
309

    
310
                //  각 서비스에 컨버터 아이템을 보내기 위한 서비스 초기화
311
                if (IsStation)
312
                {
313
                    SetServiceList(this.StationServiceIDList);
314
                }
315

    
316
                logger.Info($"StartWcfService {gServiceHostAddress}");
317
            }
318
            catch (Exception e)
319
            {
320
                throw new Exception("start Wcf Service Error. ", e);
321
            }
322

    
323
            //try
324
            //{
325
            //    // Status가 4이하인 Convert Item을 다시 Convert 함. 
326
            //    setDataBaseWaitingList();
327
            //    logger.Info("setDataBaseWaitingList");
328
            //}
329
            //catch (Exception e)
330
            //{
331
            //    throw new Exception("Database Waiting List Error . ", e);
332
            //}
333

    
334

    
335
            logger.Info("Start ServiceStation");
336

    
337
            timer = new System.Timers.Timer(1000);// new TimeSpan(0,0,0,10).TotalMilliseconds);
338
            timer.Elapsed += Timer_Elapsed;
339
            timer.AutoReset = true;
340
            timer.Start();
341

    
342
            return true;
343
        }
344

    
345
        public void SetServiceList(List<string> serviceList)
346
        {
347
            StationServiceList = new List<SubStationServiceItem>();
348

    
349
            using (DataBase.ConvertDatabase database = new DataBase.ConvertDatabase(MarkusDBConnectionString))
350
            {
351
                foreach (var item in serviceList)
352
                {
353
                    try
354
                    {
355
                        var prop = database.GetServiceProperties(item);
356

    
357
                        if (prop != null)
358
                        {
359
                            BasicHttpBinding myBinding = new BasicHttpBinding();
360
                            EndpointAddress myEndpoint = new EndpointAddress(UriHelper.UriCreate(prop.SERVICE_ADDRESS));
361
                            var StationServiceClient = new WcfClient.StationServiceAsync.StationServiceClient(myBinding, myEndpoint);
362
                        
363
                       
364
                                //var items = StationServiceClient.AliveConvertList();
365
                            
366
                                StationServiceList.Add(new SubStationServiceItem
367
                                {
368
                                    Properties = prop,
369
                                    Service = StationServiceClient
370
                                });
371
                        }
372

    
373
                    }
374
                    catch (Exception ex)
375
                    {
376
                        logger.Error($"Service Properties Error  ID : { item }",ex);
377
                    }
378
                }
379
            }
380
        }
381

    
382
        protected override void OnStop()
383
        {
384
            try
385
            {
386
                timer.Stop();
387
                StopWcfService();
388
                Stopprocess();
389

    
390
                logger.Info("ServiceStation Stop");
391
            }
392
            catch (Exception e)
393
            {
394
                logger.Error("OnStop Error . ", e);
395
            }
396
        }
397

    
398
        #region Sleep 방지
399
        //[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
400
        //static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);
401
        //[FlagsAttribute]
402
        //public enum EXECUTION_STATE : uint
403
        //{
404
        //    ES_AWAYMODE_REQUIRED = 0x00000040,
405
        //    ES_CONTINUOUS = 0x80000000,
406
        //    ES_DISPLAY_REQUIRED = 0x00000002,
407
        //    ES_SYSTEM_REQUIRED = 0x00000001
408
        //    // Legacy flag, should not be used.
409
        //    // ES_USER_PRESENT = 0x00000004
410
        //}
411
        //public static void PreventScreenAndSleep()
412
        //{
413
        //    SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS |
414
        //                            EXECUTION_STATE.ES_SYSTEM_REQUIRED |
415
        //                            EXECUTION_STATE.ES_AWAYMODE_REQUIRED |
416
        //                            EXECUTION_STATE.ES_DISPLAY_REQUIRED);
417
        //} 
418
        #endregion
419
    }
420
}
클립보드 이미지 추가 (최대 크기: 500 MB)