
org.apache.accumulo.server.master.tableOps.CreateTable Maven / Gradle / Ivy
The newest version!
/*
* 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.server.master.tableOps;
import java.io.Serializable;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.accumulo.core.Constants;
import org.apache.accumulo.core.client.Instance;
import org.apache.accumulo.core.client.admin.TimeType;
import org.apache.accumulo.core.client.impl.Tables;
import org.apache.accumulo.core.client.impl.thrift.TableOperation;
import org.apache.accumulo.core.client.impl.thrift.ThriftSecurityException;
import org.apache.accumulo.core.data.KeyExtent;
import org.apache.accumulo.core.file.FileUtil;
import org.apache.accumulo.core.master.state.tables.TableState;
import org.apache.accumulo.core.security.TablePermission;
import org.apache.accumulo.core.util.CachedConfiguration;
import org.apache.accumulo.fate.Repo;
import org.apache.accumulo.fate.zookeeper.ZooUtil.NodeExistsPolicy;
import org.apache.accumulo.server.ServerConstants;
import org.apache.accumulo.server.conf.ServerConfiguration;
import org.apache.accumulo.server.master.Master;
import org.apache.accumulo.server.master.state.tables.TableManager;
import org.apache.accumulo.server.security.AuditedSecurityOperation;
import org.apache.accumulo.server.security.SecurityConstants;
import org.apache.accumulo.server.security.SecurityOperation;
import org.apache.accumulo.server.tabletserver.TabletTime;
import org.apache.accumulo.server.trace.TraceFileSystem;
import org.apache.accumulo.server.util.MetadataTable;
import org.apache.accumulo.server.util.TablePropUtil;
import org.apache.accumulo.server.util.TabletOperations;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.Text;
import org.apache.log4j.Logger;
class TableInfo implements Serializable {
private static final long serialVersionUID = 1L;
String tableName;
String tableId;
char timeType;
String user;
public Map props;
}
class FinishCreateTable extends MasterRepo {
private static final long serialVersionUID = 1L;
private TableInfo tableInfo;
public FinishCreateTable(TableInfo ti) {
this.tableInfo = ti;
}
@Override
public long isReady(long tid, Master environment) throws Exception {
return 0;
}
@Override
public Repo call(long tid, Master env) throws Exception {
TableManager.getInstance().transitionTableState(tableInfo.tableId, TableState.ONLINE);
Utils.unreserveTable(tableInfo.tableId, tid, true);
env.getEventCoordinator().event("Created table %s ", tableInfo.tableName);
Logger.getLogger(FinishCreateTable.class).debug("Created table " + tableInfo.tableId + " " + tableInfo.tableName);
return null;
}
@Override
public String getReturn() {
return tableInfo.tableId;
}
@Override
public void undo(long tid, Master env) throws Exception {}
}
class PopulateMetadata extends MasterRepo {
private static final long serialVersionUID = 1L;
private TableInfo tableInfo;
PopulateMetadata(TableInfo ti) {
this.tableInfo = ti;
}
@Override
public long isReady(long tid, Master environment) throws Exception {
return 0;
}
@Override
public Repo call(long tid, Master environment) throws Exception {
KeyExtent extent = new KeyExtent(new Text(tableInfo.tableId), null, null);
MetadataTable.addTablet(extent, Constants.DEFAULT_TABLET_LOCATION, SecurityConstants.getSystemCredentials(), tableInfo.timeType,
environment.getMasterLock());
return new FinishCreateTable(tableInfo);
}
@Override
public void undo(long tid, Master environment) throws Exception {
MetadataTable.deleteTable(tableInfo.tableId, false, SecurityConstants.getSystemCredentials(), environment.getMasterLock());
}
}
class CreateDir extends MasterRepo {
private static final long serialVersionUID = 1L;
private TableInfo tableInfo;
CreateDir(TableInfo ti) {
this.tableInfo = ti;
}
@Override
public long isReady(long tid, Master environment) throws Exception {
return 0;
}
@Override
public Repo call(long tid, Master environment) throws Exception {
FileSystem fs = TraceFileSystem.wrap(FileUtil.getFileSystem(CachedConfiguration.getInstance(), ServerConfiguration.getSiteConfiguration()));
String dir = ServerConstants.getTablesDir() + "/" + tableInfo.tableId;
TabletOperations.createTabletDirectory(fs, dir, null);
return new PopulateMetadata(tableInfo);
}
@Override
public void undo(long tid, Master environment) throws Exception {
FileSystem fs = TraceFileSystem.wrap(FileUtil.getFileSystem(CachedConfiguration.getInstance(), ServerConfiguration.getSiteConfiguration()));
String dir = ServerConstants.getTablesDir() + "/" + tableInfo.tableId;
fs.delete(new Path(dir), true);
}
}
class PopulateZookeeper extends MasterRepo {
private static final long serialVersionUID = 1L;
private TableInfo tableInfo;
PopulateZookeeper(TableInfo ti) {
this.tableInfo = ti;
}
@Override
public long isReady(long tid, Master environment) throws Exception {
return Utils.reserveTable(tableInfo.tableId, tid, true, false, TableOperation.CREATE);
}
@Override
public Repo call(long tid, Master master) throws Exception {
// reserve the table name in zookeeper or fail
Utils.tableNameLock.lock();
try {
// write tableName & tableId to zookeeper
Instance instance = master.getInstance();
Utils.checkTableDoesNotExist(instance, tableInfo.tableName, tableInfo.tableId, TableOperation.CREATE);
TableManager.getInstance().addTable(tableInfo.tableId, tableInfo.tableName, NodeExistsPolicy.OVERWRITE);
for (Entry entry : tableInfo.props.entrySet())
TablePropUtil.setTableProperty(tableInfo.tableId, entry.getKey(), entry.getValue());
Tables.clearCache(instance);
return new CreateDir(tableInfo);
} finally {
Utils.tableNameLock.unlock();
}
}
@Override
public void undo(long tid, Master master) throws Exception {
Instance instance = master.getInstance();
TableManager.getInstance().removeTable(tableInfo.tableId);
Utils.unreserveTable(tableInfo.tableId, tid, true);
Tables.clearCache(instance);
}
}
class SetupPermissions extends MasterRepo {
private static final long serialVersionUID = 1L;
private TableInfo tableInfo;
public SetupPermissions(TableInfo ti) {
this.tableInfo = ti;
}
@Override
public Repo call(long tid, Master env) throws Exception {
// give all table permissions to the creator
SecurityOperation security = AuditedSecurityOperation.getInstance();
for (TablePermission permission : TablePermission.values()) {
try {
security.grantTablePermission(SecurityConstants.getSystemCredentials(), tableInfo.user, tableInfo.tableId, permission);
} catch (ThriftSecurityException e) {
Logger.getLogger(FinishCreateTable.class).error(e.getMessage(), e);
throw e;
}
}
// setup permissions in zookeeper before table info in zookeeper
// this way concurrent users will not get a spurious permission denied
// error
return new PopulateZookeeper(tableInfo);
}
@Override
public void undo(long tid, Master env) throws Exception {
AuditedSecurityOperation.getInstance().deleteTable(SecurityConstants.getSystemCredentials(), tableInfo.tableId);
}
}
public class CreateTable extends MasterRepo {
private static final long serialVersionUID = 1L;
private TableInfo tableInfo;
public CreateTable(String user, String tableName, TimeType timeType, Map props) {
tableInfo = new TableInfo();
tableInfo.tableName = tableName;
tableInfo.timeType = TabletTime.getTimeID(timeType);
tableInfo.user = user;
tableInfo.props = props;
}
@Override
public long isReady(long tid, Master environment) throws Exception {
return 0;
}
@Override
public Repo call(long tid, Master master) throws Exception {
// first step is to reserve a table id.. if the machine fails during this step
// it is ok to retry... the only side effect is that a table id may not be used
// or skipped
// assuming only the master process is creating tables
Utils.idLock.lock();
try {
tableInfo.tableId = Utils.getNextTableId(tableInfo.tableName, master.getInstance());
return new SetupPermissions(tableInfo);
} finally {
Utils.idLock.unlock();
}
}
@Override
public void undo(long tid, Master env) throws Exception {
// nothing to do, the table id was allocated!
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy