/*
* Copyright (c) 2016 EMC Corporation
* All Rights Reserved
*/
package com.emc.sa.api.utils;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.emc.storageos.coordinator.client.service.DistributedQueueItemProcessedCallback;
import com.emc.storageos.coordinator.client.service.impl.DistributedQueueConsumer;
import com.emc.storageos.db.client.DbClient;
import com.emc.storageos.db.client.constraint.NamedElementQueryResultList;
import com.emc.storageos.db.client.constraint.TimeSeriesConstraint;
import com.emc.storageos.db.client.model.uimodels.Order;
import com.emc.storageos.db.client.model.uimodels.OrderStatus;
import com.emc.storageos.security.audit.AuditLogManager;
import com.emc.storageos.svcs.errorhandling.resources.BadRequestException;
import com.emc.sa.api.OrderService;
import com.emc.sa.catalog.OrderManager;
public class OrderServiceJobConsumer extends DistributedQueueConsumer<OrderServiceJob> {
private final Logger log = LoggerFactory.getLogger(OrderServiceJobConsumer.class);
public static final long CHECK_INTERVAL = 1000*60*10L;
private static final long NUMBER_PER_RECORD = 1000L;
DbClient dbClient;
OrderManager orderManager;
OrderService orderService;
private long maxOrderDeletedPerGC;
public OrderServiceJobConsumer(OrderService service, DbClient client, OrderManager manager, long max) {
dbClient = client;
orderManager = manager;
orderService = service;
maxOrderDeletedPerGC = max;
}
/**
* @param job The object provisioning job which is being worked on. This could be either creation or deletion job
* @param callback This must be executed, after the item is processed successfully to remove the item
* from the distributed queue
*
* @throws Exception
*/
@Override
public void consumeItem(OrderServiceJob job, DistributedQueueItemProcessedCallback callback) throws Exception {
while (true) {
try {
OrderJobStatus jobStatus = orderService.queryJobInfo(OrderServiceJob.JobType.DELETE_ORDER);
long startTime = jobStatus.getStartTime();
long endTime = jobStatus.getEndTime();
OrderStatus status = jobStatus.getStatus();
List<URI> tids = jobStatus.getTids();
List<URI> orderIds = new ArrayList();
log.info("jobstatus={}", jobStatus);
long total = 0;
long numberOfOrdersDeletedInGC = orderService.getDeletedOrdersInCurrentPeriodWithSort(jobStatus);
long numberOfOrdersCanBeDeletedInGC =
maxOrderDeletedPerGC - numberOfOrdersDeletedInGC;
if (numberOfOrdersCanBeDeletedInGC <= 0) {
log.info("Max number of order objects ({}) have been deleted in the current GC period",
maxOrderDeletedPerGC);
Thread.sleep(CHECK_INTERVAL);
continue;
}
boolean stop = false;
for (URI tid : tids) {
TimeSeriesConstraint constraint = TimeSeriesConstraint.Factory.getOrders(tid, startTime, endTime);
NamedElementQueryResultList ids = new NamedElementQueryResultList();
dbClient.queryByConstraint(constraint, ids);
for (NamedElementQueryResultList.NamedElement namedID : ids) {
URI id = namedID.getId();
Order order = orderManager.getOrderById(id);
try {
orderManager.canBeDeleted(order, status);
if (orderIds.size() < numberOfOrdersCanBeDeletedInGC) {
orderIds.add(id);
} else if (jobStatus.getTotal() != -1) {
stop = true;
break;
}
total++;
} catch (Exception e) {
continue;
}
}
if (stop) {
break;
}
}
if (jobStatus.getTotal() == -1) {
//It's the first time to run the job, so get the total number of orders to be deleted
jobStatus.setTotal(total);
orderService.saveJobInfo(jobStatus);
if (total == 0) {
log.info("No orders can be deleted");
break;
}
}
log.info("{} orders to be deleted within current GC period", orderIds.size());
long nDeleted = 0;
long nFailed = 0;
long start = System.currentTimeMillis();
long tempCount = 0;
for (URI id : orderIds) {
Order order = orderManager.getOrderById(id);
try {
log.info("To delete order {}", order.getId());
orderManager.deleteOrder(order);
nDeleted++;
tempCount++;
if (tempCount >= NUMBER_PER_RECORD) {
jobStatus.addCompleted(tempCount);
orderService.saveJobInfo(jobStatus);
tempCount = 0;
}
} catch (BadRequestException e) {
log.warn("Failed to delete order {} e=", id, e);
nFailed++;
jobStatus.setFailed(nFailed);
orderService.saveJobInfo(jobStatus);
} catch (Exception e) {
log.warn("Failed to delete order={} e=", id, e);
nFailed++;
jobStatus.setFailed(nFailed);
orderService.saveJobInfo(jobStatus);
}
}
if (tempCount > 0) {
jobStatus.addCompleted(tempCount);
orderService.saveJobInfo(jobStatus);
tempCount = 0;
}
long end = System.currentTimeMillis();
long speed = (end - start) / (nDeleted + nFailed);
jobStatus.setTimeUsedPerOrder(speed);
orderService.saveJobInfo(jobStatus);
if (jobStatus.isFinished()) {
break;
}
Thread.sleep(CHECK_INTERVAL);
} catch (Exception e) {
log.error("e=", e);
throw e;
}
}
log.info("remove order job from the queue");
callback.itemProcessed();
}
}