프로젝트

일반

사용자정보

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

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

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

    
54
                var sendData = ObjectToBytesStringConvert.ObjectToBytesString(processSendData);
55
                
56
                ProcessStartInfo startInfo = new ProcessStartInfo
57
                {
58
                    UseShellExecute = false,
59
                    FileName = "Markus.Service.ConvertProcess.exe",
60
                    WindowStyle = ProcessWindowStyle.Hidden,
61
                    CreateNoWindow = true,
62
                    ErrorDialog = false,
63
                    RedirectStandardError = false,
64
                    Arguments = $"{convertitem.ConvertID.ToString()} {AESEncrypter.Encrypt(sendData)}"
65
                    //Arguments = $"{convertitem.ConvertID.ToString()} {convertitem.ProjectNumber} {AESEncrypter.Encrypt(MarkusDBConnectionString)} {gServiceHostAddress} {DownloadTempFolder} {MultiThreadMaxPages}"
66
                };
67

    
68
                ConvertProcess.StartInfo = startInfo;
69
                ConvertProcess.EnableRaisingEvents = false;
70

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

    
73

    
74
                if (ConvertProcess.Start())
75
                {
76
                    try
77
                    {
78
                        var processAffinity = ProcessorAffinityList.Except(AliveConvertQueue.Select(f => (long)f.ProcessorAffinity));
79

    
80
                        if (processAffinity.Count() > 0)
81
                        {
82
                            convertitem.ProcessorAffinity = processAffinity.First();
83

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

    
87
                            ConvertProcess.ProcessorAffinity = new IntPtr(convertitem.ProcessorAffinity);
88

    
89
                        }
90
                        else
91
                        {
92
                            // 모두 사용중일때 점유율이 작은 걸로 사용
93
                            var CurrentProcessAffinity = AliveConvertQueue.Select(f =>f.ProcessorAffinity).Distinct();
94

    
95
                            var affinity = CurrentProcessAffinity.Min();
96

    
97
                            convertitem.ProcessorAffinity = affinity;
98
                            ConvertProcess.ProcessorAffinity = new IntPtr(affinity);
99
                        }
100
                    }
101
                    catch (Exception ex)
102
                    {
103
                        System.Diagnostics.Debug.WriteLine(ex);
104
                    }
105
        
106

    
107
                    ServiceStation.AliveConvertQueue.Add(convertitem);
108
                    result = true;
109
                }
110
            }
111
            catch (Exception ex)
112
            {
113
                throw new Exception("ConvertThread " + $"{convertitem.ConvertID.ToString()} {convertitem.ProjectNumber} {AESEncrypter.Encrypt(MarkusDBConnectionString)} {gServiceHostAddress} {DownloadTempFolder} {MultiThreadMaxPages}", ex.InnerException);
114
            }
115
            finally
116
            {
117
                //GC.WaitForPendingFinalizers();
118
                //GC.Collect(2);
119
                //GC.Collect(2);
120
            }
121

    
122
            return result;
123
        }
124
    
125
        /// <summary>
126
        /// DB에 있는 대기중인 Item을 가져온다.
127
        /// </summary>
128
        public void setDataBaseWaitingList()
129
        {
130
            List<EntityModel.CONVERTER_DOC> convertItems = new List<EntityModel.CONVERTER_DOC>();
131

    
132
            using (DataBase.ConvertDatabase database = new DataBase.ConvertDatabase(MarkusDBConnectionString))
133
            {
134
                convertItems = database.GetWaitConvertItems(this.RunProjectList, StationServiceList.Where(x=>x.IsOnline).Sum(f=>f.Properties.PROCESS_COUNT)).ToList();
135
            }
136

    
137
            foreach (var convert in convertItems)
138
            {
139
                //ReflashSubService();
140

    
141
                if (convert.STATUS > (int)StatusCodeType.None)
142
                {
143
                    using (DataBase.ConvertDatabase database = new DataBase.ConvertDatabase(MarkusDBConnectionString))
144
                    {
145
                        database.SetCleanUpItem(convert.ID,1);
146
                    }
147
                }
148

    
149
                PassConvertItem(convert.PROJECT_NO, convert.ID,convert.DOCUMENT_ID);
150
            }
151
          
152
        }
153

    
154
        public bool IsDataBaseWaitingList(int overListCount)
155
        {
156
            bool result = false;
157

    
158
            try
159
            {
160
                using (DataBase.ConvertDatabase database = new DataBase.ConvertDatabase(MarkusDBConnectionString))
161
                {
162
                    var convertItems = database.GetWaitConvertItems(this.RunProjectList, overListCount);
163

    
164
                    if (convertItems.Count() > 0)
165
                    {
166
                        result = true;
167
                    }
168
                }
169
            }
170
            catch (Exception ex)
171
            {
172
                logger.Error($"IsDataBaseWaitingList Error",ex);
173
            }
174

    
175
            return result;
176
        }
177

    
178
        private async void ReflashSubServiceAsync()
179
        {
180
            foreach (var subservice in StationServiceList)
181
            {
182
                try
183
                {
184
                    subservice.IsOnline = await SytemNet.PingAsync(subservice.Properties.SERVICE_ADDRESS);
185

    
186
                    if (subservice.IsOnline)
187
                    {
188
                        var result = await subservice.Service.AliveConvertListAsync();
189

    
190
                        subservice.ConvertItems = result.ToList();
191
                        subservice.AliveCount = result.Count();
192
                    }
193
                    else
194
                    {
195
                        logger.Error($"Connection Error {subservice.Properties.SERVICE_ADDRESS}");
196
                        subservice.ConvertItems = new List<WcfClient.StationServiceTask.ConvertItem>();
197
                        subservice.AliveCount = subservice.Properties.PROCESS_COUNT;
198
                    }
199
                }
200
                catch (Exception ex)
201
                {
202
                    logger.Error($"ReflashSubService error - Service ID : {subservice.Properties.ID} ", ex);
203
                }
204
            }
205
        }
206

    
207

    
208
        /// <summary>
209
        /// 
210
        /// </summary>
211
        /// <param name="ProjectNo"></param>
212
        /// <param name="ConvertID"></param>
213
        /// <param name="UniqueKey">Document ID(문서의 유일키)</param>
214
        private async void PassConvertItem(string ProjectNo,string ConvertID,string UniqueKey)
215
        {
216

    
217
            try
218
            {
219
                var stationList = StationServiceList.Where(x => x.IsOnline);
220

    
221
                if (stationList.SelectMany(x => x.ConvertItems).Count(c => c.ProjectNumber == ProjectNo && c.UniqueKey == UniqueKey) == 0)
222
                {
223
                    var station = stationList.OrderByDescending(x => x.Properties.PROCESS_COUNT - x.AliveCount).FirstOrDefault();
224

    
225
                    if (station != null)
226
                    {
227
                        if (station.Properties.PROCESS_COUNT - station.AliveCount > 0)
228
                        {
229
                            System.Diagnostics.Debug.WriteLine($"{station.Properties.SERVICE_ADDRESS}  {station.Properties.PROCESS_COUNT}/{station.AliveCount}");
230
                            var result = await station.Service.ConvertAddAsync(ProjectNo, ConvertID);
231

    
232
                            if (!result.IsNullOrEmpty())
233
                            {
234
                                if (result.ToLower() == true.ToString().ToLower())
235
                                {
236
                                    station.AliveCount++;
237
                                }
238
                            }
239
                            else
240
                            {
241
                                System.Diagnostics.Debug.WriteLine("result : Nulll;");
242
                            }
243

    
244
                            logger.Info($"PassConvertItem - Service ID : {station.Properties.ID} ConvertID : {ConvertID}");
245
                        }
246
                    }
247
                }
248
            }
249
            catch (Exception ex)
250
            {
251
                logger.Error($"setDataBaseWaitingList", ex);
252
            }
253
        }
254

    
255
        /// <summary>
256
        /// 컨버터 프로세스와 AiliveItems을 비교하여 AliveItems에 없는 경우 AliveItems을 제거
257
        /// </summary>
258
        private void CleanUpAliveQueueItems()
259
        {
260
            if (AliveConvertQueue.Count() > 0)
261
            {
262
                var processList = Process.GetProcessesByName("Markus.Service.ConvertProcess");
263

    
264
                if (processList.Length == 0)
265
                {
266
                    AliveConvertQueue.Clear();
267
                    System.Diagnostics.Debug.WriteLine("AliveConvertQueue.Clear()");
268
                }
269
                else
270
                {
271
                    var argumentList = processList.Select(f => f.Arguments().CommandLine).SelectMany(f => f);
272

    
273
                    List<ConvertItem> convertItems = AliveConvertQueue;
274

    
275
                    try
276
                    {
277
                        if (convertItems.Count() > 0)
278
                        {
279
                            for (int i = convertItems.Count - 1; i >= 0; --i)
280
                            {
281
                                if (argumentList.Count(x => x == convertItems[i].ConvertID) == 0)
282
                                {
283
                                    AliveConvertQueue.RemoveAt(i);
284
                                }
285
                            }
286
                        }
287
                    }
288
                    catch (Exception ex)
289
                    {
290
                        System.Diagnostics.Debug.WriteLine(ex);
291
                    }
292
                }
293
            }
294
        }
295

    
296
        /// <summary>
297
        /// AliveConvertQueue와 db를 비교하여 AliveConvertQueue에 없는 데이터를 초기화 하여 다시 컨버팅
298
        /// </summary>
299
        private async void CleanUpDataBaseItems()
300
        {
301
            try
302
            {
303
                using (DataBase.ConvertDatabase database = new DataBase.ConvertDatabase(MarkusDBConnectionString))
304
                {
305
                    var items = database.GetConvertingItems(RunProjectList);
306

    
307
                    List< WcfClient.StationServiceTask.ConvertItem> aliveItems = new List<WcfClient.StationServiceTask.ConvertItem>();
308

    
309
                    foreach (var item in StationServiceList.Where(x => x.IsOnline))
310
                    {
311
                        var serviceItems = await item.Service.AliveConvertListAsync();
312
                        aliveItems.AddRange(serviceItems);
313
                    }
314

    
315
                    foreach (var item in items)
316
                    {
317
                        if (aliveItems.Count(x => x.ConvertID == item.ID) == 0)
318
                        {
319
                            database.SetCleanUpItem(item.ID,0);
320
                        }
321
                    }
322
             
323
                }
324
            }
325
            catch (Exception ex)
326
            {
327
                throw new Exception("CleanUpDataBaseItems Error ", ex);
328
            }
329
        }
330

    
331

    
332
        public void Stopprocess()
333
        {
334
            var process = Process.GetProcessesByName("Markus.Service.ConvertProcess");
335

    
336
            for (int i = process.Count() - 1; i >= 0 ; i--)
337
            {
338
                try
339
                {
340
                    Console.WriteLine($"{i} Process Kill");
341
                    process[i].Kill();
342
                }
343
                catch (Exception ex)
344
                {
345
                    System.Diagnostics.Debug.WriteLine(ex.ToString());
346
                }
347
            }
348
        }
349

    
350
        /// <summary>
351
        /// finish가 호출되고 살아있는 프로세스라고 추정됨
352
        /// </summary>
353
        public void DeadLockProcessKill()
354
        {
355
            var process = Process.GetProcessesByName("Markus.Service.ConvertProcess");
356

    
357
            for (int i = process.Count() - 1; i >= 0; i--)
358
            {
359
                try
360
                {
361
                    var commandLines = process[i].Arguments().CommandLine;
362

    
363
                    if (commandLines.Count() > 0)
364
                    {
365
                        if (ServiceStation.AliveConvertQueue.Count(f => f.ConvertID == commandLines[0]) == 0)
366
                        {
367
                            process[i].Kill();
368
                        }
369
                    }
370
                }
371
                catch (Exception ex)
372
                {
373
                    System.Diagnostics.Debug.WriteLine(ex.ToString());
374
                }
375
            }
376
        }
377

    
378
        private async void ConvertFinish(ConvertItem convertitem)
379
        {
380
            try
381
            {
382
                System.Diagnostics.Debug.WriteLine("Convert Finish : " + convertitem.ConvertID);
383

    
384
                System.Diagnostics.Debug.WriteLine("ServiceStation.AliveConvertQueue.Count() : " + ServiceStation.AliveConvertQueue.Count());
385
                
386
                ServiceStation.AliveConvertQueue.Remove(convertitem);
387

    
388
                System.Diagnostics.Debug.WriteLine("ServiceStation.AliveConvertQueue.Count() : " + ServiceStation.AliveConvertQueue.Count());
389

    
390
                if (IsStation)
391
                {
392
                    //if (!IsReleaseItems)
393
                    //{
394
                    //    System.Diagnostics.Debug.WriteLine("ConvertFinish ReleaseItems call");
395
                    //    ReleaseItems();
396
                    //}
397
                }
398
                else
399
                {
400
                    if (StationClient != null)
401
                    {
402
                       await  StationClient.ReleaseConvertItemsAsync();
403
                    }
404
                }
405
                //if (ServiceStation.AliveConvertQueue.Count() < MultiProcessCount)
406
                //{
407
                //    setDataBaseWaitingList();
408
                //}
409
            }
410
            catch (Exception ex)
411
            {
412
                logger.Error("ConvertFinish Error",ex);
413
            }
414
        }
415
    }
416
}
클립보드 이미지 추가 (최대 크기: 500 MB)