You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@asterixdb.apache.org by mb...@apache.org on 2018/02/05 17:22:54 UTC

[3/3] asterixdb git commit: [NO ISSUE] More multi-CC support, ConfigManager updates

[NO ISSUE] More multi-CC support, ConfigManager updates

- add ability for OptionTypes to natively parse JsonNodes
- allow all options to be overridden at the NC level, not just NC options (i.e. common, cc)
- accept controller id from the CC, avoid configuring this on NCs
- update all CCs with metadata bootstrap, not just the primary CC
- remove TxnIdFactory static singleton, management by metadata node
- remove unused build-properties style test configs
- cleanup test iodevices

Change-Id: Iff60887bf71ce3f3ed7201afd9499612bfc83485
Reviewed-on: https://asterix-gerrit.ics.uci.edu/2344
Tested-by: Jenkins <je...@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <je...@fulliautomatix.ics.uci.edu>
Reviewed-by: Murtadha Hubail <mh...@apache.org>


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

Branch: refs/heads/master
Commit: d753479fe7516ac505c5b95ead07eb1762c2d453
Parents: ad758c5
Author: Michael Blow <mb...@apache.org>
Authored: Sun Feb 4 17:06:18 2018 -0500
Committer: Michael Blow <mb...@apache.org>
Committed: Mon Feb 5 09:19:57 2018 -0800

----------------------------------------------------------------------
 asterixdb/asterix-active/pom.xml                |   5 -
 .../asterix/active/DeployedJobService.java      |  17 +-
 .../apache/asterix/api/common/APIFramework.java |   3 +-
 .../asterix/app/nc/NCAppRuntimeContext.java     |  28 ++-
 .../app/nc/task/BindMetadataNodeTask.java       |  13 +-
 .../app/nc/task/ExportMetadataNodeTask.java     |  54 +++++
 .../app/replication/NcLifecycleCoordinator.java |  12 +-
 .../message/MetadataNodeRequestMessage.java     |   1 +
 .../hyracks/bootstrap/CCApplication.java        |   6 +-
 .../hyracks/bootstrap/NCApplication.java        |  14 +-
 .../asterix/messaging/NCMessageBroker.java      |   2 +-
 .../apache/asterix/utils/FlushDatasetUtil.java  |   3 +-
 .../org/apache/asterix/utils/RebalanceUtil.java |   3 +-
 .../resources/asterix-build-configuration.xml   | 112 ---------
 .../resources/asterix-build-configuration2.xml  | 111 ---------
 .../resources/asterix-build-configuration3.xml  | 111 ---------
 .../resources/asterix-build-configuration4.xml  |  87 -------
 .../asterix-app/src/main/resources/cc-rep.conf  |   4 +-
 .../asterix-app/src/main/resources/cc.conf      |   4 +-
 .../asterix-app/src/main/resources/cc2.conf     |   4 +-
 .../asterix-app/src/main/resources/cc3.conf     |   4 +-
 .../asterix-app/src/main/resources/cc4.conf     |   4 +-
 .../asterix-app/src/main/resources/cluster.xml  |  56 -----
 .../asterix-app/src/main/resources/log4j2.xml   |   1 +
 .../src/test/resources/log4j2-test.xml          |  15 +-
 .../common/api/INcApplicationContext.java       |   8 +
 .../common/dataflow/ICcApplicationContext.java  |   6 +
 .../common/transactions/ILongBlockFactory.java  |  40 ++++
 .../transactions/ITxnIdBlockProvider.java       |  47 ++++
 .../common/transactions/ITxnIdFactory.java      |  38 +++
 .../asterix/metadata/BulkTxnIdFactory.java      |  47 ++++
 .../asterix/metadata/MetadataManager.java       | 100 ++++++--
 .../apache/asterix/metadata/MetadataNode.java   |  12 +
 .../asterix/metadata/api/IMetadataNode.java     |  24 +-
 .../metadata/bootstrap/AsterixStateProxy.java   |   1 +
 .../metadata/declared/MetadataProvider.java     |   5 +
 .../asterix/metadata/utils/IndexUtil.java       |   6 +-
 .../message/ReportLocalCountersMessage.java     |  18 +-
 .../runtime/utils/CcApplicationContext.java     |  11 +-
 .../asterix/runtime/utils/CcTxnIdFactory.java   |  86 +++++++
 .../testframework/xml/TestSuiteParser.java      |  11 +-
 .../service/transaction/TxnIdFactory.java       |  42 ----
 .../api/client/ClusterControllerInfo.java       |  11 +-
 .../apache/hyracks/api/config/IOptionType.java  |   6 +
 .../org/apache/hyracks/api/control/CcId.java    |   4 +
 .../api/control/CcIdPartitionedLongFactory.java |  65 ++++++
 .../java/org/apache/hyracks/api/job/JobId.java  |  25 +-
 .../apache/hyracks/api/job/JobIdFactory.java    |  31 +--
 .../hyracks/api/job/JobIdFactoryTest.java       | 118 ----------
 .../org/apache/hyracks/api/job/JobIdTest.java   | 135 +++++++++++
 .../control/cc/ClusterControllerService.java    |   2 +-
 .../cc/application/CCServiceContext.java        |   4 -
 .../control/cc/work/RegisterNodeWork.java       |   1 +
 .../control/common/base/IClusterController.java |   2 -
 .../control/common/config/ConfigManager.java    |  71 +++---
 .../control/common/config/OptionTypes.java      |  76 +++++-
 .../control/common/controllers/NCConfig.java    |   7 -
 .../common/controllers/NodeParameters.java      |  10 +
 .../common/controllers/NodeRegistration.java    |  13 +-
 .../ipc/ClusterControllerRemoteProxy.java       |  11 +-
 .../apache/hyracks/control/nc/CcConnection.java |  77 ++++++
 .../org/apache/hyracks/control/nc/NCDriver.java |   2 +-
 .../control/nc/NodeControllerService.java       | 233 +++++++++++--------
 .../nc/application/NCServiceContext.java        |   4 +-
 .../apache/hyracks/control/nc/io/IOManager.java |   7 +-
 hyracks-fullstack/hyracks/hyracks-util/pom.xml  |   4 +
 .../org/apache/hyracks/util/file/FileUtil.java  |  21 ++
 .../src/test/resources/log4j2-test.xml          |   8 +-
 68 files changed, 1179 insertions(+), 945 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-active/pom.xml
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-active/pom.xml b/asterixdb/asterix-active/pom.xml
index a73175a..9c7ca5f 100644
--- a/asterixdb/asterix-active/pom.xml
+++ b/asterixdb/asterix-active/pom.xml
@@ -34,11 +34,6 @@
       <version>${project.version}</version>
     </dependency>
     <dependency>
-      <groupId>org.apache.asterix</groupId>
-      <artifactId>asterix-transactions</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
       <groupId>org.apache.hyracks</groupId>
       <artifactId>hyracks-api</artifactId>
     </dependency>

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-active/src/main/java/org/apache/asterix/active/DeployedJobService.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-active/src/main/java/org/apache/asterix/active/DeployedJobService.java b/asterixdb/asterix-active/src/main/java/org/apache/asterix/active/DeployedJobService.java
index e12c5ca..bc6f1b1 100644
--- a/asterixdb/asterix-active/src/main/java/org/apache/asterix/active/DeployedJobService.java
+++ b/asterixdb/asterix-active/src/main/java/org/apache/asterix/active/DeployedJobService.java
@@ -25,7 +25,7 @@ import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
 
-import org.apache.asterix.transaction.management.service.transaction.TxnIdFactory;
+import org.apache.asterix.common.transactions.ITxnIdFactory;
 import org.apache.hyracks.api.client.IHyracksClientConnection;
 import org.apache.hyracks.api.job.DeployedJobSpecId;
 import org.apache.hyracks.api.job.JobId;
@@ -48,13 +48,15 @@ public class DeployedJobService {
 
     //Starts running a deployed job specification periodically with an interval of "duration" seconds
     public static ScheduledExecutorService startRepetitiveDeployedJobSpec(DeployedJobSpecId distributedId,
-            IHyracksClientConnection hcc, long duration, Map<byte[], byte[]> jobParameters, EntityId entityId) {
+            IHyracksClientConnection hcc, long duration, Map<byte[], byte[]> jobParameters, EntityId entityId,
+            ITxnIdFactory txnIdFactory) {
         ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(POOL_SIZE);
         scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
             @Override
             public void run() {
                 try {
-                    if (!runRepetitiveDeployedJobSpec(distributedId, hcc, jobParameters, duration, entityId)) {
+                    if (!runRepetitiveDeployedJobSpec(distributedId, hcc, jobParameters, duration, entityId,
+                            txnIdFactory)) {
                         scheduledExecutorService.shutdown();
                     }
                 } catch (Exception e) {
@@ -67,8 +69,9 @@ public class DeployedJobService {
     }
 
     public static boolean runRepetitiveDeployedJobSpec(DeployedJobSpecId distributedId, IHyracksClientConnection hcc,
-            Map<byte[], byte[]> jobParameters, long duration, EntityId entityId) throws Exception {
-        long executionMilliseconds = runDeployedJobSpec(distributedId, hcc, jobParameters, entityId);
+            Map<byte[], byte[]> jobParameters, long duration, EntityId entityId, ITxnIdFactory txnIdFactory)
+            throws Exception {
+        long executionMilliseconds = runDeployedJobSpec(distributedId, hcc, jobParameters, entityId, txnIdFactory);
         if (executionMilliseconds > duration && LOGGER.isErrorEnabled()) {
             LOGGER.log(Level.ERROR,
                     "Periodic job for " + entityId.getExtensionName() + " " + entityId.getDataverse() + "."
@@ -81,12 +84,12 @@ public class DeployedJobService {
     }
 
     public synchronized static long runDeployedJobSpec(DeployedJobSpecId distributedId, IHyracksClientConnection hcc,
-            Map<byte[], byte[]> jobParameters, EntityId entityId) throws Exception {
+            Map<byte[], byte[]> jobParameters, EntityId entityId, ITxnIdFactory txnIdFactory) throws Exception {
         JobId jobId;
         long startTime = Instant.now().toEpochMilli();
 
         //Add the Asterix Transaction Id to the map
-        jobParameters.put(TRANSACTION_ID_PARAMETER_NAME, String.valueOf(TxnIdFactory.create().getId()).getBytes());
+        jobParameters.put(TRANSACTION_ID_PARAMETER_NAME, String.valueOf(txnIdFactory.create().getId()).getBytes());
         jobId = hcc.startJob(distributedId, jobParameters);
 
         hcc.waitForCompletion(jobId);

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
index a18277e..189a7e1 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
@@ -65,7 +65,6 @@ import org.apache.asterix.lang.common.util.FunctionUtil;
 import org.apache.asterix.metadata.declared.MetadataProvider;
 import org.apache.asterix.optimizer.base.FuzzyUtils;
 import org.apache.asterix.runtime.job.listener.JobEventListenerFactory;
-import org.apache.asterix.transaction.management.service.transaction.TxnIdFactory;
 import org.apache.asterix.translator.CompiledStatements.ICompiledDmlStatement;
 import org.apache.asterix.translator.IStatementExecutor.Stats;
 import org.apache.asterix.translator.SessionConfig;
@@ -220,7 +219,7 @@ public class APIFramework {
             printPlanPostfix(output);
         }
 
-        final TxnId txnId = TxnIdFactory.create();
+        final TxnId txnId = metadataProvider.getTxnIdFactory().create();
         metadataProvider.setTxnId(txnId);
         ILangExpressionToPlanTranslator t =
                 translatorFactory.createExpressionToPlanTranslator(metadataProvider, varCounter);

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/NCAppRuntimeContext.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/NCAppRuntimeContext.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/NCAppRuntimeContext.java
index 366438a..1de6938 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/NCAppRuntimeContext.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/NCAppRuntimeContext.java
@@ -25,6 +25,8 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.stream.Collectors;
@@ -77,6 +79,7 @@ import org.apache.hyracks.api.application.INCServiceContext;
 import org.apache.hyracks.api.client.ClusterControllerInfo;
 import org.apache.hyracks.api.client.HyracksConnection;
 import org.apache.hyracks.api.client.IHyracksClientConnection;
+import org.apache.hyracks.api.control.CcId;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
 import org.apache.hyracks.api.io.IIOManager;
 import org.apache.hyracks.api.lifecycle.ILifeCycleComponent;
@@ -414,20 +417,21 @@ public class NCAppRuntimeContext implements INcApplicationContext {
 
     @Override
     public void initializeMetadata(boolean newUniverse) throws Exception {
-        IAsterixStateProxy proxy;
         LOGGER.info("Bootstrapping metadata");
         MetadataNode.INSTANCE.initialize(this, ncExtensionManager.getMetadataTupleTranslatorProvider(),
                 ncExtensionManager.getMetadataExtensions());
 
-        proxy = (IAsterixStateProxy) getServiceContext().getDistributedState();
-        if (proxy == null) {
+        //noinspection unchecked
+        ConcurrentHashMap<CcId, IAsterixStateProxy> proxyMap =
+                (ConcurrentHashMap<CcId, IAsterixStateProxy>) getServiceContext().getDistributedState();
+        if (proxyMap == null) {
             throw new IllegalStateException("Metadata node cannot access distributed state");
         }
 
         // This is a special case, we just give the metadataNode directly.
         // This way we can delay the registration of the metadataNode until
         // it is completely initialized.
-        MetadataManager.initialize(proxy, MetadataNode.INSTANCE);
+        MetadataManager.initialize(proxyMap.values(), MetadataNode.INSTANCE);
         MetadataBootstrap.startUniverse(getServiceContext(), newUniverse);
         MetadataBootstrap.startDDLRecovery();
         ncExtensionManager.initializeMetadata(getServiceContext());
@@ -440,7 +444,6 @@ public class NCAppRuntimeContext implements INcApplicationContext {
             metadataNodeStub = (IMetadataNode) UnicastRemoteObject.exportObject(MetadataNode.INSTANCE,
                     getMetadataProperties().getMetadataPort());
         }
-        ((IAsterixStateProxy) getServiceContext().getDistributedState()).setMetadataNode(metadataNodeStub);
     }
 
     @Override
@@ -451,6 +454,17 @@ public class NCAppRuntimeContext implements INcApplicationContext {
         metadataNodeStub = null;
     }
 
+    @Override
+    public synchronized void bindMetadataNodeStub(CcId ccId) throws RemoteException {
+        if (metadataNodeStub == null) {
+            throw new IllegalStateException("Metadata node not exported");
+
+        }
+        //noinspection unchecked
+        ((ConcurrentMap<CcId, IAsterixStateProxy>) getServiceContext().getDistributedState()).get(ccId)
+                .setMetadataNode(metadataNodeStub);
+    }
+
     public NCExtensionManager getNcExtensionManager() {
         return ncExtensionManager;
     }
@@ -472,7 +486,9 @@ public class NCAppRuntimeContext implements INcApplicationContext {
                 if (hcc == null || !hcc.isConnected()) {
                     try {
                         NodeControllerService ncSrv = (NodeControllerService) ncServiceContext.getControllerService();
-                        ClusterControllerInfo ccInfo = ncSrv.getNodeParameters().getClusterControllerInfo();
+                        // TODO(mblow): multicc
+                        CcId primaryCcId = ncSrv.getPrimaryCcId();
+                        ClusterControllerInfo ccInfo = ncSrv.getNodeParameters(primaryCcId).getClusterControllerInfo();
                         hcc = new HyracksConnection(ccInfo.getClientNetAddress(), ccInfo.getClientNetPort());
                     } catch (Exception e) {
                         throw HyracksDataException.create(e);

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/task/BindMetadataNodeTask.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/task/BindMetadataNodeTask.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/task/BindMetadataNodeTask.java
index e41bc60..701cb96 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/task/BindMetadataNodeTask.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/task/BindMetadataNodeTask.java
@@ -27,21 +27,12 @@ import org.apache.hyracks.api.service.IControllerService;
 public class BindMetadataNodeTask implements INCLifecycleTask {
 
     private static final long serialVersionUID = 1L;
-    private final boolean exportStub;
-
-    public BindMetadataNodeTask(boolean exportStub) {
-        this.exportStub = exportStub;
-    }
 
     @Override
     public void perform(CcId ccId, IControllerService cs) throws HyracksDataException {
         INcApplicationContext appContext = (INcApplicationContext) cs.getApplicationContext();
         try {
-            if (exportStub) {
-                appContext.exportMetadataNodeStub();
-            } else {
-                appContext.unexportMetadataNodeStub();
-            }
+            appContext.bindMetadataNodeStub(ccId);
         } catch (Exception e) {
             throw HyracksDataException.create(e);
         }
@@ -49,6 +40,6 @@ public class BindMetadataNodeTask implements INCLifecycleTask {
 
     @Override
     public String toString() {
-        return "{ \"class\" : \"" + getClass().getSimpleName() + "\", \"export-stub\" : " + exportStub + " }";
+        return "{ \"class\" : \"" + getClass().getSimpleName() + "\" }";
     }
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/task/ExportMetadataNodeTask.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/task/ExportMetadataNodeTask.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/task/ExportMetadataNodeTask.java
new file mode 100644
index 0000000..c833850
--- /dev/null
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/task/ExportMetadataNodeTask.java
@@ -0,0 +1,54 @@
+/*
+ * 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.asterix.app.nc.task;
+
+import org.apache.asterix.common.api.INCLifecycleTask;
+import org.apache.asterix.common.api.INcApplicationContext;
+import org.apache.hyracks.api.control.CcId;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.api.service.IControllerService;
+
+public class ExportMetadataNodeTask implements INCLifecycleTask {
+
+    private static final long serialVersionUID = 1L;
+    private final boolean exportStub;
+
+    public ExportMetadataNodeTask(boolean exportStub) {
+        this.exportStub = exportStub;
+    }
+
+    @Override
+    public void perform(CcId ccId, IControllerService cs) throws HyracksDataException {
+        INcApplicationContext appContext = (INcApplicationContext) cs.getApplicationContext();
+        try {
+            if (exportStub) {
+                appContext.exportMetadataNodeStub();
+            } else {
+                appContext.unexportMetadataNodeStub();
+            }
+        } catch (Exception e) {
+            throw HyracksDataException.create(e);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "{ \"class\" : \"" + getClass().getSimpleName() + "\", \"export-stub\" : " + exportStub + " }";
+    }
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/replication/NcLifecycleCoordinator.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/replication/NcLifecycleCoordinator.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/replication/NcLifecycleCoordinator.java
index 980375d..8939059 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/replication/NcLifecycleCoordinator.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/replication/NcLifecycleCoordinator.java
@@ -27,6 +27,7 @@ import java.util.stream.Collectors;
 
 import org.apache.asterix.app.nc.task.BindMetadataNodeTask;
 import org.apache.asterix.app.nc.task.CheckpointTask;
+import org.apache.asterix.app.nc.task.ExportMetadataNodeTask;
 import org.apache.asterix.app.nc.task.ExternalLibrarySetupTask;
 import org.apache.asterix.app.nc.task.LocalRecoveryTask;
 import org.apache.asterix.app.nc.task.MetadataBootstrapTask;
@@ -157,21 +158,20 @@ public class NcLifecycleCoordinator implements INcLifecycleCoordinator {
             tasks.add(new MetadataBootstrapTask());
         }
         tasks.add(new ExternalLibrarySetupTask(isMetadataNode));
-        tasks.add(new ReportLocalCountersTask());
         tasks.add(new CheckpointTask());
         tasks.add(new StartLifecycleComponentsTask());
         if (isMetadataNode) {
-            tasks.add(new BindMetadataNodeTask(true));
+            tasks.add(new ExportMetadataNodeTask(true));
+            tasks.add(new BindMetadataNodeTask());
         }
+        tasks.add(new ReportLocalCountersTask());
         return tasks;
     }
 
     protected List<INCLifecycleTask> buildActiveNCRegTasks(boolean metadataNode) {
         final List<INCLifecycleTask> tasks = new ArrayList<>();
         if (metadataNode) {
-            // need to unbind from old distributed state then rebind to new one
-            tasks.add(new BindMetadataNodeTask(false));
-            tasks.add(new BindMetadataNodeTask(true));
+            tasks.add(new BindMetadataNodeTask());
         }
         tasks.add(new ReportLocalCountersTask());
         return tasks;
@@ -182,7 +182,7 @@ public class NcLifecycleCoordinator implements INcLifecycleCoordinator {
         if (metadataNodeId.equals(node)) {
             return;
         }
-        // if current metadata node is active, we need to unbind its metadata proxy object
+        // if current metadata node is active, we need to unbind its metadata proxy objects
         if (clusterManager.isMetadataNodeActive()) {
             MetadataNodeRequestMessage msg = new MetadataNodeRequestMessage(false);
             try {

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/replication/message/MetadataNodeRequestMessage.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/replication/message/MetadataNodeRequestMessage.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/replication/message/MetadataNodeRequestMessage.java
index a8c98c7..4443825 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/replication/message/MetadataNodeRequestMessage.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/replication/message/MetadataNodeRequestMessage.java
@@ -47,6 +47,7 @@ public class MetadataNodeRequestMessage extends CcIdentifiedMessage
             if (export) {
                 appContext.initializeMetadata(false);
                 appContext.exportMetadataNodeStub();
+                appContext.bindMetadataNodeStub(getCcId());
             } else {
                 appContext.unexportMetadataNodeStub();
             }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/CCApplication.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/CCApplication.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/CCApplication.java
index 1cefd42..551e6aa 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/CCApplication.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/CCApplication.java
@@ -152,13 +152,13 @@ public class CCApplication extends BaseCCApplication {
         appCtx.setExtensionManager(ccExtensionManager);
         final CCConfig ccConfig = controllerService.getCCConfig();
         if (System.getProperty("java.rmi.server.hostname") == null) {
-            System.setProperty("java.rmi.server.hostname", ccConfig.getClusterListenAddress());
+            System.setProperty("java.rmi.server.hostname", ccConfig.getClusterPublicAddress());
         }
         MetadataProperties metadataProperties = appCtx.getMetadataProperties();
 
         setAsterixStateProxy(AsterixStateProxy.registerRemoteObject(metadataProperties.getMetadataCallbackPort()));
         ccServiceCtx.setDistributedState(proxy);
-        MetadataManager.initialize(proxy, metadataProperties);
+        MetadataManager.initialize(proxy, metadataProperties, appCtx);
         ccServiceCtx.addJobLifecycleListener(appCtx.getActiveNotificationHandler());
 
         // create event loop groups
@@ -178,7 +178,7 @@ public class CCApplication extends BaseCCApplication {
             throws AlgebricksException, IOException {
         return new CcApplicationContext(ccServiceCtx, getHcc(), libraryManager, () -> MetadataManager.INSTANCE,
                 globalRecoveryManager, lifecycleCoordinator, new ActiveNotificationHandler(), componentProvider,
-                new MetadataLockManager());
+                new MetadataLockManager(), MetadataManager::getTxnIdBlockFactory);
     }
 
     protected GlobalRecoveryManager createGlobalRecoveryManager() throws Exception {

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/NCApplication.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/NCApplication.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/NCApplication.java
index a23a763..1220462 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/NCApplication.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/NCApplication.java
@@ -199,22 +199,20 @@ public class NCApplication extends BaseNCApplication {
                 && (nodeProperties.isInitialRun() || nodeProperties.isVirtualNc())) {
             state = SystemState.BOOTSTRAPPING;
         }
-        // Request registration tasks from CC
-        // TODO (mblow): multicc
+        // Request registration tasks from CC (we only do this from our primary CC, in the case of multiple CCs)
         final NodeControllerService ncControllerService = (NodeControllerService) ncServiceCtx.getControllerService();
-        RegistrationTasksRequestMessage.send(ncControllerService.getPrimaryClusterController().getCcId(),
-                ncControllerService, NodeStatus.BOOTING, state);
+        RegistrationTasksRequestMessage.send(ncControllerService.getPrimaryCcId(), ncControllerService,
+                NodeStatus.BOOTING, state);
         startupCompleted = true;
     }
 
     @Override
     public void onRegisterNode(CcId ccId) throws Exception {
-        // TODO (mblow): multicc
-        if (startupCompleted && ccId.equals(((NodeControllerService) ncServiceCtx.getControllerService())
-                .getPrimaryClusterController().getCcId())) {
+        if (startupCompleted) {
             /*
              * If the node completed its startup before, then this is a re-registration with
-             * the CC and therefore the system state should be HEALTHY and the node status is ACTIVE
+             * the primary (or supplemental) CC and therefore the system state should be HEALTHY and the node status
+             * is ACTIVE
              */
             RegistrationTasksRequestMessage.send(ccId, (NodeControllerService) ncServiceCtx.getControllerService(),
                     NodeStatus.ACTIVE, SystemState.HEALTHY);

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-app/src/main/java/org/apache/asterix/messaging/NCMessageBroker.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/messaging/NCMessageBroker.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/messaging/NCMessageBroker.java
index 22458d3..7a74940 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/messaging/NCMessageBroker.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/messaging/NCMessageBroker.java
@@ -75,7 +75,7 @@ public class NCMessageBroker implements INCMessageBroker {
 
     @Override
     public void sendMessageToPrimaryCC(ICcAddressedMessage message) throws Exception {
-        sendMessageToCC(ncs.getPrimaryClusterController().getCcId(), message);
+        sendMessageToCC(ncs.getPrimaryCcId(), message);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-app/src/main/java/org/apache/asterix/utils/FlushDatasetUtil.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/utils/FlushDatasetUtil.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/utils/FlushDatasetUtil.java
index f446c4b..c37d8cc 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/utils/FlushDatasetUtil.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/utils/FlushDatasetUtil.java
@@ -26,7 +26,6 @@ import org.apache.asterix.metadata.declared.MetadataProvider;
 import org.apache.asterix.metadata.entities.Dataset;
 import org.apache.asterix.runtime.job.listener.JobEventListenerFactory;
 import org.apache.asterix.runtime.operators.std.FlushDatasetOperatorDescriptor;
-import org.apache.asterix.transaction.management.service.transaction.TxnIdFactory;
 import org.apache.hyracks.algebricks.common.constraints.AlgebricksPartitionConstraint;
 import org.apache.hyracks.algebricks.common.constraints.AlgebricksPartitionConstraintHelper;
 import org.apache.hyracks.algebricks.common.utils.Pair;
@@ -60,7 +59,7 @@ public class FlushDatasetUtil {
         AlgebricksMetaOperatorDescriptor emptySource = new AlgebricksMetaOperatorDescriptor(spec, 0, 1,
                 new IPushRuntimeFactory[] { new EmptyTupleSourceRuntimeFactory() }, rDescs);
 
-        TxnId txnId = TxnIdFactory.create();
+        TxnId txnId = metadataProvider.getTxnIdFactory().create();
         FlushDatasetOperatorDescriptor flushOperator =
                 new FlushDatasetOperatorDescriptor(spec, txnId, dataset.getDatasetId());
 

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-app/src/main/java/org/apache/asterix/utils/RebalanceUtil.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/utils/RebalanceUtil.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/utils/RebalanceUtil.java
index 80275a5..7bb917f 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/utils/RebalanceUtil.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/utils/RebalanceUtil.java
@@ -47,7 +47,6 @@ import org.apache.asterix.metadata.utils.DatasetUtil;
 import org.apache.asterix.metadata.utils.IndexUtil;
 import org.apache.asterix.rebalance.IDatasetRebalanceCallback;
 import org.apache.asterix.runtime.job.listener.JobEventListenerFactory;
-import org.apache.asterix.transaction.management.service.transaction.TxnIdFactory;
 import org.apache.hyracks.algebricks.common.constraints.AlgebricksPartitionConstraint;
 import org.apache.hyracks.algebricks.common.constraints.AlgebricksPartitionConstraintHelper;
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
@@ -284,7 +283,7 @@ public class RebalanceUtil {
     private static void populateDataToRebalanceTarget(Dataset source, Dataset target, MetadataProvider metadataProvider,
             IHyracksClientConnection hcc) throws Exception {
         JobSpecification spec = new JobSpecification();
-        TxnId txnId = TxnIdFactory.create();
+        TxnId txnId = metadataProvider.getTxnIdFactory().create();
         JobEventListenerFactory jobEventListenerFactory = new JobEventListenerFactory(txnId, true);
         spec.setJobletEventListenerFactory(jobEventListenerFactory);
 

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-app/src/main/resources/asterix-build-configuration.xml
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/resources/asterix-build-configuration.xml b/asterixdb/asterix-app/src/main/resources/asterix-build-configuration.xml
deleted file mode 100644
index 7eba9eb..0000000
--- a/asterixdb/asterix-app/src/main/resources/asterix-build-configuration.xml
+++ /dev/null
@@ -1,112 +0,0 @@
-<!--
- ! 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.
- !-->
-<asterixConfiguration xmlns="asterixconf">
-  <metadataNode>asterix_nc1</metadataNode>
-  <store>
-    <ncId>asterix_nc1</ncId>
-    <storeDirs>iodevice0,iodevice1</storeDirs>
-  </store>
-  <store>
-    <ncId>asterix_nc2</ncId>
-    <storeDirs>iodevice0,iodevice1</storeDirs>
-  </store>
-  <transactionLogDir>
-    <ncId>asterix_nc1</ncId>
-    <txnLogDirPath>target/txnLogDir/asterix_nc1</txnLogDirPath>
-  </transactionLogDir>
-  <transactionLogDir>
-    <ncId>asterix_nc2</ncId>
-    <txnLogDirPath>target/txnLogDir/asterix_nc2</txnLogDirPath>
-  </transactionLogDir>
-
-  <property>
-    <name>max.wait.active.cluster</name>
-    <value>60</value>
-    <description>Maximum wait (in seconds) for a cluster to be ACTIVE (all
-      nodes are available)
-      before a submitted query/statement can be
-      executed. (Default = 60 seconds)
-    </description>
-  </property>
-
-  <property>
-    <name>compiler.framesize</name>
-    <value>32KB</value>
-  </property>
-  <property>
-    <name>compiler.sortmemory</name>
-    <value>320KB</value>
-  </property>
-  <property>
-    <name>compiler.groupmemory</name>
-    <value>160KB</value>
-  </property>
-  <property>
-    <name>compiler.joinmemory</name>
-    <value>256KB</value>
-  </property>
-  <property>
-    <name>storage.buffercache.pagesize</name>
-    <value>32KB</value>
-    <description>The page size in bytes for pages in the buffer cache.
-      (Default = "128KB")
-    </description>
-  </property>
-  <property>
-    <name>storage.buffercache.size</name>
-    <value>48MB</value>
-    <description>The size of memory allocated to the disk buffer cache.
-      The value should be a multiple of the buffer cache page size.
-    </description>
-  </property>
-  <property>
-    <name>storage.memorycomponent.numpages</name>
-    <value>16</value>
-    <description>The number of pages to allocate for a memory component.
-      This budget is shared by all the memory components of the primary
-      index and all its secondary indexes across all I/O devices on a node.
-      Note: in-memory components usually has fill factor of 75% since
-      the pages are 75% full and the remaining 25% is un-utilized.
-    </description>
-  </property>
-  <property>
-    <name>storage.memorycomponent.globalbudget</name>
-    <value>512MB</value>
-    <description>The size of memory allocated to the memory components.
-      The value should be a multiple of the memory component page size.
-    </description>
-  </property>
-  <property>
-    <name>messaging.frame.size</name>
-    <value>4096</value>
-    <description>The frame size to be used for NC to NC messaging. (Default = 4kb)
-    </description>
-  </property>
-  <property>
-    <name>messaging.frame.count</name>
-    <value>512</value>
-    <description>Number of reusable frames for NC to NC messaging. (Default = 512)
-    </description>
-  </property>
-  <property>
-    <name>log.level</name>
-    <value>INFO</value>
-    <description>foo</description>
-  </property>
-</asterixConfiguration>

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-app/src/main/resources/asterix-build-configuration2.xml
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/resources/asterix-build-configuration2.xml b/asterixdb/asterix-app/src/main/resources/asterix-build-configuration2.xml
deleted file mode 100644
index af17901..0000000
--- a/asterixdb/asterix-app/src/main/resources/asterix-build-configuration2.xml
+++ /dev/null
@@ -1,111 +0,0 @@
-<!--
- ! 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.
- !-->
-<asterixConfiguration xmlns="asterixconf">
-    <metadataNode>asterix_nc1</metadataNode>
-    <store>
-        <ncId>asterix_nc1</ncId>
-        <storeDirs>iodevice0,iodevice1</storeDirs>
-    </store>
-    <store>
-        <ncId>asterix_nc2</ncId>
-        <storeDirs>iodevice0,iodevice1</storeDirs>
-    </store>
-    <transactionLogDir>
-        <ncId>asterix_nc1</ncId>
-        <txnLogDirPath>target/txnLogDir/asterix_nc1</txnLogDirPath>
-    </transactionLogDir>
-    <transactionLogDir>
-        <ncId>asterix_nc2</ncId>
-        <txnLogDirPath>target/txnLogDir/asterix_nc2</txnLogDirPath>
-    </transactionLogDir>
-
-    <property>
-        <name>max.wait.active.cluster</name>
-        <value>60</value>
-        <description>Maximum wait (in seconds) for a cluster to be ACTIVE (all
-            nodes are available)
-            before a submitted query/statement can be
-            executed. (Default = 60 seconds)
-        </description>
-    </property>
-
-    <property>
-        <name>compiler.framesize</name>
-        <value>32KB</value>
-    </property>
-    <property>
-        <name>compiler.sortmemory</name>
-        <value>320KB</value>
-    </property>
-    <property>
-        <name>compiler.groupmemory</name>
-        <value>160KB</value>
-    </property>
-    <property>
-        <name>compiler.joinmemory</name>
-        <value>256KB</value>
-    </property>
-    <property>
-        <name>compiler.parallelism</name>
-        <value>-1</value>
-    </property>
-    <property>
-        <name>storage.buffercache.pagesize</name>
-        <value>32KB</value>
-        <description>The page size in bytes for pages in the buffer cache.
-            (Default = "128KB")
-        </description>
-    </property>
-    <property>
-        <name>storage.buffercache.size</name>
-        <value>48MB</value>
-        <description>The size of memory allocated to the disk buffer cache.
-            The value should be a multiple of the buffer cache page size.
-        </description>
-    </property>
-    <property>
-        <name>storage.memorycomponent.numpages</name>
-        <value>8</value>
-        <description>The number of pages to allocate for a memory component.
-            This budget is shared by all the memory components of the primary
-            index and all its secondary indexes across all I/O devices on a node.
-            Note: in-memory components usually has fill factor of 75% since
-            the pages are 75% full and the remaining 25% is un-utilized.
-        </description>
-    </property>
-    <property>
-        <name>storage.memorycomponent.globalbudget</name>
-        <value>512MB</value>
-        <description>The size of memory allocated to the memory components.
-            The value should be a multiple of the memory component page size.
-        </description>
-    </property>
-    <property>
-        <name>messaging.frame.size</name>
-        <value>4096</value>
-        <description>The frame size to be used for NC to NC messaging. (Default = 4kb)
-        </description>
-    </property>
-    <property>
-        <name>messaging.frame.count</name>
-        <value>512</value>
-        <description>Number of reusable frames for NC to NC messaging. (Default = 512)
-        </description>
-    </property>
-</asterixConfiguration>

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-app/src/main/resources/asterix-build-configuration3.xml
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/resources/asterix-build-configuration3.xml b/asterixdb/asterix-app/src/main/resources/asterix-build-configuration3.xml
deleted file mode 100644
index 06ac7b5..0000000
--- a/asterixdb/asterix-app/src/main/resources/asterix-build-configuration3.xml
+++ /dev/null
@@ -1,111 +0,0 @@
-<!--
- ! 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.
- !-->
-<asterixConfiguration xmlns="asterixconf">
-    <metadataNode>asterix_nc1</metadataNode>
-    <store>
-        <ncId>asterix_nc1</ncId>
-        <storeDirs>iodevice0,iodevice1</storeDirs>
-    </store>
-    <store>
-        <ncId>asterix_nc2</ncId>
-        <storeDirs>iodevice0,iodevice1</storeDirs>
-    </store>
-    <transactionLogDir>
-        <ncId>asterix_nc1</ncId>
-        <txnLogDirPath>target/txnLogDir/asterix_nc1</txnLogDirPath>
-    </transactionLogDir>
-    <transactionLogDir>
-        <ncId>asterix_nc2</ncId>
-        <txnLogDirPath>target/txnLogDir/asterix_nc2</txnLogDirPath>
-    </transactionLogDir>
-
-    <property>
-        <name>max.wait.active.cluster</name>
-        <value>60</value>
-        <description>Maximum wait (in seconds) for a cluster to be ACTIVE (all
-            nodes are available)
-            before a submitted query/statement can be
-            executed. (Default = 60 seconds)
-        </description>
-    </property>
-
-    <property>
-        <name>compiler.framesize</name>
-        <value>32KB</value>
-    </property>
-    <property>
-        <name>compiler.sortmemory</name>
-        <value>320KB</value>
-    </property>
-    <property>
-        <name>compiler.groupmemory</name>
-        <value>160KB</value>
-    </property>
-    <property>
-        <name>compiler.joinmemory</name>
-        <value>256KB</value>
-    </property>
-    <property>
-        <name>compiler.parallelism</name>
-        <value>3</value>
-    </property>
-    <property>
-        <name>storage.buffercache.pagesize</name>
-        <value>32KB</value>
-        <description>The page size in bytes for pages in the buffer cache.
-            (Default = "128KB")
-        </description>
-    </property>
-    <property>
-        <name>storage.buffercache.size</name>
-        <value>48MB</value>
-        <description>The size of memory allocated to the disk buffer cache.
-            The value should be a multiple of the buffer cache page size.
-        </description>
-    </property>
-    <property>
-        <name>storage.memorycomponent.numpages</name>
-        <value>8</value>
-        <description>The number of pages to allocate for a memory component.
-            This budget is shared by all the memory components of the primary
-            index and all its secondary indexes across all I/O devices on a node.
-            Note: in-memory components usually has fill factor of 75% since
-            the pages are 75% full and the remaining 25% is un-utilized.
-        </description>
-    </property>
-    <property>
-        <name>storage.memorycomponent.globalbudget</name>
-        <value>512MB</value>
-        <description>The size of memory allocated to the memory components.
-            The value should be a multiple of the memory component page size.
-        </description>
-    </property>
-    <property>
-        <name>messaging.frame.size</name>
-        <value>4096</value>
-        <description>The frame size to be used for NC to NC messaging. (Default = 4kb)
-        </description>
-    </property>
-    <property>
-        <name>messaging.frame.count</name>
-        <value>512</value>
-        <description>Number of reusable frames for NC to NC messaging. (Default = 512)
-        </description>
-    </property>
-</asterixConfiguration>

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-app/src/main/resources/asterix-build-configuration4.xml
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/resources/asterix-build-configuration4.xml b/asterixdb/asterix-app/src/main/resources/asterix-build-configuration4.xml
deleted file mode 100644
index bfa51dd..0000000
--- a/asterixdb/asterix-app/src/main/resources/asterix-build-configuration4.xml
+++ /dev/null
@@ -1,87 +0,0 @@
-<!--
- ! 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.
- !-->
-<asterixConfiguration xmlns="asterixconf">
-    <metadataNode>asterix_nc1</metadataNode>
-    <store>
-        <ncId>asterix_nc1</ncId>
-        <storeDirs>iodevice0,iodevice1</storeDirs>
-    </store>
-    <store>
-        <ncId>asterix_nc2</ncId>
-        <storeDirs>iodevice0,iodevice1</storeDirs>
-    </store>
-    <transactionLogDir>
-        <ncId>asterix_nc1</ncId>
-        <txnLogDirPath>target/txnLogDir/asterix_nc1</txnLogDirPath>
-    </transactionLogDir>
-    <transactionLogDir>
-        <ncId>asterix_nc2</ncId>
-        <txnLogDirPath>target/txnLogDir/asterix_nc2</txnLogDirPath>
-    </transactionLogDir>
-
-    <property>
-        <name>max.wait.active.cluster</name>
-        <value>60</value>
-        <description>Maximum wait (in seconds) for a cluster to be ACTIVE (all
-            nodes are available)
-            before a submitted query/statement can be
-            executed. (Default = 60 seconds)
-        </description>
-    </property>
-
-    <property>
-        <name>compiler.framesize</name>
-        <value>32KB</value>
-    </property>
-    <property>
-        <name>compiler.sortmemory</name>
-        <value>320KB</value>
-    </property>
-    <property>
-        <name>compiler.groupmemory</name>
-        <value>160KB</value>
-    </property>
-    <property>
-        <name>compiler.joinmemory</name>
-        <value>256KB</value>
-    </property>
-    <property>
-        <name>compiler.parallelism</name>
-        <value>-1</value>
-    </property>
-    <property>
-        <name>storage.buffercache.pagesize</name>
-        <value>32KB</value>
-        <description>The page size in bytes for pages in the buffer cache.
-            (Default = "128KB")
-        </description>
-    </property>
-    <property>
-        <name>messaging.frame.size</name>
-        <value>4096</value>
-        <description>The frame size to be used for NC to NC messaging. (Default = 4kb)
-        </description>
-    </property>
-    <property>
-        <name>messaging.frame.count</name>
-        <value>512</value>
-        <description>Number of reusable frames for NC to NC messaging. (Default = 512)
-        </description>
-    </property>
-</asterixConfiguration>

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-app/src/main/resources/cc-rep.conf
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/resources/cc-rep.conf b/asterixdb/asterix-app/src/main/resources/cc-rep.conf
index 885201f..1f4e5a5 100644
--- a/asterixdb/asterix-app/src/main/resources/cc-rep.conf
+++ b/asterixdb/asterix-app/src/main/resources/cc-rep.conf
@@ -18,7 +18,7 @@
 [nc/asterix_nc1]
 txn.log.dir=../asterix-server/target/tmp/asterix_nc1/txnlog
 core.dump.dir=../asterix-server/target/tmp/asterix_nc1/coredump
-iodevices=../asterix-server/target/tmp/asterix_nc1/iodevice1,../asterix-server/target/tmp/asterix_nc1/iodevice2
+iodevices=asterix_nc1/iodevice1,asterix_nc1/iodevice2
 #jvm.args=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5006
 replication.listen.port=2001
 nc.api.port=19004
@@ -27,7 +27,7 @@ nc.api.port=19004
 ncservice.port=9091
 txn.log.dir=../asterix-server/target/tmp/asterix_nc2/txnlog
 core.dump.dir=../asterix-server/target/tmp/asterix_nc2/coredump
-iodevices=../asterix-server/target/tmp/asterix_nc2/iodevice1,../asterix-server/target/tmp/asterix_nc2/iodevice2
+iodevices=asterix_nc2/iodevice1,asterix_nc2/iodevice2
 #jvm.args=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5007
 replication.listen.port=2002
 nc.api.port=19005

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-app/src/main/resources/cc.conf
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/resources/cc.conf b/asterixdb/asterix-app/src/main/resources/cc.conf
index c5a3fdb..914b7b6 100644
--- a/asterixdb/asterix-app/src/main/resources/cc.conf
+++ b/asterixdb/asterix-app/src/main/resources/cc.conf
@@ -18,7 +18,7 @@
 [nc/asterix_nc1]
 txn.log.dir=target/tmp/asterix_nc1/txnlog
 core.dump.dir=target/tmp/asterix_nc1/coredump
-iodevices=target/tmp/asterix_nc1/iodevice1,../asterix-server/target/tmp/asterix_nc1/iodevice2
+iodevices=asterix_nc1/iodevice1,asterix_nc1/iodevice2
 nc.api.port=19004
 #jvm.args=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5006
 
@@ -26,7 +26,7 @@ nc.api.port=19004
 ncservice.port=9091
 txn.log.dir=target/tmp/asterix_nc2/txnlog
 core.dump.dir=target/tmp/asterix_nc2/coredump
-iodevices=target/tmp/asterix_nc2/iodevice1,../asterix-server/target/tmp/asterix_nc2/iodevice2
+iodevices=asterix_nc2/iodevice1,asterix_nc2/iodevice2
 nc.api.port=19005
 #jvm.args=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5007
 

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-app/src/main/resources/cc2.conf
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/resources/cc2.conf b/asterixdb/asterix-app/src/main/resources/cc2.conf
index 941b6c1..6c01386 100644
--- a/asterixdb/asterix-app/src/main/resources/cc2.conf
+++ b/asterixdb/asterix-app/src/main/resources/cc2.conf
@@ -18,7 +18,7 @@
 [nc/asterix_nc1]
 txn.log.dir=target/tmp/asterix_nc1/txnlog
 core.dump.dir=target/tmp/asterix_nc1/coredump
-iodevices=target/tmp/asterix_nc1/iodevice1,../asterix-server/target/tmp/asterix_nc1/iodevice2
+iodevices=asterix_nc1/iodevice1,asterix_nc1/iodevice2
 nc.api.port=19004
 #jvm.args=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5006
 
@@ -26,7 +26,7 @@ nc.api.port=19004
 ncservice.port=9091
 txn.log.dir=target/tmp/asterix_nc2/txnlog
 core.dump.dir=target/tmp/asterix_nc2/coredump
-iodevices=target/tmp/asterix_nc2/iodevice1,../asterix-server/target/tmp/asterix_nc2/iodevice2
+iodevices=asterix_nc2/iodevice1,asterix_nc2/iodevice2
 nc.api.port=19005
 #jvm.args=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5007
 

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-app/src/main/resources/cc3.conf
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/resources/cc3.conf b/asterixdb/asterix-app/src/main/resources/cc3.conf
index 01383ef..933e4af 100644
--- a/asterixdb/asterix-app/src/main/resources/cc3.conf
+++ b/asterixdb/asterix-app/src/main/resources/cc3.conf
@@ -18,7 +18,7 @@
 [nc/asterix_nc1]
 txn.log.dir=target/tmp/asterix_nc1/txnlog
 core.dump.dir=target/tmp/asterix_nc1/coredump
-iodevices=target/tmp/asterix_nc1/iodevice1,../asterix-server/target/tmp/asterix_nc1/iodevice2
+iodevices=asterix_nc1/iodevice1,asterix_nc1/iodevice2
 nc.api.port=19004
 #jvm.args=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5006
 
@@ -26,7 +26,7 @@ nc.api.port=19004
 ncservice.port=9091
 txn.log.dir=target/tmp/asterix_nc2/txnlog
 core.dump.dir=target/tmp/asterix_nc2/coredump
-iodevices=target/tmp/asterix_nc2/iodevice1,../asterix-server/target/tmp/asterix_nc2/iodevice2
+iodevices=asterix_nc2/iodevice1,asterix_nc2/iodevice2
 nc.api.port=19005
 #jvm.args=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5007
 

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-app/src/main/resources/cc4.conf
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/resources/cc4.conf b/asterixdb/asterix-app/src/main/resources/cc4.conf
index bcbf6b1..3b7a993 100644
--- a/asterixdb/asterix-app/src/main/resources/cc4.conf
+++ b/asterixdb/asterix-app/src/main/resources/cc4.conf
@@ -18,7 +18,7 @@
 [nc/asterix_nc1]
 txn.log.dir=target/tmp/asterix_nc1/txnlog
 core.dump.dir=target/tmp/asterix_nc1/coredump
-iodevices=target/tmp/asterix_nc1/iodevice1,../asterix-server/target/tmp/asterix_nc1/iodevice2
+iodevices=asterix_nc1/iodevice1,asterix_nc1/iodevice2
 nc.api.port=19004
 #jvm.args=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5006
 
@@ -26,7 +26,7 @@ nc.api.port=19004
 ncservice.port=9091
 txn.log.dir=target/tmp/asterix_nc2/txnlog
 core.dump.dir=target/tmp/asterix_nc2/coredump
-iodevices=target/tmp/asterix_nc2/iodevice1,../asterix-server/target/tmp/asterix_nc2/iodevice2
+iodevices=asterix_nc2/iodevice1,asterix_nc2/iodevice2
 nc.api.port=19005
 #jvm.args=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5007
 

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-app/src/main/resources/cluster.xml
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/resources/cluster.xml b/asterixdb/asterix-app/src/main/resources/cluster.xml
deleted file mode 100644
index 41be696..0000000
--- a/asterixdb/asterix-app/src/main/resources/cluster.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<!--
- ! 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.
- !-->
-<cluster xmlns="cluster">
-  <instance_name>asterix</instance_name>
-  <store>storage</store>
-  <metadata_node>nc1</metadata_node>
-
-  <high_availability>
-    <enabled>false</enabled>
-    <data_replication>
-      <strategy>metadata_only</strategy>
-      <replication_port>2016</replication_port>
-      <replication_time_out>30</replication_time_out>
-    </data_replication>
-    <fault_tolerance>
-       <strategy>metadata_node</strategy>
-    </fault_tolerance>
-  </high_availability>
-
-  <master_node>
-    <id>master</id>
-    <client_ip>127.0.0.1</client_ip>
-    <cluster_ip>127.0.0.1</cluster_ip>
-    <client_port>1098</client_port>
-    <cluster_port>1099</cluster_port>
-    <http_port>8888</http_port>
-  </master_node>
-  <node>
-    <id>nc1</id>
-    <cluster_ip>127.0.0.1</cluster_ip>
-    <replication_port>2016</replication_port>
-    <nc_api_port>19004</nc_api_port>
-  </node>
-  <node>
-    <id>nc2</id>
-    <cluster_ip>127.0.0.1</cluster_ip>
-    <replication_port>2017</replication_port>
-    <nc_api_port>19005</nc_api_port>
-  </node>
-</cluster>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-app/src/main/resources/log4j2.xml
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/resources/log4j2.xml b/asterixdb/asterix-app/src/main/resources/log4j2.xml
index 24bcf77..1debf82 100644
--- a/asterixdb/asterix-app/src/main/resources/log4j2.xml
+++ b/asterixdb/asterix-app/src/main/resources/log4j2.xml
@@ -26,5 +26,6 @@
     <Root level="WARN">
       <AppenderRef ref="Console"/>
     </Root>
+    <Logger name="org.apache.hyracks.control.nc.service" level="INFO"/>
   </Loggers>
 </Configuration>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-app/src/test/resources/log4j2-test.xml
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/log4j2-test.xml b/asterixdb/asterix-app/src/test/resources/log4j2-test.xml
index 387e900..c6ecd7d 100644
--- a/asterixdb/asterix-app/src/test/resources/log4j2-test.xml
+++ b/asterixdb/asterix-app/src/test/resources/log4j2-test.xml
@@ -32,19 +32,14 @@
     <Root level="WARN">
       <AppenderRef ref="InfoLog"/>
     </Root>
-    <Logger name="org.apache.hyracks" level="INFO" additivity="false">
-      <AppenderRef ref="InfoLog"/>
-    </Logger>
-    <Logger name="org.apache.asterix" level="INFO" additivity="false">
-      <AppenderRef ref="InfoLog"/>
-    </Logger>
-    <Logger name="org.apache.hyracks.test" level="INFO" additivity="false">
+    <Logger name="org.apache.hyracks.control.nc.service" level="INFO"/>
+    <Logger name="org.apache.hyracks" level="INFO"/>
+    <Logger name="org.apache.asterix" level="INFO"/>
+    <Logger name="org.apache.hyracks.test" level="INFO">
       <AppenderRef ref="ConsoleTest"/>
-      <AppenderRef ref="InfoLog"/>
     </Logger>
-    <Logger name="org.apache.asterix.test" level="INFO" additivity="false">
+    <Logger name="org.apache.asterix.test" level="INFO">
       <AppenderRef ref="ConsoleTest"/>
-      <AppenderRef ref="InfoLog"/>
     </Logger>
   </Loggers>
 </Configuration>

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/api/INcApplicationContext.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/api/INcApplicationContext.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/api/INcApplicationContext.java
index fffc170..a02bda5 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/api/INcApplicationContext.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/api/INcApplicationContext.java
@@ -31,6 +31,7 @@ import org.apache.asterix.common.storage.IReplicaManager;
 import org.apache.asterix.common.transactions.ITransactionSubsystem;
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
 import org.apache.hyracks.api.application.INCServiceContext;
+import org.apache.hyracks.api.control.CcId;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
 import org.apache.hyracks.api.io.IIOManager;
 import org.apache.hyracks.storage.am.lsm.common.api.ILSMIOOperationScheduler;
@@ -105,6 +106,13 @@ public interface INcApplicationContext extends IApplicationContext {
     void unexportMetadataNodeStub() throws RemoteException;
 
     /**
+     * Binds the exported metadata node to the CC's distributed state.
+     *
+     * @throws RemoteException
+     */
+    void bindMetadataNodeStub(CcId ccId) throws RemoteException;
+
+    /**
      * @return instance of {@link org.apache.asterix.common.context.IStorageComponentProvider}
      */
     IStorageComponentProvider getStorageComponentProvider();

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/dataflow/ICcApplicationContext.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/dataflow/ICcApplicationContext.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/dataflow/ICcApplicationContext.java
index e02482d..18e3327 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/dataflow/ICcApplicationContext.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/dataflow/ICcApplicationContext.java
@@ -21,6 +21,7 @@ package org.apache.asterix.common.dataflow;
 import org.apache.asterix.common.api.IApplicationContext;
 import org.apache.asterix.common.api.IMetadataLockManager;
 import org.apache.asterix.common.api.INodeJobTracker;
+import org.apache.asterix.common.transactions.ITxnIdFactory;
 import org.apache.asterix.common.cluster.IClusterStateManager;
 import org.apache.asterix.common.cluster.IGlobalRecoveryManager;
 import org.apache.asterix.common.config.ExtensionProperties;
@@ -121,4 +122,9 @@ public interface ICcApplicationContext extends IApplicationContext {
      * @return the node job tracker
      */
     INodeJobTracker getNodeJobTracker();
+
+    /**
+     * @return the transaction id factory
+     */
+    ITxnIdFactory getTxnIdFactory();
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/transactions/ILongBlockFactory.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/transactions/ILongBlockFactory.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/transactions/ILongBlockFactory.java
new file mode 100644
index 0000000..b5ee0a8
--- /dev/null
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/transactions/ILongBlockFactory.java
@@ -0,0 +1,40 @@
+/*
+ * 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.asterix.common.transactions;
+
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+
+public interface ILongBlockFactory {
+    /**
+     * Ensures future blocks are allocated larger than the supplied value
+     *
+     * @param value
+     *            the value to ensure future blocks are larger than
+     */
+    void ensureMinimum(long value) throws AlgebricksException;
+
+    /**
+     * Allocates a block of longs of specified block size
+     *
+     * @param blockSize
+     *            The size of the block of longs to reserve
+     * @return the start of the reserved block
+     */
+    long getBlock(int blockSize) throws AlgebricksException;
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/transactions/ITxnIdBlockProvider.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/transactions/ITxnIdBlockProvider.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/transactions/ITxnIdBlockProvider.java
new file mode 100644
index 0000000..94ca848
--- /dev/null
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/transactions/ITxnIdBlockProvider.java
@@ -0,0 +1,47 @@
+/*
+ * 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.asterix.common.transactions;
+
+import java.io.Serializable;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+public interface ITxnIdBlockProvider extends Remote, Serializable {
+
+    /**
+     * Ensures that future transaction blocks will be of a value larger than the supplied value
+     *
+     * @param maxId
+     *            The txn id to ensure future txn ids are larger than
+     * @throws RemoteException
+     */
+    void ensureMinimumTxnId(long maxId) throws RemoteException;
+
+    /**
+     * Allocates a block of transaction ids of specified block size
+     *
+     * @param blockSize
+     *            The size of the transaction id block to reserve
+     * @return the start of the reserved block
+     * @throws RemoteException
+     */
+    long reserveTxnIdBlock(int blockSize) throws RemoteException;
+
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/transactions/ITxnIdFactory.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/transactions/ITxnIdFactory.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/transactions/ITxnIdFactory.java
new file mode 100644
index 0000000..3c60432
--- /dev/null
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/transactions/ITxnIdFactory.java
@@ -0,0 +1,38 @@
+/*
+ * 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.asterix.common.transactions;
+
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+
+public interface ITxnIdFactory {
+    /**
+     * Creates a new unique transaction id.  The implementation must ensure this id is unique within the cluster
+     *
+     * @return the new transaction id
+     */
+    TxnId create() throws AlgebricksException;
+
+    /**
+     * Ensure that future transaction ids are larger than the supplied id
+     *
+     * @param id
+     *            the value to ensure future created transaction ids are larger than
+     */
+    void ensureMinimumId(long id) throws AlgebricksException;
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/BulkTxnIdFactory.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/BulkTxnIdFactory.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/BulkTxnIdFactory.java
new file mode 100644
index 0000000..8ac6b63
--- /dev/null
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/BulkTxnIdFactory.java
@@ -0,0 +1,47 @@
+/*
+ * 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.asterix.metadata;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.asterix.common.transactions.ITxnIdFactory;
+import org.apache.asterix.common.transactions.TxnId;
+
+class BulkTxnIdFactory implements ITxnIdFactory {
+
+    private final AtomicLong maxId = new AtomicLong();
+
+    @Override
+    public TxnId create() {
+        return new TxnId(maxId.incrementAndGet());
+    }
+
+    public long reserveIdBlock(int blockSize) {
+        if (blockSize < 1) {
+            throw new IllegalArgumentException("block size cannot be smaller than 1, but was " + blockSize);
+        }
+        return maxId.getAndAdd(blockSize) + 1;
+    }
+
+    @Override
+    public void ensureMinimumId(long id) {
+        this.maxId.getAndUpdate(next -> Math.max(next, id));
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataManager.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataManager.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataManager.java
index 8578d6b..b4b304e 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataManager.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataManager.java
@@ -21,17 +21,21 @@ package org.apache.asterix.metadata;
 
 import java.rmi.RemoteException;
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import org.apache.asterix.common.config.MetadataProperties;
+import org.apache.asterix.common.dataflow.ICcApplicationContext;
 import org.apache.asterix.common.exceptions.ACIDException;
 import org.apache.asterix.common.exceptions.ErrorCode;
 import org.apache.asterix.common.exceptions.MetadataException;
 import org.apache.asterix.common.exceptions.RuntimeDataException;
 import org.apache.asterix.common.functions.FunctionSignature;
+import org.apache.asterix.common.transactions.ILongBlockFactory;
 import org.apache.asterix.common.transactions.TxnId;
 import org.apache.asterix.external.indexing.ExternalFile;
 import org.apache.asterix.metadata.api.IAsterixStateProxy;
@@ -53,7 +57,6 @@ import org.apache.asterix.metadata.entities.Library;
 import org.apache.asterix.metadata.entities.Node;
 import org.apache.asterix.metadata.entities.NodeGroup;
 import org.apache.asterix.om.types.ARecordType;
-import org.apache.asterix.transaction.management.service.transaction.TxnIdFactory;
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
 
@@ -89,9 +92,9 @@ import org.apache.hyracks.api.exceptions.HyracksDataException;
  * cluster, i.e., metadata transaction ids shall never "accidentally" overlap
  * with transaction ids of regular jobs or other metadata transactions.
  */
-public class MetadataManager implements IMetadataManager {
+public abstract class MetadataManager implements IMetadataManager, ILongBlockFactory {
     private final MetadataCache cache = new MetadataCache();
-    protected final IAsterixStateProxy proxy;
+    protected final Collection<IAsterixStateProxy> proxies;
     protected IMetadataNode metadataNode;
     private final ReadWriteLock metadataLatch;
     protected boolean rebindMetadataNode = false;
@@ -100,19 +103,19 @@ public class MetadataManager implements IMetadataManager {
     // update field name accordingly
     public static IMetadataManager INSTANCE;
 
-    private MetadataManager(IAsterixStateProxy proxy, IMetadataNode metadataNode) {
-        this(proxy);
+    private MetadataManager(Collection<IAsterixStateProxy> proxies, MetadataNode metadataNode) {
+        this(proxies);
         if (metadataNode == null) {
             throw new IllegalArgumentException("Null metadataNode given to MetadataManager");
         }
         this.metadataNode = metadataNode;
     }
 
-    private MetadataManager(IAsterixStateProxy proxy) {
-        if (proxy == null) {
-            throw new IllegalArgumentException("Null proxy given to MetadataManager");
+    private MetadataManager(Collection<IAsterixStateProxy> proxies) {
+        if (proxies == null || proxies.isEmpty()) {
+            throw new IllegalArgumentException("Null / empty list of proxies given to MetadataManager");
         }
-        this.proxy = proxy;
+        this.proxies = proxies;
         this.metadataLatch = new ReentrantReadWriteLock(true);
     }
 
@@ -122,11 +125,7 @@ public class MetadataManager implements IMetadataManager {
     }
 
     @Override
-    public MetadataTransactionContext beginTransaction() throws RemoteException, ACIDException {
-        TxnId txnId = TxnIdFactory.create();
-        metadataNode.beginTransaction(txnId);
-        return new MetadataTransactionContext(txnId);
-    }
+    public abstract MetadataTransactionContext beginTransaction() throws RemoteException, ACIDException;
 
     @Override
     public void commitTransaction(MetadataTransactionContext ctx) throws RemoteException, ACIDException {
@@ -998,20 +997,64 @@ public class MetadataManager implements IMetadataManager {
         rebindMetadataNode = true;
     }
 
-    public static void initialize(IAsterixStateProxy proxy, MetadataProperties metadataProperties) {
-        INSTANCE = new CCMetadataManagerImpl(proxy, metadataProperties);
+    @Override
+    public void ensureMinimum(long value) throws AlgebricksException {
+        try {
+            metadataNode.ensureMinimumTxnId(value);
+        } catch (RemoteException e) {
+            throw new MetadataException(ErrorCode.REMOTE_EXCEPTION_WHEN_CALLING_METADATA_NODE, e);
+        }
+    }
+
+    @Override
+    public long getBlock(int blockSize) throws AlgebricksException {
+        try {
+            return metadataNode.reserveTxnIdBlock(blockSize);
+        } catch (RemoteException e) {
+            throw new MetadataException(ErrorCode.REMOTE_EXCEPTION_WHEN_CALLING_METADATA_NODE, e);
+        }
     }
 
-    public static void initialize(IAsterixStateProxy proxy, MetadataNode metadataNode) {
-        INSTANCE = new MetadataManager(proxy, metadataNode);
+    public static ILongBlockFactory getTxnIdBlockFactory() {
+        try {
+            INSTANCE.init();
+        } catch (HyracksDataException e) {
+            throw new IllegalStateException(e);
+        }
+        return (ILongBlockFactory) INSTANCE;
+
+    }
+
+    public static void initialize(IAsterixStateProxy proxy, MetadataProperties metadataProperties,
+            ICcApplicationContext appCtx) {
+        INSTANCE = new CCMetadataManagerImpl(proxy, metadataProperties, appCtx);
+    }
+
+    public static void initialize(Collection<IAsterixStateProxy> proxies, MetadataNode metadataNode) {
+        INSTANCE = new NCMetadataManagerImpl(proxies, metadataNode);
     }
 
     private static class CCMetadataManagerImpl extends MetadataManager {
         private final MetadataProperties metadataProperties;
+        private final ICcApplicationContext appCtx;
 
-        public CCMetadataManagerImpl(IAsterixStateProxy proxy, MetadataProperties metadataProperties) {
-            super(proxy);
+        CCMetadataManagerImpl(IAsterixStateProxy proxy, MetadataProperties metadataProperties,
+                ICcApplicationContext appCtx) {
+            super(Collections.singleton(proxy));
             this.metadataProperties = metadataProperties;
+            this.appCtx = appCtx;
+        }
+
+        @Override
+        public MetadataTransactionContext beginTransaction() throws RemoteException {
+            TxnId txnId;
+            try {
+                txnId = appCtx.getTxnIdFactory().create();
+            } catch (AlgebricksException e) {
+                throw new ACIDException(e);
+            }
+            metadataNode.beginTransaction(txnId);
+            return new MetadataTransactionContext(txnId);
         }
 
         @Override
@@ -1020,8 +1063,8 @@ public class MetadataManager implements IMetadataManager {
                 return;
             }
             try {
-                metadataNode =
-                        proxy.waitForMetadataNode(metadataProperties.getRegistrationTimeoutSecs(), TimeUnit.SECONDS);
+                metadataNode = proxies.iterator().next()
+                        .waitForMetadataNode(metadataProperties.getRegistrationTimeoutSecs(), TimeUnit.SECONDS);
                 if (metadataNode != null) {
                     rebindMetadataNode = false;
                 } else {
@@ -1038,4 +1081,17 @@ public class MetadataManager implements IMetadataManager {
             super.init();
         }
     }
+
+    private static class NCMetadataManagerImpl extends MetadataManager {
+        NCMetadataManagerImpl(Collection<IAsterixStateProxy> proxies, MetadataNode metadataNode) {
+            super(proxies, metadataNode);
+        }
+
+        @Override
+        public MetadataTransactionContext beginTransaction() throws RemoteException {
+            TxnId txnId = new TxnId(metadataNode.reserveTxnIdBlock(1));
+            metadataNode.beginTransaction(txnId);
+            return new MetadataTransactionContext(txnId);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataNode.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataNode.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataNode.java
index e8f2595..72d5cf5 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataNode.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataNode.java
@@ -132,6 +132,7 @@ public class MetadataNode implements IMetadataNode {
     private IDatasetLifecycleManager datasetLifecycleManager;
     private ITransactionSubsystem transactionSubsystem;
     private int metadataStoragePartition;
+    private transient BulkTxnIdFactory txnIdFactory;
     // core only
     private transient MetadataTupleTranslatorProvider tupleTranslatorProvider;
     // extension only
@@ -157,6 +158,17 @@ public class MetadataNode implements IMetadataNode {
                 }
             }
         }
+        this.txnIdFactory = new BulkTxnIdFactory();
+    }
+
+    @Override
+    public void ensureMinimumTxnId(long maxId) throws ACIDException, RemoteException {
+        txnIdFactory.ensureMinimumId(maxId);
+    }
+
+    @Override
+    public long reserveTxnIdBlock(int blockSize) throws ACIDException, RemoteException {
+        return txnIdFactory.reserveIdBlock(blockSize);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/api/IMetadataNode.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/api/IMetadataNode.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/api/IMetadataNode.java
index cdb27d7..c3f9d7f 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/api/IMetadataNode.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/api/IMetadataNode.java
@@ -26,6 +26,7 @@ import java.util.List;
 
 import org.apache.asterix.common.exceptions.ACIDException;
 import org.apache.asterix.common.functions.FunctionSignature;
+import org.apache.asterix.common.transactions.ITxnIdBlockProvider;
 import org.apache.asterix.common.transactions.TxnId;
 import org.apache.asterix.external.indexing.ExternalFile;
 import org.apache.asterix.metadata.entities.CompactionPolicy;
@@ -51,7 +52,28 @@ import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
  * lock/access metadata shall always go through the MetadataManager, and should
  * never call methods on the MetadataNode directly for any reason.
  */
-public interface IMetadataNode extends Remote, Serializable {
+public interface IMetadataNode extends Remote, Serializable, ITxnIdBlockProvider {
+
+    /**
+     * Allocates a block of transaction ids of specified block size
+     *
+     * @param maxId
+     *            The txn id to ensure future txn ids are larger than
+     * @throws ACIDException
+     * @throws RemoteException
+     */
+    void ensureMinimumTxnId(long maxId) throws ACIDException, RemoteException;
+
+    /**
+     * Allocates a block of transaction ids of specified block size
+     *
+     * @param blockSize
+     *            The size of the transaction id block to reserve
+     * @return the start of the reserved block
+     * @throws ACIDException
+     * @throws RemoteException
+     */
+    long reserveTxnIdBlock(int blockSize) throws ACIDException, RemoteException;
 
     /**
      * Begins a local transaction against the metadata.

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/bootstrap/AsterixStateProxy.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/bootstrap/AsterixStateProxy.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/bootstrap/AsterixStateProxy.java
index 8ab9f82..5357fc8 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/bootstrap/AsterixStateProxy.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/bootstrap/AsterixStateProxy.java
@@ -58,6 +58,7 @@ public class AsterixStateProxy implements IAsterixStateProxy {
     @Override
     public IMetadataNode waitForMetadataNode(long waitFor, TimeUnit timeUnit) throws InterruptedException {
         synchronized (this) {
+            //TODO(mblow): replace with nanoTime() to avoid being affected by system clock adjustments...
             long timeToWait = TimeUnit.MILLISECONDS.convert(waitFor, timeUnit);
             while (metadataNode == null && timeToWait > 0) {
                 long startTime = System.currentTimeMillis();

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d753479f/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/MetadataProvider.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/MetadataProvider.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/MetadataProvider.java
index f740d09..7a24400 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/MetadataProvider.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/MetadataProvider.java
@@ -26,6 +26,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.asterix.common.transactions.ITxnIdFactory;
 import org.apache.asterix.common.cluster.IClusterStateManager;
 import org.apache.asterix.common.config.DatasetConfig.DatasetType;
 import org.apache.asterix.common.config.DatasetConfig.ExternalFilePendingOp;
@@ -1539,4 +1540,8 @@ public class MetadataProvider implements IMetadataProvider<DataSourceId, String>
     public ICcApplicationContext getApplicationContext() {
         return appCtx;
     }
+
+    public ITxnIdFactory getTxnIdFactory() {
+        return appCtx.getTxnIdFactory();
+    }
 }