/**
* personium.io
* Copyright 2014 FUJITSU LIMITED
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fujitsu.dc.core.webcontainer.listener;
import java.io.File;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fujitsu.dc.common.ads.AdsWriteFailureLogException;
import com.fujitsu.dc.common.ads.AdsWriteFailureLogWriter;
import com.fujitsu.dc.core.DcCoreConfig;
import com.fujitsu.dc.core.model.impl.es.repair.RepairAds;
/**
* Ads書き込み失敗内容をリペアするServiceの定期実行を起動するユーティリティクラス.
*/
public class RepairServiceLauncher {
private static Logger logger = LoggerFactory.getLogger(RepairServiceLauncher.class);
/**
* Adsのリペア処理を行うクラス.
*/
public static class RepairAdsService implements Runnable {
/**
* RepairAdsを起動するか否かを判定するファイルのパス.
*/
String invocationFlagFile = DcCoreConfig.getRepairAdsInvocationFilePath();
@Override
public void run() {
try {
AdsWriteFailureLogWriter adsWriteFailureLogWriter = AdsWriteFailureLogWriter.getInstance(
DcCoreConfig.getAdsWriteFailureLogDir(),
DcCoreConfig.getCoreVersion(),
DcCoreConfig.getAdsWriteFailureLogPhysicalDelete());
// 現在出力中のジャーナルログファイルのローテート。
adsWriteFailureLogWriter.rotateActiveFile();
} catch (AdsWriteFailureLogException e) {
logger.warn("Faield to rotate ads failure log file.");
return;
}
// Adsリペア処理実行の有無チェック.
logger.debug("Checking invocation flag for RepairAds.");
if (shouldInvoke()) {
logger.debug("Invocation flag for RepairAds exists. Invoking RepairAds.");
// Adsリペア処理の実行.
try {
RepairAds.getInstance().repairAds();
} catch (Throwable t) {
// 例外を飛ばすとそれ以降のスケジュールが無効になるため、外部には飛ばさない。
// warnレベルでログを出力したいが、定期的にアラートメールが飛ぶのを防ぐため、infoレベルで出力.
logger.info("Ads repair process reported an error.", t);
}
} else {
logger.debug("No invocation flag for RepairAds. Invocation cancelled.");
}
}
/**
* 特定ファイルの存在有無で、リペア処理の実行必要性の有無を判断する.
* @return true: 実行が指示されている false: 実行しないように指示されている
*/
public boolean shouldInvoke() {
File flagFile = new File(invocationFlagFile);
return flagFile.exists() && flagFile.isFile();
}
}
ScheduledThreadPoolExecutor executor;
/**
* コンストラクタ. Webコンテナ起動時に呼ばれる。
*/
public RepairServiceLauncher() {
// 同時起動はしないため、Threadは1つ.
executor = new ScheduledThreadPoolExecutor(1);
executor.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
// リペアツールの実行をスケジュールする.
RepairAdsService service = new RepairAdsService();
executor.scheduleWithFixedDelay(service,
DcCoreConfig.getAdsRepairInitialDelayInSec(),
DcCoreConfig.getAdsRepairIntervalInSec(),
TimeUnit.SECONDS);
logger.info(String.format("RepairAds scheduled with delay interval %d sec.",
DcCoreConfig.getAdsRepairIntervalInSec()));
}
/**
* Webコンテナ終了時に呼ばれるメソッド.
*/
public void shutdown() {
if (null != executor && !executor.isTerminated()) {
logger.info("Shutting down RepairAds scheduler.");
executor.shutdown();
try {
long awaitShutdownInSec = DcCoreConfig.getAdsRepairAwaitShutdownInSec();
logger.info(String.format("Waiting RepairAds termination up to %d sec.", awaitShutdownInSec));
if (executor.awaitTermination(awaitShutdownInSec, TimeUnit.SECONDS)) {
logger.info("Completed shutting down RepairAds scheduler.");
} else {
logger.warn("Shutting down timed out. RepairAds scheduler have not been terminated.");
executor.shutdownNow();
}
} catch (InterruptedException e) {
executor.shutdownNow();
}
}
}
}