解读代码:private void generatePushTask() throws InterruptedException, ExecutionException {
Latency latency = MetricManager.INSTANCE.getOrRegisterLatency("stat.task.fw.generate", statsDuration);
long start = System.nanoTime();
oaTaskLogger.info("#### scan and generate PushAppTask/PushDeviceTask Task ...");
// Regular fw, single thread for now
Map<MatchCondition, TaskHandler<DeviceFwInfo>> regularFwTaskMap = new HashMap<>();
// Smb device firmwares, single thread for now
Map<MatchCondition, TaskHandler<DeviceFwInfo>> smbFwTaskMap = new HashMap<>();
// FAP device firmwares, single thread for now
Map<MatchCondition, TaskHandler<DeviceFwInfo>> FAPFwTaskMap = new HashMap<>();
//dst zoneId:DstRulePushTask, single thread for now
Map<String, TaskHandler<DeviceConfigInfo>> dstRulePushTaskMap = new HashMap<>();
//signature, single thread for now
Map<SigMatchCondition, TaskHandler<DeviceInfo>> m5SignaturePushTaskMap = new HashMap<>();
//由于是底层数据源是mysql,返回结果默认按照主键task_id升序排列,因此list中oa_task_id由小到大,for遍历时task_id大的任务也
//加入在fwHandlerList的后面,在遍历fwHandlerList时,task_id较大的任务较后处理,在updatePushTaskStatus时可以将前面task_id
//较小的任务生成的push_device_task失效掉,保证读取到的任务中最后发布的被推送
//添加排序,保证taskList内部task按照task_id升序排列
List<FwReleaseTask> fwReleaseList = new ArrayList<>();
if (IS_FW_TASK_ENABLED) { //smb设备、正式固件(FAP推送、一般设备推送)
fwReleaseList = pushDAO.findFwTaskInRDB(TaskStatusCode.READY, CURRENT_REGION, "N");
}
//过滤下架任务
//BugFix:修复使用arrayList.remove造成的ConcurrentModificationException
Iterator<FwReleaseTask> iterator = fwReleaseList.iterator();
FwReleaseTask fwReleaseTask;
while (iterator.hasNext()) {
fwReleaseTask = iterator.next();
if(ONSHELF_OFF.equalsIgnoreCase(fwReleaseTask.getOnShelf())){
iterator.remove();
}
}
Collections.sort(fwReleaseList);
//目前eap设备暂无beta固件推送
for (FwReleaseTask task : fwReleaseList) {
//将where为空的任务置为失效
if (Objects.equals(task.getWhere(), "[]")) {
task.setStatusCode(TaskStatusCode.DISABLE);
logger.warn("disable meaningless fw_release_task,task={}", task);
pushDAO.saveOrUpdateInRDB(task);
latency.record(System.nanoTime() - start, ErrorCause.BIZ);
continue;
}
try {
if (eapDeviceList.contains(task.getDeviceCategory())) {//EAP设备
oaTaskLogger.info("[generate] load fw_release_task for eap device,[task={}]", task);
FwReleaseTaskHandler handler = new FwReleaseTaskHandler(task, pushDAO, authService,
isPushEapAppEnabled, statsDuration, appFwFilterMap, oaQueue, true, vigiEnabled, batchSender, senderMap,
grpcClient, databaseSwitch, deviceUserService);
PushUtil.generateTaskMapByStr(smbFwTaskMap, task.getWhere(), handler, CURRENT_REGION);
} else if (apDeviceList.contains(task.getDeviceCategory())) {//AP设备,需要给订阅ap设备的主设备发送推送
oaTaskLogger.info("[generate] load fw_release_task for ap device,[task={}]", task);
FwReleaseFAPDeviceTaskHandler fapHandler =
new FwReleaseFAPDeviceTaskHandler(task, pushDAO, authService, statsDuration, batchSender);
PushUtil.generateTaskMapByStr(FAPFwTaskMap, task.getWhere(), fapHandler, CURRENT_REGION);
oaTaskLogger.info("[generate] load fw_release_task for regular device,[task={}]", task);
FwReleaseTaskHandler handler = new FwReleaseTaskHandler(task, pushDAO, authService, true,
statsDuration, appFwFilterMap, oaQueue, true, vigiEnabled, batchSender, senderMap,
grpcClient, databaseSwitch, deviceUserService);
PushUtil.generateTaskMapByStr(regularFwTaskMap, task.getWhere(), handler, CURRENT_REGION);
} else {//一般设备
oaTaskLogger.info("[generate] load fw_release_task for regular device,[task={}]", task);
FwReleaseTaskHandler handler = new FwReleaseTaskHandler(task, pushDAO, authService, true,
statsDuration, appFwFilterMap, oaQueue, true, vigiEnabled, batchSender, senderMap,
grpcClient, databaseSwitch, deviceUserService);
PushUtil.generateTaskMapByStr(regularFwTaskMap, task.getWhere(), handler, CURRENT_REGION);
}
latency.recordSuccess(System.nanoTime() - start);
} catch (Exception e) {
task.setStatusCode(TaskStatusCode.DISABLE);
pushDAO.saveOrUpdateInRDB(task);
latency.record(System.nanoTime() - start, ErrorCause.BIZ);
logger.error("fw_release_task ERROR:task illegal,task={}", task, e);
}
}
// 删除对应hardwareId, oemId的首次上线推送的缓存
if (regularFwTaskMap.size() > 0) {
regularFwTaskMap.keySet().forEach(matchCondition -> pushDAO
.delFwTaskCache(matchCondition.getHardwareId(), matchCondition.getOemId(), false));
}
if (FAPFwTaskMap.size() > 0) {
FAPFwTaskMap.keySet().forEach(matchCondition -> pushDAO
.delFwTaskCache(matchCondition.getHardwareId(), matchCondition.getOemId(), false));
}
if (smbFwTaskMap.size() > 0) {
smbFwTaskMap.keySet().forEach(matchCondition -> pushDAO
.delFwTaskCache(matchCondition.getHardwareId(), matchCondition.getOemId(), false));
}
// dst
//添加排序,保证taskList内部task按照task_id升序排列
List<DstRulePushTask> dstTaskList = new ArrayList<>();
if (IS_DST_TASK_ENABLED) { //dst任务
dstTaskList = pushDAO.findOATaskByStatusInRDB(DstRulePushTask.class, TaskStatusCode.READY, CURRENT_REGION);
}
Collections.sort(dstTaskList);
for (DstRulePushTask task : dstTaskList) {
DstRulePushTaskHandler handler = new DstRulePushTaskHandler(task, pushDAO, statsDuration, dstQueue, batchSender);
oaTaskLogger.info("[generate] load DST release task,[task={}]", task);
dstRulePushTaskMap.put(task.getZoneId(), handler);
}
// signature
List<M5SignaturePushTask> m5SigTaskList = new ArrayList<>();
if (IS_M5_TASK_ENABLED) {//m5任务
m5SigTaskList = pushDAO.findOATaskByStatusInRDB(M5SignaturePushTask.class, TaskStatusCode.READY, CURRENT_REGION);
}
Collections.sort(m5SigTaskList);
for (M5SignaturePushTask task : m5SigTaskList) {
List<SignatureSuitableModel> ssms = pushDAO.getSignatureSuitableModels(task.getSigVersion());
JSONArray whereJson = new JSONArray();
if (ssms != null) {
for (SignatureSuitableModel ssmInfo : ssms) {
JSONObject obj = new JSONObject();
obj.put(Constants.FIRMWARE_VERSION, ssmInfo.getFirmwareVersion());
obj.put(Constants.HARDWARE_ID, ssmInfo.getHwId());
obj.put(Constants.OEM_ID, ssmInfo.getOemId());
whereJson.put(obj);
}
} else {
logger.info("Signature Version={} has no upgrade relationship", task.getSigVersion());
continue;
}
M5SignaturePushTaskHandler handler = new M5SignaturePushTaskHandler(task, pushDAO, statsDuration, oaQueue);
oaTaskLogger.info("[generate] load signature release task,[task={}]", task);
if (whereJson.length() > 0) {
PushUtil.generateSigTaskMapByJson(m5SignaturePushTaskMap, whereJson, handler, CURRENT_REGION);
}
}
// first check whether loop is necessary, then generate push task
// 1. loop devices
if (regularFwTaskMap.size() + m5SignaturePushTaskMap.size() != 0) {
logger.info("begin loop devices for regular fw and M5 sig, fwMap={}, m5Map={}", regularFwTaskMap,
m5SignaturePushTaskMap);
long step1 = MAX_TOKEN / SPLIT_SIZE;
long step2 = MIN_TOKEN / SPLIT_SIZE;
long step = step1 - step2;
long totalDeviceNum = 0;
long index = 0;
int mapSize = (int) (0.2 * EXECUTOR_QUEUE_SIZE);
logger.info("start split and handle devices,[min={},max={},size={},step={},mapSize={}]",
MIN_TOKEN, MAX_TOKEN, SPLIT_SIZE, step, mapSize);
Map<Long, Future<Long>> futureMap = new HashMap<>();
while (index < SPLIT_SIZE) {
Thread.sleep(TASK_SLEEP_MS);
if (futureMap.size() < mapSize) {
//TODO:一次添加多个
long lower = MIN_TOKEN + index * step;
long upper;
if (index == SPLIT_SIZE - 1) {
upper = MAX_TOKEN;
} else {
upper = lower + step > MAX_TOKEN ? MAX_TOKEN : lower + step;
}
logger.info("add new period to execute,[index={},lower={},upper={}]", index, lower, upper);
Future<Long> future = executor.submit(() -> {
long deviceCount = 0;
int retry = 0;
while (retry < FW_TASK_RETRY_LIMIT) {
if (retry > 0) {
Thread.sleep((long) Math.pow(2, retry) * 1000);
}
try {
deviceCount = handleDeviceTask(lower, upper, regularFwTaskMap, m5SignaturePushTaskMap);
break;
} catch (Exception e) {
logger.error("handle device task error,[lower={},upper={},retry={}]",
lower, upper, retry, e);
retry = retry + 1;
}
}
if (retry >= FW_TASK_RETRY_LIMIT) {
logger.error("failed to handle device task,[lower={},upper={},retry={}]",
lower, upper, retry);
} else {
logger.info("success handle device task,[lower={},upper={},retry={}]",
lower, upper, retry);
}
return deviceCount;
});
futureMap.put(index, future);
logger.info("add future to map,[index={},map={}]", index, futureMap);
index = index + 1;
}
Iterator<Long> futureInterator = futureMap.keySet().iterator();
while (futureInterator.hasNext()) {
Long key = futureInterator.next();
Future<Long> future = futureMap.get(key);
if (future.isDone()) {
futureInterator.remove();
long count = future.get();
totalDeviceNum = totalDeviceNum + count;
logger.info("work done,[index={},count={},total={}]", key, count, totalDeviceNum);
}
}
}
while (!futureMap.isEmpty()) {
//noinspection BusyWait
Thread.sleep(TASK_SLEEP_MS);
Iterator<Long> futureInterator = futureMap.keySet().iterator();
while (futureInterator.hasNext()) {
Long key = futureInterator.next();
Future<Long> future = futureMap.get(key);
if (future.isDone()) {
futureInterator.remove();
long count = future.get();
totalDeviceNum = totalDeviceNum + count;
logger.info("work done,[index={},count={},total={}]", key, count, totalDeviceNum);
}
}
}
logger.info("end split and handle devices,totalDeviceNum={},deviceNotifyNum={},appNotifyNum={}",
totalDeviceNum, totalDeviceSet.size(), totalAppSet.size());
totalAppSet.clear();
totalDeviceSet.clear();
}
// 2. loop device_config
try {
if (dstRulePushTaskMap.size() != 0) {
logger.info("begin loop deviceConfigInfos for dst task, dstTaskMap={}", dstRulePushTaskMap);
Iterable<DeviceConfigInfo> deviceConfigInfos = pushDAO.getAllDeviceConfigInfo();
//数据分区隔离开关
if (DATA_BASE_PARTITION_ENABLED) {
for (DeviceConfigInfo deviceConfigInfo : deviceConfigInfos) {
if ((dstRulePushTaskMap.get(deviceConfigInfo.getZoneId()) != null)) {
//打开设备区域检查开关后,调用grpc接口判断本区是否为设备的存储区,并统计通过storage区域检查的设备数量
if (NEED_CHECK_DEVICE_STORAGE_REGION) {
DeviceRegionInfoList deviceRegionInfo = grpcClient
.getDeviceRegionInfo(deviceConfigInfo.getDeviceId());
if (Objects.isNull(deviceRegionInfo)) {
continue;
}
String connectRegion = deviceRegionInfo.getConnectRegion();
String storageRegion = deviceRegionInfo.getStorageRegion();
if (CURRENT_REGION.equals(storageRegion)) {
MetricManager.INSTANCE.getOrRegisterCounter(
Constants.ALL_STAT_DST_RULE_TASK_DEVICE_REGION_MATCH).inc();
dstRulePushTaskMap.get(deviceConfigInfo.getZoneId())
.handle(deviceConfigInfo, pushDeviceTaskMap, null, null, null, connectRegion);
} else {
MetricManager.INSTANCE.getOrRegisterCounter(
Constants.ALL_STAT_DST_RULE_TASK_DEVICE_REGION_MATCH_ERROR).inc();
}
} else {
dstRulePushTaskMap.get(deviceConfigInfo.getZoneId())
.handle(deviceConfigInfo, pushDeviceTaskMap, null, null, null, null);
}
}
}
} else {
for (DeviceConfigInfo deviceConfigInfo : deviceConfigInfos) {
if (dstRulePushTaskMap.get(deviceConfigInfo.getZoneId()) != null) {
dstRulePushTaskMap.get(deviceConfigInfo.getZoneId())
.handle(deviceConfigInfo, pushDeviceTaskMap, null, null, null, null);
}
}
}
}
} catch (Exception e) {
logger.error("loop device_config failed", e);
dstRulePushTaskMap.clear();
}
// 3. loop eap devices
if (smbFwTaskMap.size() != 0) {
logger.info("begin loop eapDevices for eapFwtasks, taskMap={}", smbFwTaskMap);
Iterable<EapDeviceInfo> eapDevices = pushDAO.getAllEapDeviceInfo();
//数据分区隔离开关
if (DATA_BASE_PARTITION_ENABLED) {
for (EapDeviceInfo eapDeviceInfo : eapDevices) {
if ((smbFwTaskMap.get(eapDeviceInfo.toMatchConditionLocalRegion(CURRENT_REGION)) != null)) {
//打开设备区域检查开关后,调用grpc接口判断本区是否为设备的存储区,并统计通过storage区域检查的设备数量
if (NEED_CHECK_DEVICE_STORAGE_REGION) {
DeviceRegionInfoList deviceRegionInfo = grpcClient
.getDeviceRegionInfo(eapDeviceInfo.getDeviceId());
if (Objects.isNull(deviceRegionInfo)) {
continue;
}
String connectRegion = deviceRegionInfo.getConnectRegion();
String storageRegion = deviceRegionInfo.getStorageRegion();
if (CURRENT_REGION.equals(storageRegion)) {
MetricManager.INSTANCE.getOrRegisterCounter(
Constants.ALL_STAT_SMB_FW_TASK_DEVICE_REGION_MATCH).inc();
smbFwTaskMap.get(eapDeviceInfo.toMatchConditionLocalRegion(CURRENT_REGION))
.handle(eapDeviceInfo.toDeviceFwInfo(), pushDeviceTaskMap, pushAppTaskMap, totalSMBDeviceSet, totalSMBAppSet, connectRegion);
} else {
MetricManager.INSTANCE.getOrRegisterCounter(
Constants.ALL_STAT_SMB_FW_TASK_DEVICE_REGION_MATCH_ERROR).inc();
}
} else {
smbFwTaskMap.get(eapDeviceInfo.toMatchConditionLocalRegion(CURRENT_REGION))
.handle(eapDeviceInfo.toDeviceFwInfo(), pushDeviceTaskMap, pushAppTaskMap, totalSMBDeviceSet, totalSMBAppSet, null);
}
}
}
} else {
//原逻辑,保留便于回滚
for (EapDeviceInfo eapDeviceInfo : eapDevices) {
if (smbFwTaskMap.get(eapDeviceInfo.toMatchCondition()) != null) {
smbFwTaskMap.get(eapDeviceInfo.toMatchCondition())
.handle(eapDeviceInfo.toDeviceFwInfo(), pushDeviceTaskMap, pushAppTaskMap, totalSMBDeviceSet, totalSMBAppSet, null);
}
}
}
logger.info("begin loop eapDevices for eap tasks, deviceNum={}, appNum={}, taskMap={}",
totalSMBDeviceSet.size(), totalSMBAppSet.size(), smbFwTaskMap);
}
totalSMBDeviceSet.clear();
totalSMBAppSet.clear();
//4. loop ap devices(using PushSubscriptionDevice)
if (FAPFwTaskMap.size() != 0) {
logger.info("begin loop apDevices for FAPFwtasks, taskMap={}", FAPFwTaskMap);
Iterable<PushSubscriptionDevice> pushSubscriptionDevices = pushDAO.getAllPushSubscriptionDevice();
//数据分区隔离开关
if (DATA_BASE_PARTITION_ENABLED) {
//调用grpc接口判断本区是否为设备的存储区
for (PushSubscriptionDevice subscriptionDevice : pushSubscriptionDevices) {
if ((FAPFwTaskMap.get(subscriptionDevice.toMatchConditionLocalRegion(CURRENT_REGION)) != null)) {
//调用grpc接口判断本区是否为设备的存储区,并统计通过storage区域检查的设备数量
Latency latencyCheckDevice = MetricManager.INSTANCE.getOrRegisterLatency(
"stat.generate_task_fap_fw_task_check_device_storage_region",
statsDuration);
DeviceRegionInfoList deviceRegionInfo = grpcClient
.getDeviceRegionInfo(subscriptionDevice.getSubscriber());
if (Objects.isNull(deviceRegionInfo)) {
continue;
}
String connectRegion = deviceRegionInfo.getConnectRegion();
String storageRegion = deviceRegionInfo.getStorageRegion();
if (CURRENT_REGION.equals(storageRegion)) {
MetricManager.INSTANCE.getOrRegisterCounter(
Constants.ALL_STAT_FAP_FW_TASK_DEVICE_REGION_MATCH).inc();
FAPFwTaskMap.get(subscriptionDevice.toMatchConditionLocalRegion(CURRENT_REGION))
.handle(subscriptionDevice.toDeviceFwInfo(), FAPDeviceTaskMap, null, totalEAPDeviceSet, null,
connectRegion);
} else {
MetricManager.INSTANCE.getOrRegisterCounter(
Constants.ALL_STAT_FAP_FW_TASK_DEVICE_REGION_MATCH_ERROR).inc();
}
}
}
} else {
//原逻辑,保留便于回滚
for (PushSubscriptionDevice subscriptionDevice : pushSubscriptionDevices) {
if (FAPFwTaskMap.get(subscriptionDevice.toMatchCondition()) != null) {
FAPFwTaskMap.get(subscriptionDevice.toMatchCondition())
.handle(subscriptionDevice.toDeviceFwInfo(), FAPDeviceTaskMap, null, totalEAPDeviceSet, null, null);
}
}
}
logger.info("end loop apDevices for FAP task, num={}, taskMap={}", totalEAPDeviceSet.size(), FAPFwTaskMap);
}
totalEAPDeviceSet.clear();
@SuppressWarnings("unchecked")
Iterable<TaskHandler<?>> handlers = Iterables.concat(regularFwTaskMap.values(), m5SignaturePushTaskMap.values(),
dstRulePushTaskMap.values(), smbFwTaskMap.values(), FAPFwTaskMap.values());
for (TaskHandler<?> handler : handlers) {
handler.setHandling();
handlingList.add(handler);
}
regularFwTaskMap.clear();
m5SignaturePushTaskMap.clear();
dstRulePushTaskMap.clear();
smbFwTaskMap.clear();
FAPFwTaskMap.clear();
oaTaskLogger.info("[generate] add handling task.[handlingTask={}]", handlingList.toString());
handlingList.clear();
oaTaskLogger.info("[generate] generate push device task amount={}", pushDeviceTaskMap.size() + FAPDeviceTaskMap.size());
oaTaskLogger.info("[generate] generate push app task amount={}", pushAppTaskMap.size());
}
最新发布