프로젝트

일반

사용자정보

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

markus / ConvertService / ServiceBase / Markus.Service.Station / StationService / ServiceStationTask.cs @ 1d79913e

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

1
using Markus.Service.Interface;
2
using Markus.Message;
3
using System;
4
using System.Collections.Generic;
5
using System.Diagnostics;
6
using System.Linq;
7
using System.Text;
8
using System.Threading;
9
using System.Threading.Tasks;
10
using System.Management;
11
using static Markus.Service.Extensions.Encrypt;
12
using Markus.Service.Extensions;
13
using Markus.Service.Helper;
14

    
15
namespace Markus.Service
16
{
17
    /// <summary>
18
    /// 컨버터 큐 처리 
19
    /// </summary>
20
    public partial class ServiceStation
21
    {
22
        /// <summary>
23
        /// 컨버터 실행중인 item
24
        /// </summary>
25
        private static List<ConvertItem> AliveConvertQueue = new List<ConvertItem>();
26

    
27
        /// <summary>
28
        /// 컨버터 프로세스 실행
29
        /// </summary>
30
        /// <param name="convertitem"></param>
31
        public bool ConvertProcessStart(ConvertItem convertitem)
32
        {
33
            bool result = false;
34
            try
35
            {
36
           
37
                Process ConvertProcess = new Process();
38

    
39
                ProcessContext processSendData = new ProcessContext
40
                {
41
                    ConvertID = convertitem.ConvertID,
42
                    ConnectionString = MarkusDBConnectionString,
43
                    ServiceStationUri = gServiceHostAddress.ToString(),
44
                    OriginFilePath = convertitem.OriginfilePath,
45
                    SaveDirectory = convertitem.ConvertPath,
46
                    TempDirectory = DownloadTempFolder,
47
                    ReleaseWorkMemory = ReleaseWorkMemory,
48
                    MultiThreadMaxPages = MultiThreadMaxPages,
49
                    MinFontSize = MinFontSize,
50
                    SendStatusInterval = SaveStatusInterval,
51
                    UseResolution = UseResolution,
52
                    FontsFolder = FontsFolder
53
                };
54

    
55
                var sendData = ObjectToBytesStringConvert.ObjectToBytesString(processSendData);
56
                var convertPath = System.IO.Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "Convert\\Markus.Service.ConvertProcess.exe");
57

    
58
                ProcessStartInfo startInfo = new ProcessStartInfo
59
                {
60
                    UseShellExecute = false,
61
                    FileName = convertPath,
62
                    WindowStyle = ProcessWindowStyle.Hidden,
63
                    CreateNoWindow = true,
64
                    ErrorDialog = false,
65
                    RedirectStandardError = false,
66
                    Arguments = $"{convertitem.ConvertID.ToString()} {AESEncrypter.Encrypt(sendData)}"
67
                    //Arguments = $"{convertitem.ConvertID.ToString()} {convertitem.ProjectNumber} {AESEncrypter.Encrypt(MarkusDBConnectionString)} {gServiceHostAddress} {DownloadTempFolder} {MultiThreadMaxPages}"
68
                };
69

    
70
                ConvertProcess.StartInfo = startInfo;
71
                ConvertProcess.EnableRaisingEvents = true;
72
                
73
                System.Diagnostics.Debug.WriteLine("convert process run : " + startInfo.Arguments);
74

    
75
                logger.Info($"convert process run : UniqueKey:{convertitem.UniqueKey}   ConvertID:{convertitem.ConvertID}" + startInfo.Arguments);
76

    
77
                if (ConvertProcess.Start())
78
                {
79
                    try
80
                    {
81
                        var processAffinity = ProcessorAffinityList.Except(AliveConvertQueue.Select(f => (long)f.ProcessorAffinity));
82

    
83
                        long currentAffinity = 0;
84

    
85
                        if (processAffinity.Count() > 0)
86
                        {
87
                            currentAffinity = processAffinity.First();
88

    
89
                            //int bitMask = 1 << (convertitem.ProcessorAffinity - 1);
90
                            //bitMask |= 1 << (anotherUserSelection - 1); / //  프로세스 두개 이상 선택
91

    
92
                            ConvertProcess.ProcessorAffinity = new IntPtr(currentAffinity);
93
                            logger.Info($"convert process currentAffinity set {currentAffinity} : UniqueKey:{convertitem.UniqueKey}   ConvertID:{convertitem.ConvertID}");
94

    
95
                        }
96
                        else
97
                        {
98
                            // 모두 사용중일때 점유율이 작은 걸로 사용
99
                            var CurrentProcessAffinity = AliveConvertQueue.Where(x=>x.ProcessorAffinity > 0).Select(f => f.ProcessorAffinity).Distinct();
100

    
101
                            currentAffinity = CurrentProcessAffinity.Min();
102
                            ConvertProcess.ProcessorAffinity = new IntPtr(currentAffinity);
103

    
104
                            logger.Info($"convert process Affinity All use {currentAffinity} : UniqueKey:{convertitem.UniqueKey}   ConvertID:{convertitem.ConvertID}");
105

    
106
                        }
107

    
108
                        var item = AliveConvertQueue.Find(x => x.Equals(convertitem));
109

    
110
                        if (item != null)
111
                        {
112
                            item.ProcessorAffinity = currentAffinity;
113
                        }
114
                    }
115
                    catch (Exception ex)
116
                    {
117
                        AliveConvertQueue.Remove(convertitem);
118
                        logger.Error("ConvertProcessStart error", ex);
119
                    }
120

    
121
                    logger.Info($"convert process run true UniqueKey:{convertitem.UniqueKey}   ConvertID:{convertitem.ConvertID}");
122
                    result = true;
123
                }
124
            }
125
            catch (Exception ex)
126
            {
127
                AliveConvertQueue.Remove(convertitem);
128
                throw new Exception("ConvertThread " + $"{convertitem.ConvertID.ToString()} {convertitem.ProjectNumber} {AESEncrypter.Encrypt(MarkusDBConnectionString)} {gServiceHostAddress} {DownloadTempFolder} {MultiThreadMaxPages}", ex.InnerException);
129
            }
130
            finally
131
            {
132
                //GC.WaitForPendingFinalizers();
133
                //GC.Collect(2);
134
                //GC.Collect(2);
135
            }
136

    
137
            return result;
138
        }
139
    
140
        /// <summary>
141
        /// DB에 있는 대기중인 Item을 가져온다.
142
        /// </summary>
143
        public void setDataBaseWaitingList()
144
        {
145
            List<EntityModel.CONVERTER_DOC> convertItems = new List<EntityModel.CONVERTER_DOC>();
146

    
147
            using (DataBase.ConvertDatabase database = new DataBase.ConvertDatabase(MarkusDBConnectionString))
148
            {
149
                convertItems = database.GetWaitConvertItems(this.RunProjectList, StationServiceList.Where(x=>x.IsOnline).Sum(f=>f.Properties.PROCESS_COUNT)).ToList();
150
            }
151

    
152
            foreach (var convert in convertItems)
153
            {
154
                //ReflashSubService();
155

    
156
                if (AliveConvertQueue.Count(x => x.ConvertID == convert.ID) == 0)
157
                {
158
                    if (convert.STATUS > (int)StatusCodeType.None)
159
                    {
160
                        using (DataBase.ConvertDatabase database = new DataBase.ConvertDatabase(MarkusDBConnectionString))
161
                        {
162
                            database.SetCleanUpItem(convert.ID, 1);
163
                        }
164
                    }
165

    
166
                    PassConvertItem(convert.PROJECT_NO, convert.ID, convert.DOCUMENT_ID);
167
                    
168
                    //System.Threading.Thread.Sleep(1000);
169
                }
170
            }
171
          
172
        }
173

    
174
        public bool IsDataBaseWaitingList(int overListCount)
175
        {
176
            bool result = false;
177

    
178
            try
179
            {
180
                using (DataBase.ConvertDatabase database = new DataBase.ConvertDatabase(MarkusDBConnectionString))
181
                {
182
                    var convertItems = database.GetWaitConvertItems(this.RunProjectList, overListCount);
183

    
184
                    if (convertItems.Count() > 0)
185
                    {
186
                        result = true;
187
                    }
188
                }
189
            }
190
            catch (Exception ex)
191
            {
192
                logger.Error($"IsDataBaseWaitingList Error",ex);
193
            }
194

    
195
            return result;
196
        }
197

    
198
        private async Task<bool> ReflashSubServiceAsync()
199
        {
200
            bool result = false;
201

    
202
            try
203
            {
204
                foreach (var subservice in StationServiceList)
205
                {
206
                    try
207
                    {
208
                        subservice.IsOnline = await SytemNet.PingAsync(subservice.Properties.SERVICE_ADDRESS);
209

    
210
                        if (subservice.IsOnline)
211
                        {
212
                            var alivelist = await subservice.Service.AliveConvertListAsync();
213

    
214
                            subservice.ConvertItems = alivelist.ToList();
215
                            subservice.AliveCount = alivelist.Count();
216
                        }
217
                        else
218
                        {
219
                            logger.Error($"Connection Error {subservice.Properties.SERVICE_ADDRESS}");
220
                            subservice.ConvertItems = new List<WcfClient.StationServiceTask.ConvertItem>();
221
                            subservice.AliveCount = subservice.Properties.PROCESS_COUNT;
222
                        }
223

    
224
                        result = true;
225
                    }
226
                    catch (Exception ex)
227
                    {
228
                        logger.Error($"ReflashSubService error - Service ID : {subservice.Properties.ID} ", ex);
229
                    }
230
                }
231
            }
232
            catch (Exception ex)
233
            {
234
                logger.Error($"ReflashSubService error", ex);
235
            }
236

    
237
            return result;
238
        }
239

    
240

    
241
        /// <summary>
242
        /// 
243
        /// </summary>
244
        /// <param name="ProjectNo"></param>
245
        /// <param name="ConvertID"></param>
246
        /// <param name="UniqueKey">Document ID(문서의 유일키)</param>
247
        private async void PassConvertItem(string ProjectNo,string ConvertID,string UniqueKey,bool isSubStation = false)
248
        {
249
            try
250
            {
251
                IEnumerable<SubStationServiceItem> stationList = null;
252

    
253
                //if (!isSubStation)
254
                //{
255
                    stationList = StationServiceList.Where(x => x.IsOnline);
256
                //}
257
                //else
258
                //{
259
                //    stationList = StationServiceList.Where(x => x.Properties.ID != this.ServiceID && x.IsOnline);
260
                //}
261

    
262
                if (stationList.SelectMany(x => x.ConvertItems).Count(c => c.ProjectNumber == ProjectNo && c.UniqueKey == UniqueKey) == 0)
263
                {
264
                    var station = stationList.OrderByDescending(x => x.Properties.PROCESS_COUNT - x.AliveCount).FirstOrDefault();
265

    
266
                    if (station != null)
267
                    {
268
                        if (station.Properties.PROCESS_COUNT - station.AliveCount > 0)
269
                        {
270
                            System.Diagnostics.Debug.WriteLine($"{station.Properties.SERVICE_ADDRESS}  {station.Properties.PROCESS_COUNT}/{station.AliveCount}");
271
                            var result = await station.Service.PassConvertAsync(ProjectNo, ConvertID);
272

    
273
                            if (!result.IsNullOrEmpty())
274
                            {
275
                                if (result.ToLower() == true.ToString().ToLower())
276
                                {
277
                                    Console.WriteLine($"PassConvertItem - Service ID : {station.Properties.ID} ConvertID : {ConvertID}");
278
                                    logger.Info($"PassConvertItem - Service ID : {station.Properties.ID} ConvertID : {ConvertID}");
279

    
280
                                    station.AliveCount++;
281
                                }
282
                                else
283
                                {
284
                                        logger.Error($"PassConvertItem Error result : {result} - Service ID : {station.Properties.ID} ConvertID : {ConvertID}");
285
                                }
286
                            }
287
                            else
288
                            {
289
                                logger.Error($"PassConvertItem result: Nulll; - Service ID : {station.Properties.ID} ConvertID : {ConvertID}");
290
                                System.Diagnostics.Debug.WriteLine("result : Nulll;");
291
                            }
292
                        }
293
                    }
294
                }
295
            }
296
            catch (Exception ex)
297
            {
298
                logger.Error($"setDataBaseWaitingList", ex);
299
            }
300
        }
301

    
302
        /// <summary>
303
        /// 컨버터 프로세스와 AiliveItems을 비교하여 AliveItems에 없는 경우 AliveItems을 제거
304
        /// </summary>
305
        private void CleanUpAliveQueueItems()
306
        {
307
            if (AliveConvertQueue.Count() > 0)
308
            {
309
                var processList = Process.GetProcessesByName("Markus.Service.ConvertProcess");
310

    
311
                if (processList.Length == 0)
312
                {
313
                    AliveConvertQueue.Clear();
314
                    System.Diagnostics.Debug.WriteLine("AliveConvertQueue.Clear()");
315
                }
316
                else
317
                {
318
                    var argumentList = processList.Select(f => f.Arguments().CommandLine).SelectMany(f => f).ToList();
319

    
320
                    List<ConvertItem> convertItems = AliveConvertQueue;
321

    
322
                    try
323
                    {
324
                        if (convertItems.Count() > 0 && argumentList.Count() > 0)
325
                        {
326
                            for (int i = convertItems.Count - 1; i >= 0; --i)
327
                            {
328
                                if (argumentList.Count(x => x == convertItems[i].ConvertID) == 0)
329
                                {
330
                                    System.Diagnostics.Debug.WriteLine($"AliveConvertQueue remove {convertItems[i].ConvertID}");
331
                                    logger.Warn($"AliveConvertQueue remove {convertItems[i].ConvertID}");
332
                                    AliveConvertQueue.Remove(convertItems[i]);
333

    
334
                                }
335
                            }
336
                        }
337
                    }
338
                    catch (Exception ex)
339
                    {
340
                        logger.Error("CleanUpAliveQueueItems error",ex);
341
                    }
342
                }
343
            }
344
        }
345

    
346
        /// <summary>
347
        /// AliveConvertQueue와 db를 비교하여 AliveConvertQueue에 없는 데이터를 초기화 하여 다시 컨버팅
348
        /// </summary>
349
        private async void CleanUpDataBaseItems()
350
        {
351
            try
352
            {
353
                using (DataBase.ConvertDatabase database = new DataBase.ConvertDatabase(MarkusDBConnectionString))
354
                {
355
                    var items = database.GetConvertingItems(RunProjectList);
356

    
357
                    List< WcfClient.StationServiceTask.ConvertItem> aliveItems = new List<WcfClient.StationServiceTask.ConvertItem>();
358

    
359
                    foreach (var item in StationServiceList.Where(x => x.IsOnline))
360
                    {
361
                        var serviceItems = await item.Service.AliveConvertListAsync();
362
                        aliveItems.AddRange(serviceItems);
363
                    }
364

    
365
                    if (aliveItems.Count() > 0)
366
                    {
367
                        logger.Warn($"aliveItems  : {string.Join(",",aliveItems.Select(x=>x.ConvertID))}");
368

    
369
                        foreach (var item in items)
370
                        {
371
                            if (aliveItems.Count(x => x.ConvertID == item.ID) == 0)
372
                            {
373
                                Console.WriteLine($"SetCleanUpItem  : {item.ID}");
374
                                logger.Warn($"SetCleanUpItem  : {item.ID}");
375
                                database.SetCleanUpItem(item.ID, 0);
376
                            }
377
                        }
378
                    }
379
             
380
                }
381
            }
382
            catch (Exception ex)
383
            {
384
                throw new Exception("CleanUpDataBaseItems Error ", ex);
385
            }
386
        }
387

    
388
        public void Stopprocess()
389
        {
390
            var process = Process.GetProcessesByName("Markus.Service.ConvertProcess");
391

    
392
            for (int i = process.Count() - 1; i >= 0 ; i--)
393
            {
394
                try
395
                {
396
                    Console.WriteLine($"{i} Process Kill");
397
                    process[i].Kill();
398
                }
399
                catch (Exception ex)
400
                {
401
                    System.Diagnostics.Debug.WriteLine(ex.ToString());
402
                }
403
            }
404
        }
405

    
406
        /// <summary>
407
        /// finish가 호출되고 살아있는 프로세스라고 추정됨
408
        /// </summary>
409
        public void DeadLockProcessKill()
410
        {
411
            var process = Process.GetProcessesByName("Markus.Service.ConvertProcess");
412

    
413
            for (int i = process.Count() - 1; i >= 0; i--)
414
            {
415
                try
416
                {
417
                    var commandLines = process[i].Arguments().CommandLine;
418

    
419
                    if (commandLines.Count() > 0)
420
                    {
421
                        if (ServiceStation.AliveConvertQueue.Count(f => f.ConvertID == commandLines[0]) == 0)
422
                        {
423
                            process[i].Kill();
424
                        }
425
                    }
426
                }
427
                catch (Exception ex)
428
                {
429
                    System.Diagnostics.Debug.WriteLine(ex.ToString());
430
                }
431
            }
432
        }
433

    
434
        private async void ConvertFinish(ConvertItem convertitem)
435
        {
436
            try
437
            {
438
                System.Diagnostics.Debug.WriteLine("Convert Finish : " + convertitem.ConvertID);
439

    
440
                System.Diagnostics.Debug.WriteLine("ServiceStation.AliveConvertQueue.Count() : " + ServiceStation.AliveConvertQueue.Count());
441

    
442
                List<string> deleteItems = new List<string> { convertitem.ConvertID };
443

    
444

    
445
                ServiceStation.AliveConvertQueue.RemoveAll(x=>deleteItems.Any(y=>y == x.ConvertID));
446

    
447
                System.Diagnostics.Debug.WriteLine("ServiceStation.AliveConvertQueue.Count() : " + ServiceStation.AliveConvertQueue.Count());
448

    
449
                if (IsStation)
450
                {
451
                    if (!IsReleaseItems)
452
                    {
453
                        System.Diagnostics.Debug.WriteLine("ConvertFinish ReleaseItems call");
454
                        ReleaseItems();
455
                    }
456
                }
457
                else
458
                {
459
                    if (StationClient != null)
460
                    {
461
                       await  StationClient.ReleaseConvertItemsAsync();
462
                    }
463
                }
464
                //if (ServiceStation.AliveConvertQueue.Count() < MultiProcessCount)
465
                //{
466
                //    setDataBaseWaitingList();
467
                //}
468
            }
469
            catch (Exception ex)
470
            {
471
                logger.Error("ConvertFinish Error",ex);
472
            }
473
        }
474
    }
475
}
클립보드 이미지 추가 (최대 크기: 500 MB)