blob: e0aa69befcee8806a33cfb3cf4ea15490813724b [file] [log] [blame]
/*
* Copyright 2009-2010 by The Regents of the University of California
* Licensed 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 from
*
* 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 edu.uci.ics.asterix.metadata;
import java.util.ArrayList;
import edu.uci.ics.asterix.metadata.entities.Dataset;
import edu.uci.ics.asterix.metadata.entities.Datatype;
import edu.uci.ics.asterix.metadata.entities.Dataverse;
import edu.uci.ics.asterix.metadata.entities.Function;
import edu.uci.ics.asterix.metadata.entities.NodeGroup;
/**
* Used to implement serializable transactions against the MetadataCache.
* Assumes that the MetadataNode also provides serializable transactions. If the
* MetadataNode provides weaker guarantees than serializable, then you can
* expect update anomalies in the MetadataManager, e.g., because the
* MetadataCache could get polluted by a transaction reading an uncommitted
* write of another transaction, and putting the uncommitted entity in the
* MetadataCache. Logs the logical operations of a single transaction against
* the metadata. Once the transaction decides to commit, its log will be forward
* rolled against the MetadataCache. If it decides to abort, then its logs are
* simply discarded without changing the MetadataCache. Also provides a
* transaction-local "view" of its own uncommitted changes to the MetadataCache,
* to allow metadata transactions to read their uncommitted writes, without
* changing the MetadataCache. For example, think of what would happen if a
* transactions read its own uncommitted addDataset(), causing an update to the
* MetadataCache (the MetadataCache is immediately updated on reads, following
* the assumption that the MetadataNode won't allow reading uncommitted values).
* Another transaction might see this uncommitted dataset in the MetadataCache.
* This class is not thread safe. We assume that a metadata transaction consists
* of only one thread.
*/
public class MetadataTransactionContext extends MetadataCache {
// Keeps track of deleted metadata entities.
// An entity can either be in the droppedCache or in the inherited members
// of MetadataCache (the "added" entities).
// The APIs in this class make sure that these two caches are kept in sync.
protected MetadataCache droppedCache = new MetadataCache();
protected ArrayList<MetadataLogicalOperation> opLog = new ArrayList<MetadataLogicalOperation>();
private final long txnId;
public MetadataTransactionContext(long txnId) {
this.txnId = txnId;
}
public long getTxnId() {
return txnId;
}
public void addDataverse(Dataverse dataverse) {
droppedCache.dropDataverse(dataverse);
logAndApply(new MetadataLogicalOperation(dataverse, true));
}
public void addDataset(Dataset dataset) {
droppedCache.dropDataset(dataset);
logAndApply(new MetadataLogicalOperation(dataset, true));
}
public void addDatatype(Datatype datatype) {
droppedCache.dropDatatype(datatype);
logAndApply(new MetadataLogicalOperation(datatype, true));
}
public void addNogeGroup(NodeGroup nodeGroup) {
droppedCache.dropNodeGroup(nodeGroup);
logAndApply(new MetadataLogicalOperation(nodeGroup, true));
}
public void addFunction(Function function) {
droppedCache.dropFunction(function);
logAndApply(new MetadataLogicalOperation(function, true));
}
public void dropDataverse(String dataverseName) {
Dataverse dataverse = new Dataverse(dataverseName, null);
droppedCache.addDataverseIfNotExists(dataverse);
logAndApply(new MetadataLogicalOperation(dataverse, false));
}
public void dropDataset(String dataverseName, String datasetName) {
Dataset dataset = new Dataset(dataverseName, datasetName, null, null,
null);
droppedCache.addDatasetIfNotExists(dataset);
logAndApply(new MetadataLogicalOperation(dataset, false));
}
public void dropDataDatatype(String dataverseName, String datatypeName) {
Datatype datatype = new Datatype(dataverseName, datatypeName, null,
false);
droppedCache.addDatatypeIfNotExists(datatype);
logAndApply(new MetadataLogicalOperation(datatype, false));
}
public void dropNodeGroup(String nodeGroupName) {
NodeGroup nodeGroup = new NodeGroup(nodeGroupName, null);
droppedCache.addNodeGroupIfNotExists(nodeGroup);
logAndApply(new MetadataLogicalOperation(nodeGroup, false));
}
public void dropFunction(String dataverseName, String functionName,
int arity) {
Function function = new Function(dataverseName, functionName, arity,
null, null);
droppedCache.addFunctionIfNotExists(function);
logAndApply(new MetadataLogicalOperation(function, false));
}
public void logAndApply(MetadataLogicalOperation op) {
opLog.add(op);
doOperation(op);
}
public boolean dataverseIsDropped(String dataverseName) {
return droppedCache.getDataverse(dataverseName) != null;
}
public boolean datasetIsDropped(String dataverseName, String datasetName) {
if (droppedCache.getDataverse(dataverseName) != null) {
return true;
}
return droppedCache.getDataset(dataverseName, datasetName) != null;
}
public boolean datatypeIsDropped(String dataverseName, String datatypeName) {
if (droppedCache.getDataverse(dataverseName) != null) {
return true;
}
return droppedCache.getDatatype(dataverseName, datatypeName) != null;
}
public boolean nodeGroupIsDropped(String nodeGroup) {
return droppedCache.getNodeGroup(nodeGroup) != null;
}
public boolean functionIsDropped(String dataverseName, String functionName,
int arity) {
return droppedCache.getFunction(dataverseName, functionName, arity) != null;
}
public ArrayList<MetadataLogicalOperation> getOpLog() {
return opLog;
}
@Override
public void clear() {
super.clear();
droppedCache.clear();
opLog.clear();
}
}