package org.zstack.core.asyncbatch; import org.zstack.header.core.AbstractCompletion; import org.zstack.header.core.AsyncBackup; import org.zstack.header.core.AsyncLatch; import org.zstack.header.core.NoErrorCompletion; import org.zstack.header.errorcode.ErrorCode; import org.zstack.header.errorcode.SysErrors; import org.zstack.utils.DebugUtils; import org.zstack.utils.Utils; import org.zstack.utils.logging.CLogger; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * Created by xing5 on 2016/6/26. */ public abstract class AsyncBatch extends AbstractCompletion { private static final CLogger logger = Utils.getLogger(AsyncBatch.class); private List<AsyncBatchRunner> runners = new ArrayList<>(); protected List<ErrorCode> errors = Collections.synchronizedList(new ArrayList<ErrorCode>()); public AsyncBatch(AsyncBackup one, AsyncBackup... others) { super(one, others); } protected void batch(AsyncBatchRunner runner) { DebugUtils.Assert(runner != null, "runner cannot be null"); runners.add(runner); } protected abstract void setup(); protected abstract void done(); public void start() { setup(); if (runners.isEmpty()) { done(); return; } AsyncBatch that = this; AsyncLatch latch = new AsyncLatch(runners.size(), new NoErrorCompletion(backups == null ? new AsyncBackup[]{} : backups.toArray(new AsyncBackup[backups.size()])) { @Override public void done() { that.done(); } }); for (AsyncBatchRunner runner : runners) { try { runner.run(new NoErrorCompletion(latch) { @Override public void done() { latch.ack(); } }); } catch (Throwable t) { logger.warn("unhandled exception happened", t); ErrorCode code = new ErrorCode(); code.setCode(SysErrors.INTERNAL.toString()); code.setDescription("an internal error happened"); code.setDetails(t.getMessage()); errors.add(code); latch.ack(); } } } }