|
|
@@ -0,0 +1,275 @@
|
|
|
+package com.sig.todp.server.service;
|
|
|
+
|
|
|
+import com.its.common.utils.Elapsed;
|
|
|
+import com.sig.todp.server.cluster.ClusterConfig;
|
|
|
+import com.sig.todp.server.dao.mapper.IntMapper;
|
|
|
+import com.sig.todp.server.dto.RegionCenter;
|
|
|
+import com.sig.todp.server.dto.TTodInt;
|
|
|
+import com.sig.todp.server.dto.TTodUtils;
|
|
|
+import com.sig.todp.server.entity.TbCurrTod;
|
|
|
+import com.sig.todp.server.entity.TbCurrTrans;
|
|
|
+import com.sig.todp.server.process.dbms.DbmsDataProcess;
|
|
|
+import com.sig.todp.server.repository.ApplicationRepository;
|
|
|
+import lombok.Getter;
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.slf4j.MDC;
|
|
|
+
|
|
|
+import javax.annotation.PostConstruct;
|
|
|
+import javax.annotation.PreDestroy;
|
|
|
+import java.io.IOException;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Collections;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+@Slf4j
|
|
|
+@Getter
|
|
|
+//@Service
|
|
|
+@RequiredArgsConstructor
|
|
|
+public class SigTodpServiceOld {
|
|
|
+
|
|
|
+ private final ClusterConfig clusterConfig;
|
|
|
+ private final ApplicationRepository repo;
|
|
|
+ private final DbmsDataProcess dbmsDataProcess;
|
|
|
+ private final IntMapper mapper;
|
|
|
+ private final ThreadGroup workerGroup = new ThreadGroup("SigTodp");
|
|
|
+ private final List<Thread> threadList = new ArrayList<>();
|
|
|
+ private final List<SigTodpWorker> workerList = new ArrayList<>();
|
|
|
+
|
|
|
+ @PostConstruct
|
|
|
+ private void init() {
|
|
|
+ log.info("SigTodpService.init: start.");
|
|
|
+ log.info("SigTodpService.init: ..end.");
|
|
|
+ }
|
|
|
+
|
|
|
+ public void loadTodDatabase() {
|
|
|
+ Elapsed elapsed = new Elapsed();
|
|
|
+ log.info("SigTodpService..loadTodDatabase: START.");
|
|
|
+
|
|
|
+ List<String> keySet = new ArrayList<>(this.repo.getCenterMap().keySet());
|
|
|
+ Collections.sort(keySet);
|
|
|
+ for (String key : keySet) {
|
|
|
+ RegionCenter center = this.repo.getCenterMap().get(key);
|
|
|
+ if (center == null) {
|
|
|
+ log.error("SigTodpService.loadTodDatabase: {}, NOT FOUND.", key);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ MDC.put("id", center.getLogKey());
|
|
|
+ try {
|
|
|
+ loadCurrentTrans(center);
|
|
|
+ loadCurrentOpTod(center);
|
|
|
+ }
|
|
|
+ catch (Exception e) {
|
|
|
+ log.error("SigTodpService..loadTodDatabase: Exception, {}, {}", center.getRegionCd(), e.getMessage());
|
|
|
+ }
|
|
|
+ finally {
|
|
|
+ MDC.remove("id");
|
|
|
+ MDC.clear();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ log.info("SigTodpService..loadTodDatabase: ..END.. {}", Elapsed.elapsedTimeStr(elapsed.nanoSeconds()));
|
|
|
+ }
|
|
|
+
|
|
|
+ private void loadCurrentTrans(RegionCenter center) {
|
|
|
+ Elapsed elapsed = new Elapsed();
|
|
|
+ log.info("SigTodpService.loadCurrentTrans: START. {}.", center.getRegionCd());
|
|
|
+ center.getIntMap().forEach((key, dto) -> {
|
|
|
+ dto.useTrans = false;
|
|
|
+ });
|
|
|
+
|
|
|
+ int dual;
|
|
|
+ int aRings = 0;
|
|
|
+ int bRings = 0;
|
|
|
+ int ring;
|
|
|
+ int oldIntNo = -1;
|
|
|
+ TTodInt todInt = null;
|
|
|
+
|
|
|
+ List<TbCurrTrans> list = this.mapper.selectCurrTransAll(center.getRegionCd());
|
|
|
+ for (TbCurrTrans entity : list) {
|
|
|
+ TTodInt dto = center.getIntMap().get(entity.getIntNo());
|
|
|
+ if (dto == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ ring = entity.getRingNo();
|
|
|
+ if (ring != 0 && ring != 1) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ if (entity.getIntNo() != oldIntNo) {
|
|
|
+ // 조회과가 순차적으로 들어있음. 교차로번호가 변경되었음.....
|
|
|
+ updateTodTrans(aRings, bRings, todInt);
|
|
|
+
|
|
|
+ oldIntNo = entity.getIntNo(); // 새로운 교차로를 할당.
|
|
|
+ aRings = bRings = 0;
|
|
|
+
|
|
|
+ todInt = dto;
|
|
|
+
|
|
|
+ todInt.trans.mainPhaseInx = entity.getIntMainPhase(); /* 주현시 인덱스(0..7) */
|
|
|
+ todInt.trans.progressionRing = 0; /* 연동방향, 0=ARING, 1=BRING */
|
|
|
+ todInt.trans.transDir = 1; /* 전이방향(1=POSITIVE,2=NEGATIVE) */
|
|
|
+ todInt.trans.acceptableDelta = 10; /* 전이 없이 주기단순보정 허용 델타값(가급적 큰 것이 좋음. 10초정도까지도) */
|
|
|
+ todInt.trans.maxTransition = 5; /* 허용 가능한 최대 전이주기 수 ==> 최대 5개로 고정 */
|
|
|
+ todInt.trans.keepPreInterval = 1; /* 전이주기 분할 시 선행현시길이고정(주현시 선행현시를 길이 고정) */
|
|
|
+ todInt.trans.minimumOverlap = 3; /* 최소 동시신호 유지시간 */
|
|
|
+ todInt.trans.dual = 0; /* 듀얼 현시운영지정(LSB:1=1현시듀얼) */
|
|
|
+ }
|
|
|
+ if (todInt == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ring == 0) {
|
|
|
+ todInt.trans.minG[ring][aRings] += entity.getMinTm(); /* 최소청시간 */
|
|
|
+ todInt.trans.maxG[ring][aRings] += entity.getMaxTm(); /* 최대청시간 */
|
|
|
+ if (entity.getEop() == 1) {
|
|
|
+ /* EOP 가 1이면 현시가 바뀌는 것이다. */
|
|
|
+ aRings++; /* 현시 수 */
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ /* EOP 가 1이면 현시가 바뀌는 것이다. */
|
|
|
+ todInt.trans.minG[ring][bRings] += entity.getMinTm(); /* 최소청시간 */
|
|
|
+ todInt.trans.maxG[ring][bRings] += entity.getMaxTm(); /* 최대청시간 */
|
|
|
+
|
|
|
+ if (entity.getEop() == 1) {
|
|
|
+ /* EOP 가 1이면 현시가 바뀌는 것이다. */
|
|
|
+ bRings++; /* 현시 수 */
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (Exception e) {
|
|
|
+ log.info("SigTodpService.loadCurrentTrans: Exception. {}. {}. {}", center.getRegionCd(), entity.getIntNo(), e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ updateTodTrans(aRings, bRings, todInt);
|
|
|
+ log.info("SigTodpService.loadCurrentTrans: ..END. {}. {} EA. {}", center.getRegionCd(), list.size(), Elapsed.elapsedTimeStr(elapsed.nanoSeconds()));
|
|
|
+ }
|
|
|
+
|
|
|
+ private void updateTodTrans(int aRings, int bRings, TTodInt todInt) {
|
|
|
+ int dual;
|
|
|
+ if (todInt != null) {
|
|
|
+ // 마지막 교차로 처리
|
|
|
+ dual = 0;
|
|
|
+ for (int phase = 0; phase < TTodUtils.MAX_PHASES; phase++) {
|
|
|
+ if (todInt.trans.minG[0][phase] > 0 && todInt.trans.maxG[0][phase] > 0) {
|
|
|
+ dual |= 0x01 << phase;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ todInt.trans.phaseCnt = Math.max(aRings, bRings);
|
|
|
+ todInt.trans.dual = (byte)(dual & 0xFF);
|
|
|
+ todInt.useTrans = true;
|
|
|
+// log.info("{}, {}", todInt.getIntNo(), todInt.trans);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void loadCurrentOpTod(RegionCenter center) {
|
|
|
+ Elapsed elapsed = new Elapsed();
|
|
|
+ log.info("SigTodpService.loadCurrentOpTod: START. {}.", center.getRegionCd());
|
|
|
+ center.getIntMap().forEach((key, dto) -> {
|
|
|
+ dto.useFlag = false;
|
|
|
+ });
|
|
|
+
|
|
|
+ int idx = 0;
|
|
|
+ List<TbCurrTod> list = this.mapper.selectCurrTodAll(center.getRegionCd());
|
|
|
+ for (TbCurrTod entity : list) {
|
|
|
+ TTodInt dto = center.getIntMap().get(entity.getIntNo());
|
|
|
+ if (dto == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (entity.getIdxNo() <= 0 || entity.getIdxNo() >= TTodUtils.MAX_TOD_PLANS) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ idx = entity.getIdxNo() - 1;
|
|
|
+ dto.plan.itTod[idx].hour = entity.getHour();
|
|
|
+ dto.plan.itTod[idx].minute = entity.getMinute();
|
|
|
+ dto.plan.itTod[idx].cycle = entity.getCycle();
|
|
|
+ dto.plan.itTod[idx].offset = entity.getOffset();
|
|
|
+
|
|
|
+ dto.plan.itTod[idx].split[0][TTodUtils.ARING] = entity.getSplitA1();
|
|
|
+ dto.plan.itTod[idx].split[1][TTodUtils.ARING] = entity.getSplitA2();
|
|
|
+ dto.plan.itTod[idx].split[2][TTodUtils.ARING] = entity.getSplitA3();
|
|
|
+ dto.plan.itTod[idx].split[3][TTodUtils.ARING] = entity.getSplitA4();
|
|
|
+ dto.plan.itTod[idx].split[4][TTodUtils.ARING] = entity.getSplitA5();
|
|
|
+ dto.plan.itTod[idx].split[5][TTodUtils.ARING] = entity.getSplitA6();
|
|
|
+ dto.plan.itTod[idx].split[6][TTodUtils.ARING] = entity.getSplitA7();
|
|
|
+ dto.plan.itTod[idx].split[7][TTodUtils.ARING] = entity.getSplitA8();
|
|
|
+
|
|
|
+ dto.plan.itTod[idx].split[0][TTodUtils.BRING] = entity.getSplitB1();
|
|
|
+ dto.plan.itTod[idx].split[1][TTodUtils.BRING] = entity.getSplitB2();
|
|
|
+ dto.plan.itTod[idx].split[2][TTodUtils.BRING] = entity.getSplitB3();
|
|
|
+ dto.plan.itTod[idx].split[3][TTodUtils.BRING] = entity.getSplitB4();
|
|
|
+ dto.plan.itTod[idx].split[4][TTodUtils.BRING] = entity.getSplitB5();
|
|
|
+ dto.plan.itTod[idx].split[5][TTodUtils.BRING] = entity.getSplitB6();
|
|
|
+ dto.plan.itTod[idx].split[6][TTodUtils.BRING] = entity.getSplitB7();
|
|
|
+ dto.plan.itTod[idx].split[7][TTodUtils.BRING] = entity.getSplitB8();
|
|
|
+ dto.useFlag = true;
|
|
|
+ }
|
|
|
+ catch (Exception e) {
|
|
|
+ log.error("SigTodpService.loadCurrentOpTod: Exception. {}. {}. {}", center.getRegionCd(), entity.getIntNo(), e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ log.info("SigTodpService.loadCurrentOpTod: ..END. {}. {} EA. {}", center.getRegionCd(), list.size(), Elapsed.elapsedTimeStr(elapsed.nanoSeconds()));
|
|
|
+ }
|
|
|
+
|
|
|
+ public void start() {
|
|
|
+ log.info("SigTodpService.start: START.");
|
|
|
+ List<String> keySet = new ArrayList<>(this.repo.getCenterMap().keySet());
|
|
|
+ Collections.sort(keySet);
|
|
|
+ for (String key : keySet) {
|
|
|
+ RegionCenter center = this.repo.getCenterMap().get(key);
|
|
|
+ if (center == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ MDC.put("id", center.getLogKey());
|
|
|
+ try {
|
|
|
+ SigTodpWorker todpWorker = new SigTodpWorker(center, this.dbmsDataProcess, this.clusterConfig);
|
|
|
+ this.workerList.add(todpWorker);
|
|
|
+ Thread worker = new Thread(this.workerGroup, todpWorker);
|
|
|
+ worker.setName(String.format("SigTodp-%s", center.getRegionCd()));
|
|
|
+ worker.setDaemon(true);
|
|
|
+ todpWorker.setThread(worker);
|
|
|
+ this.threadList.add(worker);
|
|
|
+ }
|
|
|
+ catch (IOException e) {
|
|
|
+ log.error("SigTodpService.start: Exception {}, {}", center.getRegionCd(), e.getMessage());
|
|
|
+ }
|
|
|
+ finally {
|
|
|
+ MDC.remove("id");
|
|
|
+ MDC.clear();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for (Thread worker : this.threadList) {
|
|
|
+ worker.start();
|
|
|
+ }
|
|
|
+ log.info("SigTodpService.start: ..END.");
|
|
|
+ }
|
|
|
+
|
|
|
+ public void checkTodpWorkerThread() {
|
|
|
+ for(SigTodpWorker todpWorker : this.workerList) {
|
|
|
+ if (!todpWorker.isRunning()) {
|
|
|
+ Thread worker = new Thread(this.workerGroup, todpWorker);
|
|
|
+ worker.setName(String.format("SigTodp-%s", todpWorker.getCenter().getRegionCd()));
|
|
|
+ worker.setDaemon(true);
|
|
|
+ todpWorker.setThread(worker);
|
|
|
+ worker.start();
|
|
|
+ log.warn("SigTodpService.checkTodpWorkerThread: {}, Thread Restarting.", todpWorker.getCenter().getRegionCd());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @PreDestroy
|
|
|
+ public void onDestroy() throws Exception {
|
|
|
+ log.error("SigTodpService.onDestroy.");
|
|
|
+ for(SigTodpWorker todpWorker : this.workerList) {
|
|
|
+ todpWorker.close();
|
|
|
+ }
|
|
|
+ for(SigTodpWorker todpWorker : this.workerList) {
|
|
|
+ Thread thread = todpWorker.getThread();
|
|
|
+ if (thread != null && thread.isAlive()) {
|
|
|
+ thread.join(1000);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|