/*
* Copyright (c) 2008-2015 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.systemservices.impl.jobs.consumer;
import java.util.concurrent.CancellationException;
import java.util.concurrent.atomic.AtomicBoolean;
import com.emc.storageos.systemservices.impl.jobs.DbConsistencyJob;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.emc.storageos.coordinator.client.model.DbConsistencyStatus;
import com.emc.storageos.coordinator.client.service.CoordinatorClient;
import com.emc.storageos.coordinator.client.service.DistributedQueueItemProcessedCallback;
import com.emc.storageos.coordinator.client.service.impl.DistributedQueueConsumer;
import com.emc.storageos.db.client.impl.DbConsistencyChecker;
import com.emc.storageos.db.common.DbSchemaChecker;
import com.emc.storageos.model.db.DbConsistencyStatusRestRep.Status;
import com.netflix.astyanax.connectionpool.exceptions.ConnectionException;
public class DbConsistencyJobConsumer extends DistributedQueueConsumer<DbConsistencyJob> {
private static final Logger log = LoggerFactory.getLogger(DbConsistencyJobConsumer.class);
private CoordinatorClient coordinator;
private DbConsistencyChecker dbChecker;
private static final String[] MODEL_PACKAGES = new String[] { "com.emc.storageos.db.client.model" };
private static final AtomicBoolean schemaInitialized = new AtomicBoolean(false);
@Override
public void consumeItem(DbConsistencyJob job, DistributedQueueItemProcessedCallback callback) throws Exception {
DbConsistencyStatus status = dbChecker.getStatusFromZk();
log.info("start db consistency check, current status:{}", status);
if (isFreshStart(status)) {
log.info("it's first time to run db consistency check, init status in zk");
status = createStatusInZk();
} else if (status.isFinished()) {
log.info("there is finished state, move it to previous");
status.moveToPrevious();
} else if (status.isCancelled()) {
log.info("current status is cancel, restart db consistency check");
status.init();
}
try {
dbChecker.persistStatus(status);
initSchemaIfNot();
dbChecker.check();
status = markResult();
} catch (CancellationException ce) {
log.warn("cancellation:{}", ce.getMessage());
status.markResult(Status.CANCEL);
} catch (ConnectionException e) {
log.warn("ConnectionException:{}", e);
status.markResult(Status.FAILED);
} catch (Exception e) {
log.error("failed to check db consistency {}", e);
status = markFailure();
} finally {
log.info("db consistency check done, persist final result {} in zk", status.getStatus());
this.dbChecker.persistStatus(status);
callback.itemProcessed();
}
}
private void initSchemaIfNot() throws Exception {
if (!schemaInitialized.get()) {
log.info("init Data Object Type");
DbSchemaChecker.checkSourceSchema(MODEL_PACKAGES);
schemaInitialized.getAndSet(true);
}
}
private DbConsistencyStatus markFailure() {
DbConsistencyStatus status = this.dbChecker.getStatusFromZk();
status.markResult(Status.FAILED);
return status;
}
private DbConsistencyStatus markResult() {
DbConsistencyStatus status = dbChecker.getStatusFromZk();
if (status.getInconsistencyCount() > 0) {
log.info("there are {} inconsistency found, mark result as fail", status.getInconsistencyCount());
status.markResult(Status.FAILED);
} else {
log.info("no inconsistency record found, mark result as successful");
status.markResult(Status.SUCCESS);
}
return status;
}
private DbConsistencyStatus createStatusInZk() {
DbConsistencyStatus status = new DbConsistencyStatus();
status.init();
return status;
}
private boolean isFreshStart(DbConsistencyStatus status) {
return status == null;
}
public CoordinatorClient getCoordinator() {
return coordinator;
}
public void setCoordinator(CoordinatorClient coordinator) {
this.coordinator = coordinator;
}
public DbConsistencyChecker getDbChecker() {
return dbChecker;
}
public void setDbChecker(DbConsistencyChecker dbChecker) {
this.dbChecker = dbChecker;
}
}