accumulo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ctubb...@apache.org
Subject [5/8] git commit: Merge branch '1.5' into 1.6
Date Wed, 01 Oct 2014 01:26:40 GMT
Merge branch '1.5' into 1.6


Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo
Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/beebb946
Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/beebb946
Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/beebb946

Branch: refs/heads/master
Commit: beebb946d07722cf47fd375e35510f852d5b597e
Parents: 8d316a3 8b17144
Author: Christopher Tubbs <ctubbsii@apache.org>
Authored: Tue Sep 30 21:16:00 2014 -0400
Committer: Christopher Tubbs <ctubbsii@apache.org>
Committed: Tue Sep 30 21:16:00 2014 -0400

----------------------------------------------------------------------
 .../main/java/org/apache/accumulo/master/FateServiceHandler.java   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/accumulo/blob/beebb946/server/master/src/main/java/org/apache/accumulo/master/FateServiceHandler.java
----------------------------------------------------------------------
diff --cc server/master/src/main/java/org/apache/accumulo/master/FateServiceHandler.java
index a3ea117,0000000..5818da3
mode 100644,000000..100644
--- a/server/master/src/main/java/org/apache/accumulo/master/FateServiceHandler.java
+++ b/server/master/src/main/java/org/apache/accumulo/master/FateServiceHandler.java
@@@ -1,550 -1,0 +1,550 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one or more
 + * contributor license agreements.  See the NOTICE file distributed with
 + * this work for additional information regarding copyright ownership.
 + * The ASF licenses this file to You under the Apache License, Version 2.0
 + * (the "License"); you may not use this file except in compliance with
 + * the License.  You may obtain a copy of the License at
 + *
 + *     http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing, software
 + * distributed under the License is distributed on an "AS IS" BASIS,
 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 + * See the License for the specific language governing permissions and
 + * limitations under the License.
 + */
 +package org.apache.accumulo.master;
 +
 +import java.nio.ByteBuffer;
 +import java.util.HashMap;
 +import java.util.HashSet;
 +import java.util.List;
 +import java.util.Map;
 +import java.util.Map.Entry;
 +import java.util.Set;
 +
 +import org.apache.accumulo.core.client.AccumuloSecurityException;
 +import org.apache.accumulo.core.client.IteratorSetting;
 +import org.apache.accumulo.core.client.NamespaceNotFoundException;
 +import org.apache.accumulo.core.client.TableNotFoundException;
 +import org.apache.accumulo.core.client.admin.TimeType;
 +import org.apache.accumulo.core.client.impl.Namespaces;
 +import org.apache.accumulo.core.client.impl.TableOperationsImpl;
 +import org.apache.accumulo.core.client.impl.Tables;
 +import org.apache.accumulo.core.client.impl.thrift.SecurityErrorCode;
 +import org.apache.accumulo.core.client.impl.thrift.TableOperation;
 +import org.apache.accumulo.core.client.impl.thrift.TableOperationExceptionType;
 +import org.apache.accumulo.core.client.impl.thrift.ThriftSecurityException;
 +import org.apache.accumulo.core.client.impl.thrift.ThriftTableOperationException;
 +import org.apache.accumulo.core.iterators.IteratorUtil;
 +import org.apache.accumulo.core.master.thrift.FateOperation;
 +import org.apache.accumulo.core.master.thrift.FateService;
 +import org.apache.accumulo.core.security.thrift.TCredentials;
 +import org.apache.accumulo.core.util.ArgumentChecker.Validator;
 +import org.apache.accumulo.core.util.ByteBufferUtil;
 +import org.apache.accumulo.fate.ReadOnlyTStore.TStatus;
 +import org.apache.accumulo.master.tableOps.BulkImport;
 +import org.apache.accumulo.master.tableOps.CancelCompactions;
 +import org.apache.accumulo.master.tableOps.ChangeTableState;
 +import org.apache.accumulo.master.tableOps.CloneTable;
 +import org.apache.accumulo.master.tableOps.CompactRange;
 +import org.apache.accumulo.master.tableOps.CreateNamespace;
 +import org.apache.accumulo.master.tableOps.CreateTable;
 +import org.apache.accumulo.master.tableOps.DeleteNamespace;
 +import org.apache.accumulo.master.tableOps.DeleteTable;
 +import org.apache.accumulo.master.tableOps.ExportTable;
 +import org.apache.accumulo.master.tableOps.ImportTable;
 +import org.apache.accumulo.master.tableOps.RenameNamespace;
 +import org.apache.accumulo.master.tableOps.RenameTable;
 +import org.apache.accumulo.master.tableOps.TableRangeOp;
 +import org.apache.accumulo.master.tableOps.TraceRepo;
 +import org.apache.accumulo.server.client.ClientServiceHandler;
 +import org.apache.accumulo.server.master.state.MergeInfo;
 +import org.apache.accumulo.server.util.TablePropUtil;
 +import org.apache.accumulo.trace.thrift.TInfo;
 +import org.apache.hadoop.io.Text;
 +import org.apache.log4j.Logger;
 +
 +/**
 + *
 + */
 +class FateServiceHandler implements FateService.Iface {
 +
 +  protected final Master master;
 +  protected static final Logger log = Master.log;
 +
 +  public FateServiceHandler(Master master) {
 +    this.master = master;
 +  }
 +
 +  @Override
 +  public long beginFateOperation(TInfo tinfo, TCredentials credentials) throws ThriftSecurityException
{
 +    authenticate(credentials);
 +    return master.fate.startTransaction();
 +  }
 +
 +  @Override
 +  public void executeFateOperation(TInfo tinfo, TCredentials c, long opid, FateOperation
op, List<ByteBuffer> arguments, Map<String,String> options,
 +      boolean autoCleanup) throws ThriftSecurityException, ThriftTableOperationException
{
 +    authenticate(c);
 +
 +    switch (op) {
 +      case NAMESPACE_CREATE: {
 +        TableOperation tableOp = TableOperation.CREATE;
 +        String namespace = validateNamespaceArgument(arguments.get(0), tableOp, null);
 +
 +        if (!master.security.canCreateNamespace(c, namespace))
 +          throw new ThriftSecurityException(c.getPrincipal(), SecurityErrorCode.PERMISSION_DENIED);
 +
 +        master.fate.seedTransaction(opid, new TraceRepo<Master>(new CreateNamespace(c.getPrincipal(),
namespace, options)), autoCleanup);
 +        break;
 +      }
 +      case NAMESPACE_RENAME: {
 +        TableOperation tableOp = TableOperation.RENAME;
 +        String oldName = validateNamespaceArgument(arguments.get(0), tableOp, Namespaces.NOT_DEFAULT.and(Namespaces.NOT_ACCUMULO));
 +        String newName = validateNamespaceArgument(arguments.get(1), tableOp, null);
 +
 +        String namespaceId = ClientServiceHandler.checkNamespaceId(master.getInstance(),
oldName, tableOp);
 +        if (!master.security.canRenameNamespace(c, namespaceId, oldName, newName))
 +          throw new ThriftSecurityException(c.getPrincipal(), SecurityErrorCode.PERMISSION_DENIED);
 +
 +        master.fate.seedTransaction(opid, new TraceRepo<Master>(new RenameNamespace(namespaceId,
oldName, newName)), autoCleanup);
 +        break;
 +      }
 +      case NAMESPACE_DELETE: {
 +        TableOperation tableOp = TableOperation.DELETE;
 +        String namespace = validateNamespaceArgument(arguments.get(0), tableOp, Namespaces.NOT_DEFAULT.and(Namespaces.NOT_ACCUMULO));
 +
 +        String namespaceId = ClientServiceHandler.checkNamespaceId(master.getInstance(),
namespace, tableOp);
 +        if (!master.security.canDeleteNamespace(c, namespaceId))
 +          throw new ThriftSecurityException(c.getPrincipal(), SecurityErrorCode.PERMISSION_DENIED);
 +
 +        master.fate.seedTransaction(opid, new TraceRepo<Master>(new DeleteNamespace(namespaceId)),
autoCleanup);
 +        break;
 +      }
 +      case TABLE_CREATE: {
 +        TableOperation tableOp = TableOperation.CREATE;
 +        String tableName = validateTableNameArgument(arguments.get(0), tableOp, Tables.NOT_SYSTEM);
 +        TimeType timeType = TimeType.valueOf(ByteBufferUtil.toString(arguments.get(1)));
 +
 +        String namespaceId;
 +
 +        try {
 +          namespaceId = Namespaces.getNamespaceId(master.getInstance(), Tables.qualify(tableName).getFirst());
 +        } catch (NamespaceNotFoundException e) {
 +          throw new ThriftTableOperationException(null, tableName, tableOp, TableOperationExceptionType.NAMESPACE_NOTFOUND,
"");
 +        }
 +
 +        if (!master.security.canCreateTable(c, tableName, namespaceId))
 +          throw new ThriftSecurityException(c.getPrincipal(), SecurityErrorCode.PERMISSION_DENIED);
 +
 +        master.fate.seedTransaction(opid, new TraceRepo<Master>(new CreateTable(c.getPrincipal(),
tableName, timeType, options, namespaceId)), autoCleanup);
 +
 +        break;
 +      }
 +      case TABLE_RENAME: {
 +        TableOperation tableOp = TableOperation.RENAME;
 +        final String oldTableName = validateTableNameArgument(arguments.get(0), tableOp,
Tables.NOT_SYSTEM);
 +        String newTableName = validateTableNameArgument(arguments.get(1), tableOp, new Validator<String>()
{
 +
 +          @Override
 +          public boolean isValid(String argument) {
 +            // verify they are in the same namespace
 +            String oldNamespace = Tables.qualify(oldTableName).getFirst();
 +            return oldNamespace.equals(Tables.qualify(argument).getFirst());
 +          }
 +
 +          @Override
 +          public String invalidMessage(String argument) {
 +            return "Cannot move tables to a new namespace by renaming. The namespace for
" + oldTableName + " does not match " + argument;
 +          }
 +
 +        });
 +
 +        String tableId = ClientServiceHandler.checkTableId(master.getInstance(), oldTableName,
tableOp);
 +        String namespaceId = Tables.getNamespaceId(master.getInstance(), tableId);
 +
 +        final boolean canRename;
 +        try {
 +          canRename = master.security.canRenameTable(c, tableId, oldTableName, newTableName,
namespaceId);
 +        } catch (ThriftSecurityException e) {
 +          throwIfTableMissingSecurityException(e, tableId, oldTableName, TableOperation.RENAME);
 +          throw e;
 +        }
 +
 +        if (!canRename)
 +          throw new ThriftSecurityException(c.getPrincipal(), SecurityErrorCode.PERMISSION_DENIED);
 +
 +        try {
 +          master.fate.seedTransaction(opid, new TraceRepo<Master>(new RenameTable(tableId,
oldTableName, newTableName)), autoCleanup);
 +        } catch (NamespaceNotFoundException e) {
 +          throw new ThriftTableOperationException(null, oldTableName, tableOp, TableOperationExceptionType.NAMESPACE_NOTFOUND,
"");
 +        }
 +
 +        break;
 +      }
 +      case TABLE_CLONE: {
 +        TableOperation tableOp = TableOperation.CLONE;
 +        String srcTableId = validateTableIdArgument(arguments.get(0), tableOp, Tables.NOT_ROOT_ID);
 +        String tableName = validateTableNameArgument(arguments.get(1), tableOp, Tables.NOT_SYSTEM);
 +        String namespaceId;
 +        try {
 +          namespaceId = Namespaces.getNamespaceId(master.getInstance(), Tables.qualify(tableName).getFirst());
 +        } catch (NamespaceNotFoundException e) {
 +          // shouldn't happen, but possible once cloning between namespaces is supported
 +          throw new ThriftTableOperationException(null, tableName, tableOp, TableOperationExceptionType.NAMESPACE_NOTFOUND,
"");
 +        }
 +
 +        final boolean canCloneTable;
 +        try {
 +          canCloneTable = master.security.canCloneTable(c, srcTableId, tableName, namespaceId,
namespaceId);
 +        } catch (ThriftSecurityException e) {
 +          throwIfTableMissingSecurityException(e, srcTableId, null, TableOperation.CLONE);
 +          throw e;
 +        }
 +
 +        if (!canCloneTable)
 +          throw new ThriftSecurityException(c.getPrincipal(), SecurityErrorCode.PERMISSION_DENIED);
 +
 +        Map<String,String> propertiesToSet = new HashMap<String,String>();
 +        Set<String> propertiesToExclude = new HashSet<String>();
 +
 +        for (Entry<String,String> entry : options.entrySet()) {
 +          if (entry.getKey().startsWith(TableOperationsImpl.CLONE_EXCLUDE_PREFIX)) {
 +            propertiesToExclude.add(entry.getKey().substring(TableOperationsImpl.CLONE_EXCLUDE_PREFIX.length()));
 +            continue;
 +          }
 +
 +          if (!TablePropUtil.isPropertyValid(entry.getKey(), entry.getValue())) {
 +            throw new ThriftTableOperationException(null, tableName, tableOp, TableOperationExceptionType.OTHER,
"Property or value not valid "
 +                + entry.getKey() + "=" + entry.getValue());
 +          }
 +
 +          propertiesToSet.put(entry.getKey(), entry.getValue());
 +        }
 +
 +        master.fate.seedTransaction(opid, new TraceRepo<Master>(new CloneTable(c.getPrincipal(),
srcTableId, tableName, propertiesToSet, propertiesToExclude)),
 +            autoCleanup);
 +
 +        break;
 +      }
 +      case TABLE_DELETE: {
 +        TableOperation tableOp = TableOperation.DELETE;
 +        String tableName = validateTableNameArgument(arguments.get(0), tableOp, Tables.NOT_SYSTEM);
 +
 +        final String tableId = ClientServiceHandler.checkTableId(master.getInstance(), tableName,
tableOp);
 +        String namespaceId = Tables.getNamespaceId(master.getInstance(), tableId);
 +
 +        final boolean canDeleteTable;
 +        try {
 +          canDeleteTable = master.security.canDeleteTable(c, tableId, namespaceId);
 +        } catch (ThriftSecurityException e) {
 +          throwIfTableMissingSecurityException(e, tableId, tableName, TableOperation.DELETE);
 +          throw e;
 +        }
 +
 +        if (!canDeleteTable)
 +          throw new ThriftSecurityException(c.getPrincipal(), SecurityErrorCode.PERMISSION_DENIED);
 +        master.fate.seedTransaction(opid, new TraceRepo<Master>(new DeleteTable(tableId)),
autoCleanup);
 +        break;
 +      }
 +      case TABLE_ONLINE: {
 +        TableOperation tableOp = TableOperation.ONLINE;
 +        final String tableId = validateTableIdArgument(arguments.get(0), tableOp, Tables.NOT_ROOT_ID);
 +        String namespaceId = Tables.getNamespaceId(master.getInstance(), tableId);
 +
 +        final boolean canOnlineOfflineTable;
 +        try {
 +          canOnlineOfflineTable = master.security.canOnlineOfflineTable(c, tableId, op,
namespaceId);
 +        } catch (ThriftSecurityException e) {
 +          throwIfTableMissingSecurityException(e, tableId, null, TableOperation.ONLINE);
 +          throw e;
 +        }
 +
 +        if (!canOnlineOfflineTable)
 +          throw new ThriftSecurityException(c.getPrincipal(), SecurityErrorCode.PERMISSION_DENIED);
 +
 +        master.fate.seedTransaction(opid, new TraceRepo<Master>(new ChangeTableState(tableId,
tableOp)), autoCleanup);
 +        break;
 +      }
 +      case TABLE_OFFLINE: {
 +        TableOperation tableOp = TableOperation.OFFLINE;
 +        final String tableId = validateTableIdArgument(arguments.get(0), tableOp, Tables.NOT_ROOT_ID);
 +        String namespaceId = Tables.getNamespaceId(master.getInstance(), tableId);
 +
 +        final boolean canOnlineOfflineTable;
 +        try {
 +          canOnlineOfflineTable = master.security.canOnlineOfflineTable(c, tableId, op,
namespaceId);
 +        } catch (ThriftSecurityException e) {
 +          throwIfTableMissingSecurityException(e, tableId, null, TableOperation.OFFLINE);
 +          throw e;
 +        }
 +
 +        if (!canOnlineOfflineTable)
 +          throw new ThriftSecurityException(c.getPrincipal(), SecurityErrorCode.PERMISSION_DENIED);
 +
 +        master.fate.seedTransaction(opid, new TraceRepo<Master>(new ChangeTableState(tableId,
tableOp)), autoCleanup);
 +        break;
 +      }
 +      case TABLE_MERGE: {
 +        TableOperation tableOp = TableOperation.MERGE;
 +        String tableName = validateTableNameArgument(arguments.get(0), tableOp, null);
 +        Text startRow = ByteBufferUtil.toText(arguments.get(1));
 +        Text endRow = ByteBufferUtil.toText(arguments.get(2));
 +
 +        final String tableId = ClientServiceHandler.checkTableId(master.getInstance(), tableName,
tableOp);
 +        String namespaceId = Tables.getNamespaceId(master.getInstance(), tableId);
 +
 +        final boolean canMerge;
 +        try {
 +          canMerge = master.security.canMerge(c, tableId, namespaceId);
 +        } catch (ThriftSecurityException e) {
 +          throwIfTableMissingSecurityException(e, tableId, tableName, TableOperation.MERGE);
 +          throw e;
 +        }
 +
 +        if (!canMerge)
 +          throw new ThriftSecurityException(c.getPrincipal(), SecurityErrorCode.PERMISSION_DENIED);
 +
 +        Master.log.debug("Creating merge op: " + tableId + " " + startRow + " " + endRow);
 +        master.fate.seedTransaction(opid, new TraceRepo<Master>(new TableRangeOp(MergeInfo.Operation.MERGE,
tableId, startRow, endRow)), autoCleanup);
 +        break;
 +      }
 +      case TABLE_DELETE_RANGE: {
 +        TableOperation tableOp = TableOperation.DELETE_RANGE;
 +        String tableName = validateTableNameArgument(arguments.get(0), tableOp, Tables.NOT_SYSTEM);
 +        Text startRow = ByteBufferUtil.toText(arguments.get(1));
 +        Text endRow = ByteBufferUtil.toText(arguments.get(2));
 +
 +        final String tableId = ClientServiceHandler.checkTableId(master.getInstance(), tableName,
tableOp);
 +        String namespaceId = Tables.getNamespaceId(master.getInstance(), tableId);
 +
 +        final boolean canDeleteRange;
 +        try {
 +          canDeleteRange = master.security.canDeleteRange(c, tableId, tableName, startRow,
endRow, namespaceId);
 +        } catch (ThriftSecurityException e) {
 +          throwIfTableMissingSecurityException(e, tableId, tableName, TableOperation.DELETE_RANGE);
 +          throw e;
 +        }
 +
 +        if (!canDeleteRange)
 +          throw new ThriftSecurityException(c.getPrincipal(), SecurityErrorCode.PERMISSION_DENIED);
 +
 +        master.fate.seedTransaction(opid, new TraceRepo<Master>(new TableRangeOp(MergeInfo.Operation.DELETE,
tableId, startRow, endRow)), autoCleanup);
 +        break;
 +      }
 +      case TABLE_BULK_IMPORT: {
 +        TableOperation tableOp = TableOperation.BULK_IMPORT;
 +        String tableName = validateTableNameArgument(arguments.get(0), tableOp, Tables.NOT_SYSTEM);
 +        String dir = ByteBufferUtil.toString(arguments.get(1));
 +        String failDir = ByteBufferUtil.toString(arguments.get(2));
 +        boolean setTime = Boolean.parseBoolean(ByteBufferUtil.toString(arguments.get(3)));
 +
 +        final String tableId = ClientServiceHandler.checkTableId(master.getInstance(), tableName,
tableOp);
 +        String namespaceId = Tables.getNamespaceId(master.getInstance(), tableId);
 +
 +        final boolean canBulkImport;
 +        try {
 +          canBulkImport = master.security.canBulkImport(c, tableId, tableName, dir, failDir,
namespaceId);
 +        } catch (ThriftSecurityException e) {
 +          throwIfTableMissingSecurityException(e, tableId, tableName, TableOperation.BULK_IMPORT);
 +          throw e;
 +        }
 +
 +        if (!canBulkImport)
 +          throw new ThriftSecurityException(c.getPrincipal(), SecurityErrorCode.PERMISSION_DENIED);
 +
 +        master.fate.seedTransaction(opid, new TraceRepo<Master>(new BulkImport(tableId,
dir, failDir, setTime)), autoCleanup);
 +        break;
 +      }
 +      case TABLE_COMPACT: {
 +        TableOperation tableOp = TableOperation.COMPACT;
 +        String tableId = validateTableIdArgument(arguments.get(0), tableOp, null);
 +        byte[] startRow = ByteBufferUtil.toBytes(arguments.get(1));
 +        byte[] endRow = ByteBufferUtil.toBytes(arguments.get(2));
 +        List<IteratorSetting> iterators = IteratorUtil.decodeIteratorSettings(ByteBufferUtil.toBytes(arguments.get(3)));
 +        String namespaceId = Tables.getNamespaceId(master.getInstance(), tableId);
 +
 +        final boolean canCompact;
 +        try {
 +          canCompact = master.security.canCompact(c, tableId, namespaceId);
 +        } catch (ThriftSecurityException e) {
 +          throwIfTableMissingSecurityException(e, tableId, null, TableOperation.COMPACT);
 +          throw e;
 +        }
 +
 +        if (!canCompact)
 +          throw new ThriftSecurityException(c.getPrincipal(), SecurityErrorCode.PERMISSION_DENIED);
 +
 +        master.fate.seedTransaction(opid, new TraceRepo<Master>(new CompactRange(tableId,
startRow, endRow, iterators)), autoCleanup);
 +        break;
 +      }
 +      case TABLE_CANCEL_COMPACT: {
 +        TableOperation tableOp = TableOperation.COMPACT_CANCEL;
 +        String tableId = validateTableIdArgument(arguments.get(0), tableOp, null);
 +        String namespaceId = Tables.getNamespaceId(master.getInstance(), tableId);
 +
 +        final boolean canCancelCompact;
 +        try {
 +          canCancelCompact = master.security.canCompact(c, tableId, namespaceId);
 +        } catch (ThriftSecurityException e) {
 +          throwIfTableMissingSecurityException(e, tableId, null, TableOperation.COMPACT_CANCEL);
 +          throw e;
 +        }
 +
 +        if (!canCancelCompact)
 +          throw new ThriftSecurityException(c.getPrincipal(), SecurityErrorCode.PERMISSION_DENIED);
 +
 +        master.fate.seedTransaction(opid, new TraceRepo<Master>(new CancelCompactions(tableId)),
autoCleanup);
 +        break;
 +      }
 +      case TABLE_IMPORT: {
 +        TableOperation tableOp = TableOperation.IMPORT;
 +        String tableName = validateTableNameArgument(arguments.get(0), tableOp, Tables.NOT_SYSTEM);
 +        String exportDir = ByteBufferUtil.toString(arguments.get(1));
 +        String namespaceId;
 +        try {
 +          namespaceId = Namespaces.getNamespaceId(master.getInstance(), Tables.qualify(tableName).getFirst());
 +        } catch (NamespaceNotFoundException e) {
 +          throw new ThriftTableOperationException(null, tableName, tableOp, TableOperationExceptionType.NAMESPACE_NOTFOUND,
"");
 +        }
 +
 +        final boolean canImport;
 +        try {
 +          canImport = master.security.canImport(c, tableName, exportDir, namespaceId);
 +        } catch (ThriftSecurityException e) {
 +          throwIfTableMissingSecurityException(e, null, tableName, TableOperation.IMPORT);
 +          throw e;
 +        }
 +
 +        if (!canImport)
 +          throw new ThriftSecurityException(c.getPrincipal(), SecurityErrorCode.PERMISSION_DENIED);
 +
 +        master.fate.seedTransaction(opid, new TraceRepo<Master>(new ImportTable(c.getPrincipal(),
tableName, exportDir, namespaceId)), autoCleanup);
 +        break;
 +      }
 +      case TABLE_EXPORT: {
 +        TableOperation tableOp = TableOperation.EXPORT;
 +        String tableName = validateTableNameArgument(arguments.get(0), tableOp, Tables.NOT_SYSTEM);
 +        String exportDir = ByteBufferUtil.toString(arguments.get(1));
 +
 +        String tableId = ClientServiceHandler.checkTableId(master.getInstance(), tableName,
tableOp);
 +        String namespaceId = Tables.getNamespaceId(master.getInstance(), tableId);
 +
 +        final boolean canExport;
 +        try {
 +          canExport = master.security.canExport(c, tableId, tableName, exportDir, namespaceId);
 +        } catch (ThriftSecurityException e) {
 +          throwIfTableMissingSecurityException(e, tableId, tableName, TableOperation.EXPORT);
 +          throw e;
 +        }
 +
 +        if (!canExport)
 +          throw new ThriftSecurityException(c.getPrincipal(), SecurityErrorCode.PERMISSION_DENIED);
 +
 +        master.fate.seedTransaction(opid, new TraceRepo<Master>(new ExportTable(tableName,
tableId, exportDir)), autoCleanup);
 +        break;
 +      }
 +      default:
 +        throw new UnsupportedOperationException();
 +    }
 +  }
 +
 +  /**
 +   * Inspects the {@link ThriftSecurityException} and throws a {@link ThriftTableOperationException}
if the {@link SecurityErrorCode} on the
 +   * {@link ThriftSecurityException} was {code}TABLE_DOESNT_EXIST{code}. If the {@link ThriftSecurityException}
is thrown because a table doesn't exist anymore,
 +   * clients will likely see an {@link AccumuloSecurityException} instead of a {@link TableNotFoundException}
as expected. If the
 +   * {@link ThriftSecurityException} has a different {@link SecurityErrorCode}, this method
does nothing and expects the caller to properly handle the original
 +   * exception.
 +   *
 +   * @param e
 +   *          A caught ThriftSecurityException
 +   * @param tableId
 +   *          Table ID being operated on, or null
 +   * @param tableName
 +   *          Table name being operated on, or null
 +   * @param op
 +   *          The TableOperation the Master was attempting to perform
 +   * @throws ThriftTableOperationException
-    *           Thrown if {@link e} was thrown because {@link SecurityErrorCode#TABLE_DOESNT_EXIST}
++   *           Thrown if {@code e} was thrown because {@link SecurityErrorCode#TABLE_DOESNT_EXIST}
 +   */
 +  private void throwIfTableMissingSecurityException(ThriftSecurityException e, String tableId,
String tableName, TableOperation op)
 +      throws ThriftTableOperationException {
 +    // ACCUMULO-3135 Table can be deleted after we get table ID but before we can check
permission
 +    if (e.isSetCode() && SecurityErrorCode.TABLE_DOESNT_EXIST == e.getCode()) {
 +      throw new ThriftTableOperationException(tableId, tableName, op, TableOperationExceptionType.NOTFOUND,
"Table no longer exists");
 +    }
 +  }
 +
 +  @Override
 +  public String waitForFateOperation(TInfo tinfo, TCredentials credentials, long opid) throws
ThriftSecurityException, ThriftTableOperationException {
 +    authenticate(credentials);
 +
 +    TStatus status = master.fate.waitForCompletion(opid);
 +    if (status == TStatus.FAILED) {
 +      Exception e = master.fate.getException(opid);
 +      if (e instanceof ThriftTableOperationException)
 +        throw (ThriftTableOperationException) e;
 +      else if (e instanceof ThriftSecurityException)
 +        throw (ThriftSecurityException) e;
 +      else if (e instanceof RuntimeException)
 +        throw (RuntimeException) e;
 +      else
 +        throw new RuntimeException(e);
 +    }
 +
 +    String ret = master.fate.getReturn(opid);
 +    if (ret == null)
 +      ret = ""; // thrift does not like returning null
 +    return ret;
 +  }
 +
 +  @Override
 +  public void finishFateOperation(TInfo tinfo, TCredentials credentials, long opid) throws
ThriftSecurityException {
 +    authenticate(credentials);
 +    master.fate.delete(opid);
 +  }
 +
 +  protected void authenticate(TCredentials credentials) throws ThriftSecurityException {
 +    // this is a bit redundant, the credentials of the caller (the first arg) will throw
an exception if it fails to authenticate
 +    // before the second arg is checked (which would return true or false)
 +    if (!master.security.authenticateUser(credentials, credentials))
 +      throw new ThriftSecurityException(credentials.getPrincipal(), SecurityErrorCode.BAD_CREDENTIALS);
 +  }
 +
 +  // Verify table name arguments are valid, and match any additional restrictions
 +  private String validateTableIdArgument(ByteBuffer tableIdArg, TableOperation op, Validator<String>
userValidator) throws ThriftTableOperationException {
 +    String tableId = tableIdArg == null ? null : ByteBufferUtil.toString(tableIdArg);
 +    try {
 +      return Tables.VALID_ID.and(userValidator).validate(tableId);
 +    } catch (IllegalArgumentException e) {
 +      String why = e.getMessage();
 +      log.warn(why);
 +      throw new ThriftTableOperationException(tableId, null, op, TableOperationExceptionType.INVALID_NAME,
why);
 +    }
 +  }
 +
 +  // Verify table name arguments are valid, and match any additional restrictions
 +  private String validateTableNameArgument(ByteBuffer tableNameArg, TableOperation op, Validator<String>
userValidator) throws ThriftTableOperationException {
 +    String tableName = tableNameArg == null ? null : ByteBufferUtil.toString(tableNameArg);
 +    return _validateArgument(tableName, op, Tables.VALID_NAME.and(userValidator));
 +  }
 +
 +  // Verify namespace arguments are valid, and match any additional restrictions
 +  private String validateNamespaceArgument(ByteBuffer namespaceArg, TableOperation op, Validator<String>
userValidator) throws ThriftTableOperationException {
 +    String namespace = namespaceArg == null ? null : ByteBufferUtil.toString(namespaceArg);
 +    return _validateArgument(namespace, op, Namespaces.VALID_NAME.and(userValidator));
 +  }
 +
 +  // helper to handle the exception
 +  private <T> T _validateArgument(T arg, TableOperation op, Validator<T> validator)
throws ThriftTableOperationException {
 +    try {
 +      return validator.validate(arg);
 +    } catch (IllegalArgumentException e) {
 +      String why = e.getMessage();
 +      log.warn(why);
 +      throw new ThriftTableOperationException(null, String.valueOf(arg), op, TableOperationExceptionType.INVALID_NAME,
why);
 +    }
 +  }
 +}


Mime
View raw message