package org.ovirt.engine.core.bll;

import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.TimeUnit;

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Singleton;

import org.ovirt.engine.core.common.AuditLogType;
import org.ovirt.engine.core.common.BackendService;
import org.ovirt.engine.core.common.businessentities.EngineBackupLog;
import org.ovirt.engine.core.common.config.Config;
import org.ovirt.engine.core.common.config.ConfigValues;
import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogDirector;
import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogableBase;
import org.ovirt.engine.core.dao.EngineBackupLogDao;
import org.ovirt.engine.core.utils.timer.OnTimerMethodAnnotation;
import org.ovirt.engine.core.utils.timer.SchedulerUtilQuartzImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Responsible for checking that a warm backup is available
 * raise alerts for no backup or too old backup.
 */
@Singleton
public class EngineBackupAwarenessManager implements BackendService {

    @Inject
    private SchedulerUtilQuartzImpl schedulerUtil;

    private enum BackupScope {
        DB("db"),
        FILES("files");

        String name;

        BackupScope(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }
    }

    private static final Logger log = LoggerFactory.getLogger(EngineBackupAwarenessManager.class);
    private volatile boolean active;
    @Inject
    private AuditLogDirector auditLogDirector;
    @Inject
    private EngineBackupLogDao engineBackupLogDao;

    /**
     * Initializes the backup h Check Manager
     */
    @PostConstruct
    private void initialize() {
        log.info("Start initializing {}", getClass().getSimpleName());
        Integer backupCheckPeriodInHours = Config.<Integer>getValue(ConfigValues.BackupCheckPeriodInHours);
        // disable feature if value is negative
        if (backupCheckPeriodInHours > 0) {
            schedulerUtil.scheduleAFixedDelayJob(this,
                    "backupCheck",
                    new Class[] {},
                    new Object[] {},
                    backupCheckPeriodInHours,
                    backupCheckPeriodInHours,
                    TimeUnit.HOURS);
            log.info("Finished initializing {}", getClass().getSimpleName());
        }
    }

    @OnTimerMethodAnnotation("backupCheck")
    public void backupCheck() {
        // skip backup check if previous operation is not completed yet
        if (!active) {
            try {
                synchronized (this) {
                    log.info("Backup check started.");
                    active = true;
                    doBackupCheck();
                    log.info("Backup check completed.");
                }
            } finally {
                active = false;
            }
        }
    }

    private void doBackupCheck() {
        AuditLogableBase alert = new AuditLogableBase();

        //try to get last backup record
        EngineBackupLog lastDbBackup = getLastBackupByScope(BackupScope.DB);
        EngineBackupLog lastFilesBackup = getLastBackupByScope(BackupScope.FILES);
        if (lastDbBackup == null || lastFilesBackup == null) {
            auditLogDirector.log(alert, AuditLogType.ENGINE_NO_FULL_BACKUP);
        } else {
            //check time elapsed from last full (db and files) backup
            Integer backupAlertPeriodInDays = Config.<Integer>getValue(ConfigValues.BackupAlertPeriodInDays);
            Date lastDbBackupDate = lastDbBackup.getDoneAt();
            Date lastFilesBackupDate = lastFilesBackup.getDoneAt();
            Date lastFullBackupDate = lastDbBackupDate.compareTo(lastFilesBackupDate) < 0
                    ? lastDbBackupDate
                    : lastFilesBackupDate;
            long diffInDays = (Calendar.getInstance().getTimeInMillis() - lastFullBackupDate.getTime())
                              / TimeUnit.DAYS.toMillis(1);
            if (diffInDays > backupAlertPeriodInDays) {
                alert.addCustomValue("Date", lastFullBackupDate.toString());
                auditLogDirector.log(alert, AuditLogType.ENGINE_NO_WARM_BACKUP);
            }
        }

    }

    private EngineBackupLog getLastBackupByScope(BackupScope scope) {
        return engineBackupLogDao.getLastSuccessfulEngineBackup(scope.getName());
    }
}

@@ -116,16 +116,105 @@
 imeUnit;
+%0Aimport java.util.concurrent.locks.Lock;%0Aimport java.util.concurrent.locks.ReentrantLock;
 %0A%0Aimport
@@ -1609,31 +1609,39 @@
 ate 
-volatile boolean active
+Lock lock = new ReentrantLock()
 ;%0A  
@@ -2696,15 +2696,22 @@
 if (
-!active
+lock.tryLock()
 ) %7B%0A
@@ -2732,50 +2732,8 @@
 y %7B%0A
-                synchronized (this) %7B%0A    
     
@@ -2783,47 +2783,8 @@
 %22);%0A
-                    active = true;%0A    
     
@@ -2808,28 +2808,24 @@
 kupCheck();%0A
-    
             
@@ -2869,26 +2869,8 @@
 %22);%0A
-                %7D%0A
     
@@ -2909,22 +2909,21 @@
     
-active = false
+lock.unlock()
 ;%0A  

resolve Coverityy issue 1294817