/* * Copyright (c) 2009-2011 by Bjoern Kolbeck, * Zuse Institute Berlin * * Licensed under the BSD License, see LICENSE file for details. * */ package org.xtreemfs.dir.operations; import java.io.IOException; import org.xtreemfs.babudb.api.database.DatabaseRequestListener; import org.xtreemfs.babudb.api.exception.BabuDBException; import org.xtreemfs.dir.DIRRequest; import org.xtreemfs.dir.DIRRequestDispatcher; import org.xtreemfs.foundation.pbrpc.generatedinterfaces.RPC.ErrorType; import org.xtreemfs.foundation.pbrpc.generatedinterfaces.RPC.POSIXErrno; import com.google.protobuf.Message; /** * * @author bjko */ public abstract class DIROperation { protected final DIRRequestDispatcher master; public DIROperation(DIRRequestDispatcher master) { this.master = master; } public abstract int getProcedureId(); /** * called after request was parsed and operation assigned. * * @param rq * the new request */ public abstract void startRequest(DIRRequest rq); /** * Method to check if operation needs user authentication. * * @return true, if the user needs to be authenticated */ public abstract boolean isAuthRequired(); protected abstract Message getRequestMessagePrototype(); /** * parses the RPC request message. Can throw any exception which * will result in an error message telling the client that the * request message data is garbage. * @param rq * @throws java.lang.Exception */ public void parseRPCMessage(DIRRequest rq) throws IOException { rq.deserializeMessage(getRequestMessagePrototype()); } void requestFailed(BabuDBException error, DIRRequest rq) { assert(error != null); rq.sendError(ErrorType.ERRNO,POSIXErrno.POSIX_ERROR_EINVAL,error.toString()); } /** * Operation to give a failure back to the client. * Will decide, if a {@link RedirectException} should be returned. * * @param error - Exception thrown. * @param rq - original {@link DIRRequest}. */ /* void requestFailed(Exception error, DIRRequest rq) { // handle connection errors caused by being not the replication master if (error != null && dbsReplicationManager != null && ((error instanceof BabuDBException && ((BabuDBException) error).getErrorCode().equals(NO_ACCESS)) || ( // TODO better exception handling error instanceof ConcurrentModificationException)) // && !dbsReplicationManager.isMaster() ... removed for testing ) { InetAddress altMaster = dbsReplicationManager.getMaster(); if (altMaster != null) { // retrieve the correct port for the DIR mirror String host = altMaster.getHostAddress(); Integer port = this.master.getConfig().getMirrors().get(host); if (port == null) { Logging.logMessage(Logging.LEVEL_ERROR, this, "The port for " + "the mirror DIR '%s' could not be retrieved.", host); rq.sendInternalServerError(error); } else { rq.sendRedirectException(host, port); } } else { // if there is a handover in progress, redirect to the local // server to notify the client about this process InetAddress host = this.master.getConfig().getAddress(); int port = this.master.getConfig().getPort(); InetSocketAddress address = (host == null) ? new InetSocketAddress(port) : new InetSocketAddress(host, port); rq.sendRedirectException(address.getAddress().getHostAddress(), port); } // handle errors caused by ServerExceptions } else if (error != null && error instanceof ONCRPCException) { Logging.logError(Logging.LEVEL_ERROR, this, error); rq.sendException((ONCRPCException) error); // handle user errors } else if (error != null && error instanceof BabuDBException && (((BabuDBException) error).getErrorCode().equals(NO_SUCH_DB) || ((BabuDBException) error).getErrorCode().equals(DB_EXISTS) || ((BabuDBException) error).getErrorCode().equals(NO_SUCH_INDEX) || ((BabuDBException) error).getErrorCode().equals(NO_SUCH_SNAPSHOT) || ((BabuDBException) error).getErrorCode().equals(SNAP_EXISTS))) { // blame the client Logging.logError(Logging.LEVEL_ERROR, this, error); rq.sendException(new InvalidArgumentException(error.getMessage())); // handle unknown errors } else { if (error != null && !(error instanceof BabuDBException)) { Logging.logError(Logging.LEVEL_ERROR, this, error); } if (error != null) { Logging.logError(Logging.LEVEL_ERROR, this, error); } rq.sendInternalServerError(error); } }*/ /** * Method-interface for sending a response * * @param result - can be null, if not necessary. * @param rq - original {@link DIRRequest}. */ abstract void requestFinished(Object result, DIRRequest rq); /** * Listener implementation for non-blocking BabuDB requests. * * @author flangner * @since 11/16/2009 * @param <I> - input type. * @param <O> - output type. */ abstract class DBRequestListener<I, O> implements DatabaseRequestListener<I> { private final boolean finishRequest; DBRequestListener(boolean finishRequest) { this.finishRequest = finishRequest; } abstract O execute(I result, DIRRequest rq) throws Exception; /* * (non-Javadoc) * @see org.xtreemfs.babudb.BabuDBRequestListener#failed(org.xtreemfs.babudb.BabuDBException, java.lang.Object) */ @Override public void failed(BabuDBException error, Object request) { requestFailed(error, (DIRRequest) request); } /* * (non-Javadoc) * @see org.xtreemfs.babudb.BabuDBRequestListener#finished(java.lang.Object, java.lang.Object) */ @Override public void finished(I data, Object context) { try { O result = execute(data, (DIRRequest) context); if (finishRequest) { requestFinished(result, (DIRRequest) context); } } catch (IllegalArgumentException ex) { DIRRequest rq = (DIRRequest) context; rq.sendError(ErrorType.ERRNO, POSIXErrno.POSIX_ERROR_EINVAL, ex.toString()); } catch (java.util.ConcurrentModificationException ex) { DIRRequest rq = (DIRRequest) context; rq.sendError(ErrorType.ERRNO, POSIXErrno.POSIX_ERROR_EAGAIN, ex.toString()); } catch (Exception e) { DIRRequest rq = (DIRRequest) context; rq.sendInternalServerError(e); } } } }