프로젝트

일반

사용자정보

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

markus / ConvertService / ServiceBase / Markus.Service.Station / StationService / ServiceStationTask.cs @ 43e1d368

이력 | 보기 | 이력해설 | 다운로드 (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

    
57
#if DEBUG
58
                var convertPath = System.IO.Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "Markus.Service.ConvertProcess.exe");
59
#else
60
                var convertPath = System.IO.Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "Convert\\Markus.Service.ConvertProcess.exe");
61
#endif
62
                ProcessStartInfo startInfo = new ProcessStartInfo
63
                {
64
                    UseShellExecute = false,
65
                    FileName = convertPath,
66
                    WindowStyle = ProcessWindowStyle.Hidden,
67
                    CreateNoWindow = true,
68
                    ErrorDialog = false,
69
                    RedirectStandardError = false,
70
                    Arguments = $"{convertitem.ConvertID.ToString()} {AESEncrypter.Encrypt(sendData)}"
71
                    //Arguments = $"{convertitem.ConvertID.ToString()} {convertitem.ProjectNumber} {AESEncrypter.Encrypt(MarkusDBConnectionString)} {gServiceHostAddress} {DownloadTempFolder} {MultiThreadMaxPages}"
72
                };
73

    
74
                ConvertProcess.StartInfo = startInfo;
75
                ConvertProcess.EnableRaisingEvents = false;
76

    
77
                System.Diagnostics.Debug.WriteLine("convert process run : " + startInfo.Arguments);
78

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

    
81
                if (ConvertProcess.Start())
82
                {
83
                    try
84
                    {
85
                        var processAffinity = ProcessorAffinityList.Except(AliveConvertQueue.Select(f => (long)f.ProcessorAffinity));
86

    
87
                        long currentAffinity = 0;
88

    
89
                        if (processAffinity.Count() > 0)
90
                        {
91
                            currentAffinity = processAffinity.First();
92

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

    
96
                            ConvertProcess.ProcessorAffinity = new IntPtr(currentAffinity);
97
                            logger.Info($"convert process currentAffinity set {currentAffinity} : UniqueKey:{convertitem.UniqueKey}   ConvertID:{convertitem.ConvertID}");
98

    
99
                        }
100
                        else
101
                        {
102
                            // 모두 사용중일때 점유율이 작은 걸로 사용
103
                            var CurrentProcessAffinity = AliveConvertQueue.Select(f => f.ProcessorAffinity).Distinct();
104

    
105
                            currentAffinity = CurrentProcessAffinity.Min();
106
                            ConvertProcess.ProcessorAffinity = new IntPtr(currentAffinity);
107

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

    
110
                        }
111

    
112
                        var item = AliveConvertQueue.Find(x => x.Equals(convertitem));
113

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

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

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

    
151
            using (DataBase.ConvertDatabase database = new DataBase.ConvertDatabase(MarkusDBConnectionString))
152
            {
153
                convertItems = database.GetWaitConvertItems(this.RunProjectList, StationServiceList.Where(x=>x.IsOnline).Sum(f=>f.Properties.PROCESS_COUNT)).ToList();
154
            }
155

    
156
            foreach (var convert in convertItems)
157
            {
158
                //ReflashSubService();
159

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

    
170
                    PassConvertItem(convert.PROJECT_NO, convert.ID, convert.DOCUMENT_ID);
171
                    
172
                    //System.Threading.Thread.Sleep(1000);
173
                }
174
            }
175
          
176
        }
177

    
178
        public bool IsDataBaseWaitingList(int overListCount)
179
        {
180
            bool result = false;
181

    
182
            try
183
            {
184
                using (DataBase.ConvertDatabase database = new DataBase.ConvertDatabase(MarkusDBConnectionString))
185
                {
186
                    var convertItems = database.GetWaitConvertItems(this.RunProjectList, overListCount);
187

    
188
                    if (convertItems.Count() > 0)
189
                    {
190
                        result = true;
191
                    }
192
                }
193
            }
194
            catch (Exception ex)
195
            {
196
                logger.Error($"IsDataBaseWaitingList Error",ex);
197
            }
198

    
199
            return result;
200
        }
201

    
202
        private async Task<bool> ReflashSubServiceAsync()
203
        {
204
            bool result = false;
205

    
206
            try
207
            {
208
                foreach (var subservice in StationServiceList)
209
                {
210
                    try
211
                    {
212
                        subservice.IsOnline = await SytemNet.PingAsync(subservice.Properties.SERVICE_ADDRESS);
213

    
214
                        if (subservice.IsOnline)
215
                        {
216
                            var alivelist = await subservice.Service.AliveConvertListAsync();
217

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

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

    
241
            return result;
242
        }
243

    
244

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

    
257
                //if (!isSubStation)
258
                //{
259
                    stationList = StationServiceList.Where(x => x.IsOnline);
260
                //}
261
                //else
262
                //{
263
                //    stationList = StationServiceList.Where(x => x.Properties.ID != this.ServiceID && x.IsOnline);
264
                //}
265

    
266
                if (stationList.SelectMany(x => x.ConvertItems).Count(c => c.ProjectNumber == ProjectNo && c.UniqueKey == UniqueKey) == 0)
267
                {
268
                    var station = stationList.OrderByDescending(x => x.Properties.PROCESS_COUNT - x.AliveCount).FirstOrDefault();
269

    
270
                    if (station != null)
271
                    {
272
                        if (station.Properties.PROCESS_COUNT - station.AliveCount > 0)
273
                        {
274
                            System.Diagnostics.Debug.WriteLine($"{station.Properties.SERVICE_ADDRESS}  {station.Properties.PROCESS_COUNT}/{station.AliveCount}");
275
                            var result = await station.Service.ConvertAddAsync(ProjectNo, ConvertID);
276

    
277
                            if (!result.IsNullOrEmpty())
278
                            {
279
                                if (result.ToLower() == true.ToString().ToLower())
280
                                {
281
                                    Console.WriteLine($"PassConvertItem - Service ID : {station.Properties.ID} ConvertID : {ConvertID}");
282
                                    logger.Info($"PassConvertItem - Service ID : {station.Properties.ID} ConvertID : {ConvertID}");
283

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

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

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

    
324
                    List<ConvertItem> convertItems = AliveConvertQueue;
325

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

    
338
                                }
339
                            }
340
                        }
341
                    }
342
                    catch (Exception ex)
343
                    {
344
                        logger.Error("CleanUpAliveQueueItems error",ex);
345
                    }
346
                }
347
            }
348
        }
349

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

    
361
                    List< WcfClient.StationServiceTask.ConvertItem> aliveItems = new List<WcfClient.StationServiceTask.ConvertItem>();
362

    
363
                    foreach (var item in StationServiceList.Where(x => x.IsOnline))
364
                    {
365
                        var serviceItems = await item.Service.AliveConvertListAsync();
366
                        aliveItems.AddRange(serviceItems);
367
                    }
368

    
369
                    if (aliveItems.Count() > 0)
370
                    {
371
                        logger.Warn($"aliveItems  : {string.Join(",",aliveItems.Select(x=>x.ConvertID))}");
372

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

    
392
        public void Stopprocess()
393
        {
394
            var process = Process.GetProcessesByName("Markus.Service.ConvertProcess");
395

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

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

    
417
            for (int i = process.Count() - 1; i >= 0; i--)
418
            {
419
                try
420
                {
421
                    var commandLines = process[i].Arguments().CommandLine;
422

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

    
438
        private async void ConvertFinish(ConvertItem convertitem)
439
        {
440
            try
441
            {
442
                System.Diagnostics.Debug.WriteLine("Convert Finish : " + convertitem.ConvertID);
443

    
444
                System.Diagnostics.Debug.WriteLine("ServiceStation.AliveConvertQueue.Count() : " + ServiceStation.AliveConvertQueue.Count());
445
                
446
                ServiceStation.AliveConvertQueue.RemoveAll(x=>x.ConvertID == convertitem.ConvertID);
447

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

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