markus / ConvertService / ServiceBase / Markus.Service.Station / StationService / ServiceStationTask.cs @ 1d79913e
이력 | 보기 | 이력해설 | 다운로드 (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 |
var convertPath = System.IO.Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "Convert\\Markus.Service.ConvertProcess.exe"); |
57 |
|
58 |
ProcessStartInfo startInfo = new ProcessStartInfo |
59 |
{ |
60 |
UseShellExecute = false, |
61 |
FileName = convertPath, |
62 |
WindowStyle = ProcessWindowStyle.Hidden, |
63 |
CreateNoWindow = true, |
64 |
ErrorDialog = false, |
65 |
RedirectStandardError = false, |
66 |
Arguments = $"{convertitem.ConvertID.ToString()} {AESEncrypter.Encrypt(sendData)}" |
67 |
//Arguments = $"{convertitem.ConvertID.ToString()} {convertitem.ProjectNumber} {AESEncrypter.Encrypt(MarkusDBConnectionString)} {gServiceHostAddress} {DownloadTempFolder} {MultiThreadMaxPages}" |
68 |
}; |
69 |
|
70 |
ConvertProcess.StartInfo = startInfo; |
71 |
ConvertProcess.EnableRaisingEvents = true; |
72 |
|
73 |
System.Diagnostics.Debug.WriteLine("convert process run : " + startInfo.Arguments); |
74 |
|
75 |
logger.Info($"convert process run : UniqueKey:{convertitem.UniqueKey} ConvertID:{convertitem.ConvertID}" + startInfo.Arguments); |
76 |
|
77 |
if (ConvertProcess.Start()) |
78 |
{ |
79 |
try |
80 |
{ |
81 |
var processAffinity = ProcessorAffinityList.Except(AliveConvertQueue.Select(f => (long)f.ProcessorAffinity)); |
82 |
|
83 |
long currentAffinity = 0; |
84 |
|
85 |
if (processAffinity.Count() > 0) |
86 |
{ |
87 |
currentAffinity = processAffinity.First(); |
88 |
|
89 |
//int bitMask = 1 << (convertitem.ProcessorAffinity - 1); |
90 |
//bitMask |= 1 << (anotherUserSelection - 1); / // 프로세스 두개 이상 선택 |
91 |
|
92 |
ConvertProcess.ProcessorAffinity = new IntPtr(currentAffinity); |
93 |
logger.Info($"convert process currentAffinity set {currentAffinity} : UniqueKey:{convertitem.UniqueKey} ConvertID:{convertitem.ConvertID}"); |
94 |
|
95 |
} |
96 |
else |
97 |
{ |
98 |
// 모두 사용중일때 점유율이 작은 걸로 사용 |
99 |
var CurrentProcessAffinity = AliveConvertQueue.Where(x=>x.ProcessorAffinity > 0).Select(f => f.ProcessorAffinity).Distinct(); |
100 |
|
101 |
currentAffinity = CurrentProcessAffinity.Min(); |
102 |
ConvertProcess.ProcessorAffinity = new IntPtr(currentAffinity); |
103 |
|
104 |
logger.Info($"convert process Affinity All use {currentAffinity} : UniqueKey:{convertitem.UniqueKey} ConvertID:{convertitem.ConvertID}"); |
105 |
|
106 |
} |
107 |
|
108 |
var item = AliveConvertQueue.Find(x => x.Equals(convertitem)); |
109 |
|
110 |
if (item != null) |
111 |
{ |
112 |
item.ProcessorAffinity = currentAffinity; |
113 |
} |
114 |
} |
115 |
catch (Exception ex) |
116 |
{ |
117 |
AliveConvertQueue.Remove(convertitem); |
118 |
logger.Error("ConvertProcessStart error", ex); |
119 |
} |
120 |
|
121 |
logger.Info($"convert process run true UniqueKey:{convertitem.UniqueKey} ConvertID:{convertitem.ConvertID}"); |
122 |
result = true; |
123 |
} |
124 |
} |
125 |
catch (Exception ex) |
126 |
{ |
127 |
AliveConvertQueue.Remove(convertitem); |
128 |
throw new Exception("ConvertThread " + $"{convertitem.ConvertID.ToString()} {convertitem.ProjectNumber} {AESEncrypter.Encrypt(MarkusDBConnectionString)} {gServiceHostAddress} {DownloadTempFolder} {MultiThreadMaxPages}", ex.InnerException); |
129 |
} |
130 |
finally |
131 |
{ |
132 |
//GC.WaitForPendingFinalizers(); |
133 |
//GC.Collect(2); |
134 |
//GC.Collect(2); |
135 |
} |
136 |
|
137 |
return result; |
138 |
} |
139 |
|
140 |
/// <summary> |
141 |
/// DB에 있는 대기중인 Item을 가져온다. |
142 |
/// </summary> |
143 |
public void setDataBaseWaitingList() |
144 |
{ |
145 |
List<EntityModel.CONVERTER_DOC> convertItems = new List<EntityModel.CONVERTER_DOC>(); |
146 |
|
147 |
using (DataBase.ConvertDatabase database = new DataBase.ConvertDatabase(MarkusDBConnectionString)) |
148 |
{ |
149 |
convertItems = database.GetWaitConvertItems(this.RunProjectList, StationServiceList.Where(x=>x.IsOnline).Sum(f=>f.Properties.PROCESS_COUNT)).ToList(); |
150 |
} |
151 |
|
152 |
foreach (var convert in convertItems) |
153 |
{ |
154 |
//ReflashSubService(); |
155 |
|
156 |
if (AliveConvertQueue.Count(x => x.ConvertID == convert.ID) == 0) |
157 |
{ |
158 |
if (convert.STATUS > (int)StatusCodeType.None) |
159 |
{ |
160 |
using (DataBase.ConvertDatabase database = new DataBase.ConvertDatabase(MarkusDBConnectionString)) |
161 |
{ |
162 |
database.SetCleanUpItem(convert.ID, 1); |
163 |
} |
164 |
} |
165 |
|
166 |
PassConvertItem(convert.PROJECT_NO, convert.ID, convert.DOCUMENT_ID); |
167 |
|
168 |
//System.Threading.Thread.Sleep(1000); |
169 |
} |
170 |
} |
171 |
|
172 |
} |
173 |
|
174 |
public bool IsDataBaseWaitingList(int overListCount) |
175 |
{ |
176 |
bool result = false; |
177 |
|
178 |
try |
179 |
{ |
180 |
using (DataBase.ConvertDatabase database = new DataBase.ConvertDatabase(MarkusDBConnectionString)) |
181 |
{ |
182 |
var convertItems = database.GetWaitConvertItems(this.RunProjectList, overListCount); |
183 |
|
184 |
if (convertItems.Count() > 0) |
185 |
{ |
186 |
result = true; |
187 |
} |
188 |
} |
189 |
} |
190 |
catch (Exception ex) |
191 |
{ |
192 |
logger.Error($"IsDataBaseWaitingList Error",ex); |
193 |
} |
194 |
|
195 |
return result; |
196 |
} |
197 |
|
198 |
private async Task<bool> ReflashSubServiceAsync() |
199 |
{ |
200 |
bool result = false; |
201 |
|
202 |
try |
203 |
{ |
204 |
foreach (var subservice in StationServiceList) |
205 |
{ |
206 |
try |
207 |
{ |
208 |
subservice.IsOnline = await SytemNet.PingAsync(subservice.Properties.SERVICE_ADDRESS); |
209 |
|
210 |
if (subservice.IsOnline) |
211 |
{ |
212 |
var alivelist = await subservice.Service.AliveConvertListAsync(); |
213 |
|
214 |
subservice.ConvertItems = alivelist.ToList(); |
215 |
subservice.AliveCount = alivelist.Count(); |
216 |
} |
217 |
else |
218 |
{ |
219 |
logger.Error($"Connection Error {subservice.Properties.SERVICE_ADDRESS}"); |
220 |
subservice.ConvertItems = new List<WcfClient.StationServiceTask.ConvertItem>(); |
221 |
subservice.AliveCount = subservice.Properties.PROCESS_COUNT; |
222 |
} |
223 |
|
224 |
result = true; |
225 |
} |
226 |
catch (Exception ex) |
227 |
{ |
228 |
logger.Error($"ReflashSubService error - Service ID : {subservice.Properties.ID} ", ex); |
229 |
} |
230 |
} |
231 |
} |
232 |
catch (Exception ex) |
233 |
{ |
234 |
logger.Error($"ReflashSubService error", ex); |
235 |
} |
236 |
|
237 |
return result; |
238 |
} |
239 |
|
240 |
|
241 |
/// <summary> |
242 |
/// |
243 |
/// </summary> |
244 |
/// <param name="ProjectNo"></param> |
245 |
/// <param name="ConvertID"></param> |
246 |
/// <param name="UniqueKey">Document ID(문서의 유일키)</param> |
247 |
private async void PassConvertItem(string ProjectNo,string ConvertID,string UniqueKey,bool isSubStation = false) |
248 |
{ |
249 |
try |
250 |
{ |
251 |
IEnumerable<SubStationServiceItem> stationList = null; |
252 |
|
253 |
//if (!isSubStation) |
254 |
//{ |
255 |
stationList = StationServiceList.Where(x => x.IsOnline); |
256 |
//} |
257 |
//else |
258 |
//{ |
259 |
// stationList = StationServiceList.Where(x => x.Properties.ID != this.ServiceID && x.IsOnline); |
260 |
//} |
261 |
|
262 |
if (stationList.SelectMany(x => x.ConvertItems).Count(c => c.ProjectNumber == ProjectNo && c.UniqueKey == UniqueKey) == 0) |
263 |
{ |
264 |
var station = stationList.OrderByDescending(x => x.Properties.PROCESS_COUNT - x.AliveCount).FirstOrDefault(); |
265 |
|
266 |
if (station != null) |
267 |
{ |
268 |
if (station.Properties.PROCESS_COUNT - station.AliveCount > 0) |
269 |
{ |
270 |
System.Diagnostics.Debug.WriteLine($"{station.Properties.SERVICE_ADDRESS} {station.Properties.PROCESS_COUNT}/{station.AliveCount}"); |
271 |
var result = await station.Service.PassConvertAsync(ProjectNo, ConvertID); |
272 |
|
273 |
if (!result.IsNullOrEmpty()) |
274 |
{ |
275 |
if (result.ToLower() == true.ToString().ToLower()) |
276 |
{ |
277 |
Console.WriteLine($"PassConvertItem - Service ID : {station.Properties.ID} ConvertID : {ConvertID}"); |
278 |
logger.Info($"PassConvertItem - Service ID : {station.Properties.ID} ConvertID : {ConvertID}"); |
279 |
|
280 |
station.AliveCount++; |
281 |
} |
282 |
else |
283 |
{ |
284 |
logger.Error($"PassConvertItem Error result : {result} - Service ID : {station.Properties.ID} ConvertID : {ConvertID}"); |
285 |
} |
286 |
} |
287 |
else |
288 |
{ |
289 |
logger.Error($"PassConvertItem result: Nulll; - Service ID : {station.Properties.ID} ConvertID : {ConvertID}"); |
290 |
System.Diagnostics.Debug.WriteLine("result : Nulll;"); |
291 |
} |
292 |
} |
293 |
} |
294 |
} |
295 |
} |
296 |
catch (Exception ex) |
297 |
{ |
298 |
logger.Error($"setDataBaseWaitingList", ex); |
299 |
} |
300 |
} |
301 |
|
302 |
/// <summary> |
303 |
/// 컨버터 프로세스와 AiliveItems을 비교하여 AliveItems에 없는 경우 AliveItems을 제거 |
304 |
/// </summary> |
305 |
private void CleanUpAliveQueueItems() |
306 |
{ |
307 |
if (AliveConvertQueue.Count() > 0) |
308 |
{ |
309 |
var processList = Process.GetProcessesByName("Markus.Service.ConvertProcess"); |
310 |
|
311 |
if (processList.Length == 0) |
312 |
{ |
313 |
AliveConvertQueue.Clear(); |
314 |
System.Diagnostics.Debug.WriteLine("AliveConvertQueue.Clear()"); |
315 |
} |
316 |
else |
317 |
{ |
318 |
var argumentList = processList.Select(f => f.Arguments().CommandLine).SelectMany(f => f).ToList(); |
319 |
|
320 |
List<ConvertItem> convertItems = AliveConvertQueue; |
321 |
|
322 |
try |
323 |
{ |
324 |
if (convertItems.Count() > 0 && argumentList.Count() > 0) |
325 |
{ |
326 |
for (int i = convertItems.Count - 1; i >= 0; --i) |
327 |
{ |
328 |
if (argumentList.Count(x => x == convertItems[i].ConvertID) == 0) |
329 |
{ |
330 |
System.Diagnostics.Debug.WriteLine($"AliveConvertQueue remove {convertItems[i].ConvertID}"); |
331 |
logger.Warn($"AliveConvertQueue remove {convertItems[i].ConvertID}"); |
332 |
AliveConvertQueue.Remove(convertItems[i]); |
333 |
|
334 |
} |
335 |
} |
336 |
} |
337 |
} |
338 |
catch (Exception ex) |
339 |
{ |
340 |
logger.Error("CleanUpAliveQueueItems error",ex); |
341 |
} |
342 |
} |
343 |
} |
344 |
} |
345 |
|
346 |
/// <summary> |
347 |
/// AliveConvertQueue와 db를 비교하여 AliveConvertQueue에 없는 데이터를 초기화 하여 다시 컨버팅 |
348 |
/// </summary> |
349 |
private async void CleanUpDataBaseItems() |
350 |
{ |
351 |
try |
352 |
{ |
353 |
using (DataBase.ConvertDatabase database = new DataBase.ConvertDatabase(MarkusDBConnectionString)) |
354 |
{ |
355 |
var items = database.GetConvertingItems(RunProjectList); |
356 |
|
357 |
List< WcfClient.StationServiceTask.ConvertItem> aliveItems = new List<WcfClient.StationServiceTask.ConvertItem>(); |
358 |
|
359 |
foreach (var item in StationServiceList.Where(x => x.IsOnline)) |
360 |
{ |
361 |
var serviceItems = await item.Service.AliveConvertListAsync(); |
362 |
aliveItems.AddRange(serviceItems); |
363 |
} |
364 |
|
365 |
if (aliveItems.Count() > 0) |
366 |
{ |
367 |
logger.Warn($"aliveItems : {string.Join(",",aliveItems.Select(x=>x.ConvertID))}"); |
368 |
|
369 |
foreach (var item in items) |
370 |
{ |
371 |
if (aliveItems.Count(x => x.ConvertID == item.ID) == 0) |
372 |
{ |
373 |
Console.WriteLine($"SetCleanUpItem : {item.ID}"); |
374 |
logger.Warn($"SetCleanUpItem : {item.ID}"); |
375 |
database.SetCleanUpItem(item.ID, 0); |
376 |
} |
377 |
} |
378 |
} |
379 |
|
380 |
} |
381 |
} |
382 |
catch (Exception ex) |
383 |
{ |
384 |
throw new Exception("CleanUpDataBaseItems Error ", ex); |
385 |
} |
386 |
} |
387 |
|
388 |
public void Stopprocess() |
389 |
{ |
390 |
var process = Process.GetProcessesByName("Markus.Service.ConvertProcess"); |
391 |
|
392 |
for (int i = process.Count() - 1; i >= 0 ; i--) |
393 |
{ |
394 |
try |
395 |
{ |
396 |
Console.WriteLine($"{i} Process Kill"); |
397 |
process[i].Kill(); |
398 |
} |
399 |
catch (Exception ex) |
400 |
{ |
401 |
System.Diagnostics.Debug.WriteLine(ex.ToString()); |
402 |
} |
403 |
} |
404 |
} |
405 |
|
406 |
/// <summary> |
407 |
/// finish가 호출되고 살아있는 프로세스라고 추정됨 |
408 |
/// </summary> |
409 |
public void DeadLockProcessKill() |
410 |
{ |
411 |
var process = Process.GetProcessesByName("Markus.Service.ConvertProcess"); |
412 |
|
413 |
for (int i = process.Count() - 1; i >= 0; i--) |
414 |
{ |
415 |
try |
416 |
{ |
417 |
var commandLines = process[i].Arguments().CommandLine; |
418 |
|
419 |
if (commandLines.Count() > 0) |
420 |
{ |
421 |
if (ServiceStation.AliveConvertQueue.Count(f => f.ConvertID == commandLines[0]) == 0) |
422 |
{ |
423 |
process[i].Kill(); |
424 |
} |
425 |
} |
426 |
} |
427 |
catch (Exception ex) |
428 |
{ |
429 |
System.Diagnostics.Debug.WriteLine(ex.ToString()); |
430 |
} |
431 |
} |
432 |
} |
433 |
|
434 |
private async void ConvertFinish(ConvertItem convertitem) |
435 |
{ |
436 |
try |
437 |
{ |
438 |
System.Diagnostics.Debug.WriteLine("Convert Finish : " + convertitem.ConvertID); |
439 |
|
440 |
System.Diagnostics.Debug.WriteLine("ServiceStation.AliveConvertQueue.Count() : " + ServiceStation.AliveConvertQueue.Count()); |
441 |
|
442 |
List<string> deleteItems = new List<string> { convertitem.ConvertID }; |
443 |
|
444 |
|
445 |
ServiceStation.AliveConvertQueue.RemoveAll(x=>deleteItems.Any(y=>y == x.ConvertID)); |
446 |
|
447 |
System.Diagnostics.Debug.WriteLine("ServiceStation.AliveConvertQueue.Count() : " + ServiceStation.AliveConvertQueue.Count()); |
448 |
|
449 |
if (IsStation) |
450 |
{ |
451 |
if (!IsReleaseItems) |
452 |
{ |
453 |
System.Diagnostics.Debug.WriteLine("ConvertFinish ReleaseItems call"); |
454 |
ReleaseItems(); |
455 |
} |
456 |
} |
457 |
else |
458 |
{ |
459 |
if (StationClient != null) |
460 |
{ |
461 |
await StationClient.ReleaseConvertItemsAsync(); |
462 |
} |
463 |
} |
464 |
//if (ServiceStation.AliveConvertQueue.Count() < MultiProcessCount) |
465 |
//{ |
466 |
// setDataBaseWaitingList(); |
467 |
//} |
468 |
} |
469 |
catch (Exception ex) |
470 |
{ |
471 |
logger.Error("ConvertFinish Error",ex); |
472 |
} |
473 |
} |
474 |
} |
475 |
} |