package com.opower.updater; import com.opower.updater.admin.loader.TableUpdatesNotFoundException; import com.opower.updater.operation.MissingUpdateException; import com.opower.updater.operation.OperationForbiddenException; import com.opower.updater.operation.TableAlreadyExistException; import com.opower.updater.operation.TableDoesNotExistException; import org.kiji.schema.KijiURI; import org.kiji.schema.tools.BaseTool; import java.util.List; import java.util.concurrent.TimeUnit; /** * Base class for updater tools. This base class is responsible for obtaining a lock in zookeeper to avoid * running two tools that could alter the tables in a given kiji instance at the same time. * * @author felix.trepanier */ public abstract class BaseUpdaterTool extends BaseTool { private static final Integer MAX_LOCK_WAIT_TIME_SEC = 5; private final UpdaterLocker locker; protected KijiURI kijiURI; protected BaseUpdaterTool(UpdaterLocker locker) { this.locker = locker; } /** * Executes the tool operation. * <p/> * This is called by the {@link com.opower.updater.BaseUpdaterTool#run(java.util.List)} method * after the updater lock has been acquired. * * @param nonFlagArgs The arguments on the command-line that were not parsed as flags. * @return Operation return code. * @throws Exception */ protected abstract int executeToolOperation(List<String> nonFlagArgs) throws Exception; /** * Create the KijiURI to be used to open the kiji instance. * * @return the KijiURI to be used to open the kiji instance. */ protected abstract KijiURI createKijiURI(); /** * {@inheritDoc} */ @Override protected void setup() throws Exception { super.setup(); kijiURI = createKijiURI(); } /** * {@inheritDoc} */ @Override protected final int run(List<String> nonFlagArgs) throws Exception { UpdaterLocker.AcquiredLock lock = null; try { lock = locker.acquireLock(kijiURI, MAX_LOCK_WAIT_TIME_SEC, TimeUnit.SECONDS); return executeToolOperation(nonFlagArgs); } catch (LockNotAcquiredException ex) { getPrintStream().println("Error: Could not acquire the updater lock: " + ex.getMessage() + "."); return FAILURE; } catch (OperationForbiddenException ex) { getPrintStream().println("Error: " + ex.getMessage()); return FAILURE; } catch (TableAlreadyExistException ex) { getPrintStream().println("Error: Table '" + ex.getTableName() + "' already exists."); return FAILURE; } catch (TableDoesNotExistException ex) { getPrintStream().println("Error: Table '" + ex.getTableName() + "' does not exist."); return FAILURE; } catch (MissingUpdateException ex) { getPrintStream().println("Error: Update " + ex.getExpectedId() + " was not found." + " Id " + ex.getIdFound() + " was found instead."); return FAILURE; } catch (TableUpdatesNotFoundException ex) { getPrintStream().println("Error: Could not find updates for table '" + ex.getTableName() + "'."); return FAILURE; } finally { if (lock != null) { lock.release(); } } } /** * {@inheritDoc} */ @Override public String getCategory() { return "updater"; } }