프로젝트

일반

사용자정보

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

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

이력 | 보기 | 이력해설 | 다운로드 (14.8 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
            try
175
            {
176
                if (!IsReleaseItems)
177
                {
178
                    ReleaseItems();
179
                }
180

    
181
                logger.Info("StationService Info");
182
            }
183
            catch (Exception ex)
184
            {
185
                logger.Error("Timer Error " ,ex);
186
            }
187
            System.Threading.Thread.SpinWait(10000);
188

    
189
            timer.Start();
190
        }
191

    
192
        /// <summary>
193
        /// alivequeue와 process를 비교하여 정리하고
194
        /// 대기중인 아이템을 분배한다.
195
        /// </summary>
196
        private void ReleaseItems()
197
        {
198
            try
199
            {
200
                IsReleaseItems = true;
201

    
202
                CleanUpAliveQueueItems();
203

    
204
                if (IsStation)
205
                {
206
                    System.Diagnostics.Debug.WriteLine("ReflashSubService");
207
                    ReflashSubService();
208
                    System.Diagnostics.Debug.WriteLine("ReflashSubService");
209

    
210
                    System.Diagnostics.Debug.WriteLine("CleanUpDataBaseItems");
211
                    CleanUpDataBaseItems();
212
                    System.Diagnostics.Debug.WriteLine("setDataBaseWaitingList");
213
                    setDataBaseWaitingList();
214
                    System.Diagnostics.Debug.WriteLine("ReleaseItems end");
215
                }
216
            }
217
            catch (Exception ex)
218
            {
219
                logger.Error("get Wating Item error", ex);
220
            }
221

    
222
            IsReleaseItems = false;
223
        }
224

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

    
239
            int processCount = Environment.ProcessorCount;
240
            int AffinityScope = 1;
241

    
242
            if (processCount > MultiProcessCount)
243
            {
244
                AffinityScope = processCount / MultiProcessCount;
245
            }
246

    
247
            for (int i = 0; i < processCount - AffinityScope; i += AffinityScope)
248
            {
249
                var bits = new int[processCount];
250

    
251
                for (int j = i; j < i + AffinityScope; j++)
252
                {
253
                    bits[j] = 1;
254
                }
255

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

    
258
                ProcessorAffinityList.Add(affinity);
259
            }
260
        }
261

    
262
        public bool StartService()
263
        {
264
          
265
            try
266
            {
267
                this.GetApplicationConfig();
268
                logger.Info("Read Config");
269

    
270
                ProcessorAffinityInit();
271

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

    
296
            try
297
            {
298
                // 기존에 실행 중이던 프로세스 종료
299
                Stopprocess();
300
                logger.Info("Stopprocess");
301
            }
302
            catch (Exception e)
303
            {
304
                throw new Exception("Stop Process Error. ", e);
305
            }
306

    
307
            try
308
            {
309
                // WCF 실행
310
                StartWcfService();
311

    
312
                if (gWcfServiceHost.BaseAddresses?.Count() > 0)
313
                {
314
                    gServiceHostAddress = gWcfServiceHost.BaseAddresses.First();
315
                }
316

    
317
                //  각 서비스에 컨버터 아이템을 보내기 위한 서비스 초기화
318
                if (IsStation)
319
                {
320
                    SetServiceList(this.StationServiceIDList);
321
                }
322

    
323
                logger.Info($"StartWcfService {gServiceHostAddress}");
324
            }
325
            catch (Exception e)
326
            {
327
                throw new Exception("start Wcf Service Error. ", e);
328
            }
329

    
330
            //try
331
            //{
332
            //    // Status가 4이하인 Convert Item을 다시 Convert 함. 
333
            //    setDataBaseWaitingList();
334
            //    logger.Info("setDataBaseWaitingList");
335
            //}
336
            //catch (Exception e)
337
            //{
338
            //    throw new Exception("Database Waiting List Error . ", e);
339
            //}
340

    
341

    
342
            logger.Info("Start ServiceStation");
343

    
344
            timer = new System.Timers.Timer(1000);// new TimeSpan(0,0,0,10).TotalMilliseconds);
345
            timer.Elapsed += Timer_Elapsed;
346
            timer.AutoReset = true;
347
            timer.Start();
348

    
349
            return true;
350
        }
351

    
352
        public void SetServiceList(List<string> serviceList)
353
        {
354
            StationServiceList = new List<SubStationServiceItem>();
355

    
356
            using (DataBase.ConvertDatabase database = new DataBase.ConvertDatabase(MarkusDBConnectionString))
357
            {
358
                foreach (var item in serviceList)
359
                {
360
                    try
361
                    {
362
                        var prop = database.GetServiceProperties(item);
363

    
364
                        if (prop != null)
365
                        {
366
                            BasicHttpBinding myBinding = new BasicHttpBinding();
367
                            EndpointAddress myEndpoint = new EndpointAddress(UriHelper.UriCreate(prop.SERVICE_ADDRESS));
368
                            var StationServiceClient = new WcfClient.StationServiceAsync.StationServiceClient(myBinding, myEndpoint);
369
                        
370
                       
371
                                //var items = StationServiceClient.AliveConvertList();
372
                            
373
                                StationServiceList.Add(new SubStationServiceItem
374
                                {
375
                                    Properties = prop,
376
                                    Service = StationServiceClient
377
                                });
378
                        }
379

    
380
                    }
381
                    catch (Exception ex)
382
                    {
383
                        logger.Error($"Service Properties Error  ID : { item }",ex);
384
                    }
385
                }
386
            }
387
        }
388

    
389
        protected override void OnStop()
390
        {
391
            try
392
            {
393
                timer.Stop();
394
                StopWcfService();
395
                Stopprocess();
396

    
397
                logger.Info("ServiceStation Stop");
398
            }
399
            catch (Exception e)
400
            {
401
                logger.Error("OnStop Error . ", e);
402
            }
403
        }
404

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