프로젝트

일반

사용자정보

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

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

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

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

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

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

    
74

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

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

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

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

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

    
96
                            var affinity = CurrentProcessAffinity.Min();
97

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

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

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

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

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

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

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

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

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

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

    
176
            return result;
177
        }
178

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

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

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

    
208

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

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

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

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

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

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

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

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

    
274
                    List<ConvertItem> convertItems = AliveConvertQueue;
275

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

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

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

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

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

    
332

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

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

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

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

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

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

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

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

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