프로젝트

일반

사용자정보

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

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

이력 | 보기 | 이력해설 | 다운로드 (13.2 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
            using (DataBase.ConvertDatabase database = new DataBase.ConvertDatabase(MarkusDBConnectionString))
131
            {
132
                var convertItems = database.GetWaitConvertItems(this.RunProjectList, StationServiceList.Where(x=>x.IsOnline).Sum(f=>f.Properties.PROCESS_COUNT));
133

    
134
                foreach (var convert in convertItems)
135
                {
136
                    if (convert.STATUS > (int)StatusCodeType.None)
137
                    {
138
                        database.SetCleanUpItem(convert.ID);
139
                    }
140

    
141
                    PassConvertItem(convert.PROJECT_NO, convert.ID,convert.DOCUMENT_ID);
142
                }
143
            }
144
        }
145

    
146
        private void ReflashSubService()
147
        {
148
            foreach (var subservice in StationServiceList)
149
            {
150
                try
151
                {
152
                    subservice.IsOnline = SytemNet.Ping(subservice.Properties.SERVICE_ADDRESS);
153

    
154
                    if (subservice.IsOnline)
155
                    {
156
                        var result = subservice.Service.AliveConvertList();
157

    
158
                        subservice.ConvertItems = result.ToList();
159
                        subservice.AliveCount = result.Count();
160
                    }
161
                    else
162
                    {
163
                        logger.Error($"Connection Error {subservice.Properties.SERVICE_ADDRESS}");
164
                        subservice.ConvertItems = new List<WcfClient.StationServiceAsync.ConvertItem>();
165
                        subservice.AliveCount = subservice.Properties.PROCESS_COUNT;
166
                    }
167
                }
168
                catch (Exception ex)
169
                {
170
                    logger.Error($"ReflashSubService error - Service ID : {subservice.Properties.ID} ", ex);
171
                }
172
            }
173
        }
174

    
175

    
176
        /// <summary>
177
        /// 
178
        /// </summary>
179
        /// <param name="ProjectNo"></param>
180
        /// <param name="ConvertID"></param>
181
        /// <param name="UniqueKey">Document ID(문서의 유일키)</param>
182
        private void PassConvertItem(string ProjectNo,string ConvertID,string UniqueKey)
183
        {
184

    
185
            try
186
            {
187

    
188
                var stationList = StationServiceList.Where(x => x.IsOnline);
189

    
190
                if (stationList.SelectMany(x => x.ConvertItems).Count(c => c.ProjectNumber == ProjectNo && c.UniqueKey == UniqueKey) == 0)
191
                {
192
                    var station = stationList.OrderByDescending(x => x.Properties.PROCESS_COUNT - x.AliveCount).FirstOrDefault();
193

    
194
                    if (station != null)
195
                    {
196
                        station.Service.ConvertAddAsync(ProjectNo, ConvertID);
197
                        logger.Info($"PassConvertItem - Service ID : {station.Properties.ID} ConvertID : {ConvertID}");
198
                    }
199
                }
200
            }
201
            catch (Exception ex)
202
            {
203
                logger.Error($"setDataBaseWaitingList", ex);
204
            }
205
        }
206

    
207
        private void CleanUpAliveQueueItems()
208
        {
209
            var processList = Process.GetProcessesByName("Markus.Service.ConvertProcess");
210

    
211
            if (processList.Length == 0)
212
            {
213
                AliveConvertQueue.Clear();
214
                System.Diagnostics.Debug.WriteLine("AliveConvertQueue.Clear()");
215
            }
216
            else
217
            {
218
                var argumentList = processList.Select(f => f.Arguments().CommandLine).SelectMany(f => f);
219

    
220
                for (int i = AliveConvertQueue.Count - 1; i >= 0; --i)
221
                {
222
                    if (argumentList.Count(x => x == AliveConvertQueue[i].ConvertID) == 0)
223
                    {
224
                        AliveConvertQueue.RemoveAt(i);
225
                    }
226
                }
227

    
228
                //foreach (var process in processList)
229
                //{
230
                //    var arguments = process.Arguments();
231

    
232
                //    if (arguments.CommandLine?.Count() == 2)
233
                //    {
234
                //        if (AliveConvertQueue.Count(x => x.ConvertID == arguments.CommandLine.First()) == 0)
235
                //        {
236
                //            var convetContext = ObjectToBytesStringConvert.BytesStringToObject<ProcessContext>(AESEncrypter.Decrypt(arguments.CommandLine[1]));
237

    
238
                //            if (convetContext.ServiceStationUri == this.gServiceHostAddress.ToString())
239
                //            {
240
                //                process.Kill();
241
                //            }
242
                //        }
243
                //    }
244
                //}
245
            }
246

    
247
        }
248

    
249
        private void CleanUpDataBaseItems()
250
        {
251
            using (DataBase.ConvertDatabase database = new DataBase.ConvertDatabase(MarkusDBConnectionString))
252
            {
253
                var items = database.GetConvertingItems(RunProjectList);
254

    
255
                List< WcfClient.StationServiceAsync.ConvertItem> aliveItems = new List<WcfClient.StationServiceAsync.ConvertItem>();
256

    
257
                foreach (var item in StationServiceList.Where(x=>x.IsOnline))
258
                {
259
                    try
260
                    {
261
                        aliveItems.AddRange(item.Service.AliveConvertList());
262
                    }
263
                    catch (Exception)
264
                    {
265
                    }
266
                }
267

    
268
                foreach (var item in items)
269
                {
270
                    if(aliveItems.Count(x=>x.ConvertID == item.ID) == 0)
271
                    {
272
                        database.SetCleanUpItem(item.ID);
273
                    }
274
                }
275
            }
276
        }
277

    
278

    
279
        public void Stopprocess()
280
        {
281
            var process = Process.GetProcessesByName("Markus.Service.ConvertProcess");
282

    
283
            for (int i = process.Count() - 1; i >= 0 ; i--)
284
            {
285
                try
286
                {
287
                    Console.WriteLine($"{i} Process Kill");
288
                    process[i].Kill();
289
                }
290
                catch (Exception ex)
291
                {
292
                    System.Diagnostics.Debug.WriteLine(ex.ToString());
293
                }
294
            }
295
        }
296

    
297
        /// <summary>
298
        /// finish가 호출되고 살아있는 프로세스라고 추정됨
299
        /// </summary>
300
        public void DeadLockProcessKill()
301
        {
302
            var process = Process.GetProcessesByName("Markus.Service.ConvertProcess");
303

    
304
            for (int i = process.Count() - 1; i >= 0; i--)
305
            {
306
                try
307
                {
308
                    var commandLines = process[i].Arguments().CommandLine;
309

    
310
                    if (commandLines.Count() > 0)
311
                    {
312
                        if (ServiceStation.AliveConvertQueue.Count(f => f.ConvertID == commandLines[0]) == 0)
313
                        {
314
                            process[i].Kill();
315
                        }
316
                    }
317
                }
318
                catch (Exception ex)
319
                {
320
                    System.Diagnostics.Debug.WriteLine(ex.ToString());
321
                }
322
            }
323
        }
324

    
325
        private void ConvertFinish(ConvertItem convertitem)
326
        {
327
            try
328
            {
329
                System.Diagnostics.Debug.WriteLine("Convert Finish : " + convertitem.ConvertID);
330

    
331
                System.Diagnostics.Debug.WriteLine("ServiceStation.AliveConvertQueue.Count() : " + ServiceStation.AliveConvertQueue.Count());
332
                
333
                ServiceStation.AliveConvertQueue.Remove(convertitem);
334

    
335
                System.Diagnostics.Debug.WriteLine("ServiceStation.AliveConvertQueue.Count() : " + ServiceStation.AliveConvertQueue.Count());
336

    
337
                if (IsStation)
338
                {
339
                    System.Diagnostics.Debug.WriteLine("setDataBaseWaitingList");
340
                    setDataBaseWaitingList();
341
                    System.Diagnostics.Debug.WriteLine("ReleaseItems end");
342
                }
343
                else
344
                {
345
                    if (StationClient != null)
346
                    {
347
                        StationClient.ReleaseConvertItems();
348
                    }
349
                }
350
                //if (ServiceStation.AliveConvertQueue.Count() < MultiProcessCount)
351
                //{
352
                //    setDataBaseWaitingList();
353
                //}
354
            }
355
            catch (Exception ex)
356
            {
357
                logger.Error("ConvertFinish Error",ex);
358
            }
359
        }
360
    }
361
}
클립보드 이미지 추가 (최대 크기: 500 MB)