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 |
} |