package com.its.bis.service; import com.its.app.utils.Elapsed; import com.its.bis.api.dto.AgipObeLoc; import com.its.bis.config.ServerConfig; import com.its.bis.config.ThreadPoolInitializer; import com.its.bis.dto.Location; import com.its.bis.dto.NearNodeDto; import com.its.bis.dto.TbLinkDto; import com.its.bis.dto.TbNodeDto; import com.its.bis.process.DbmsDataProcess; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.slf4j.MDC; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.PostConstruct; import java.util.ArrayList; import java.util.List; import java.util.Map; @Slf4j @Service @RequiredArgsConstructor @Transactional(rollbackFor = {Exception.class}) public class BisAgipService { private final AppRepositoryService repoService; private final ServerConfig config; private final DbmsDataProcess dbmsDataProcess; private final ThreadPoolInitializer threadPoolInitializer; private final List threadList = new ArrayList(); private final List workerList = new ArrayList(); private final ThreadGroup workerGroup = new ThreadGroup("BisAgipService"); private int workers; @PostConstruct private void init() { log.info("BisAgipService.init: Start."); this.workers = this.threadPoolInitializer.getDbms(); if (this.workers <= 0) this.workers = 10; int qSize = 100; for (int ii = 0; ii < this.workers; ii++) { BisAgipWorker packetWorker = new BisAgipWorker(ii, qSize, this.config, this.repoService, this.dbmsDataProcess); this.workerList.add(packetWorker); Thread worker = new Thread(workerGroup, packetWorker); worker.setName(String.format("BisAgipService-%02d.%02d", this.workers, ii+1)); worker.setDaemon(true); this.threadList.add(worker); } for (Thread worker : this.threadList) { worker.start(); } log.info("BisAgipService.init: ..End."); } /** * REST API 로 수신한 위치정보를 작업큐에 입력 * @param obeLoc * @return */ public boolean add(AgipObeLoc obeLoc) { boolean offer = false; String deviceId = obeLoc.getDeviceId(); if (deviceId == null || deviceId.equals("")) { deviceId = "xxx"; obeLoc.setDeviceId(deviceId); } try { int idx = Math.abs(deviceId.hashCode() % this.workers); offer = this.workerList.get(idx).add(obeLoc); } catch (Exception e) { MDC.put("id", deviceId); log.error("QUEUE_DATA.add: Exception: {}, {}, {}", deviceId, obeLoc, e.getMessage()); MDC.clear(); } return offer; } public void report() { for (BisAgipWorker worker : this.workerList) { worker.report(); } } public double getDistance(double lat1, double lon1, double lat2, double lon2) { double EARTH_RADIUS = 6371.0; double dLat = Math.toRadians(lat2 - lat1); double dLon = Math.toRadians(lon2 - lon1); double a = Math.sin(dLat/2)* Math.sin(dLat/2)+ Math.cos(Math.toRadians(lat1))* Math.cos(Math.toRadians(lat2))* Math.sin(dLon/2)* Math.sin(dLon/2); double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); return (EARTH_RADIUS * c * 1000); // Distance in m } public NearNodeDto getNearNode(Location loc) { Elapsed elapsed = new Elapsed(); log.info("getNearNode: {}", loc); //Location(mDistance=0.0, mInitialBearing=0.0, mFinalBearing=0.0, mLatitude=128.73881251, mLongitude=36.56128759) double maxDistance = 40; NearNodeDto node = NearNodeDto.builder().nodeId(0L).distance(maxDistance).build(); for (Map.Entry e : this.repoService.getEntrySetNode()) { TbNodeDto obj = e.getValue(); double fDistance = (float) getDistance(loc.getMLatitude(), loc.getMLongitude(), obj.getXCrdn(), obj.getYCrdn()); if (fDistance < maxDistance) { maxDistance = fDistance; node.setNodeId(obj.getNodeId()); node.setDistance(fDistance); } } log.info("getNearNode: {} ms. {} m, {}", elapsed.milliSeconds(), maxDistance, node); return node; } public TbLinkDto getSectInfo(Long fNodeId, Long tNodeId) { return this.repoService.getSectMap(fNodeId, tNodeId); } }