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 2017/10/24 22:03:47 UTC

asterixdb git commit: [ASTERIXDB-1076][HYR] Prevent node death false positives

Repository: asterixdb
Updated Branches:
  refs/heads/master 91b774364 -> 8734988fa


[ASTERIXDB-1076][HYR] Prevent node death false positives

- Measure actual time since last heartbeat touched, not based on number
  of dead cycle detections since last heartbeat received
- Update heartbeat touch on job result received, in addition to when
  heartbeat data is received
- Minor refactoring in NC/CC config

Change-Id: Idb1abcc2b783b192b88ed988d398fcfe763531e9
Reviewed-on: https://asterix-gerrit.ics.uci.edu/2097
Sonar-Qube: Jenkins <je...@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <je...@fulliautomatix.ics.uci.edu>
Contrib: Jenkins <je...@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <je...@fulliautomatix.ics.uci.edu>
Reviewed-by: Ian Maxon <im...@apache.org>


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

Branch: refs/heads/master
Commit: 8734988fae1d32dce74ec9fff5cee0dd5c2e5d15
Parents: 91b7743
Author: Michael Blow <mi...@couchbase.com>
Authored: Tue Oct 24 15:54:28 2017 -0400
Committer: Murtadha Hubail <mh...@apache.org>
Committed: Tue Oct 24 15:00:16 2017 -0700

----------------------------------------------------------------------
 .../api/common/AsterixHyracksIntegrationUtil.java  |  2 +-
 .../apache/hyracks/client/stats/HyracksUtils.java  |  2 +-
 .../control/cc/ClusterControllerService.java       |  2 +-
 .../hyracks/control/cc/NodeControllerState.java    | 17 +++++++++++++----
 .../hyracks/control/cc/cluster/NodeManager.java    |  5 ++++-
 .../control/cc/work/AbstractTaskLifecycleWork.java |  5 +++++
 .../hyracks/control/cc/work/RegisterNodeWork.java  |  2 +-
 .../control/common/controllers/CCConfig.java       | 15 ++++-----------
 .../common/controllers/ControllerConfig.java       |  4 ++++
 .../control/common/controllers/NCConfig.java       |  7 +------
 .../control/common/controllers/NodeParameters.java |  6 +++---
 .../hyracks/control/nc/NodeControllerService.java  | 13 +++++++++----
 12 files changed, 47 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/asterixdb/blob/8734988f/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/AsterixHyracksIntegrationUtil.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/AsterixHyracksIntegrationUtil.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/AsterixHyracksIntegrationUtil.java
index f5e94b1..ecf25eb 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/AsterixHyracksIntegrationUtil.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/AsterixHyracksIntegrationUtil.java
@@ -166,7 +166,7 @@ public class AsterixHyracksIntegrationUtil {
         ncConfig.getConfigManager().processConfig();
 
         // get initial partitions from config
-        String[] nodeStores = ncConfig.getAppConfig().getStringArray(NCConfig.Option.IODEVICES);
+        String[] nodeStores = ncConfig.getNodeScopedAppConfig().getStringArray(NCConfig.Option.IODEVICES);
         if (nodeStores == null) {
             throw new IllegalStateException("Couldn't find stores for NC: " + ncConfig.getNodeId());
         }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/8734988f/hyracks-fullstack/hyracks/hyracks-client/src/test/java/org/apache/hyracks/client/stats/HyracksUtils.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-client/src/test/java/org/apache/hyracks/client/stats/HyracksUtils.java b/hyracks-fullstack/hyracks/hyracks-client/src/test/java/org/apache/hyracks/client/stats/HyracksUtils.java
index 54ae838..3eff037 100644
--- a/hyracks-fullstack/hyracks/hyracks-client/src/test/java/org/apache/hyracks/client/stats/HyracksUtils.java
+++ b/hyracks-fullstack/hyracks/hyracks-client/src/test/java/org/apache/hyracks/client/stats/HyracksUtils.java
@@ -56,7 +56,7 @@ public class HyracksUtils {
         ccConfig.setClientListenPort(TEST_HYRACKS_CC_CLIENT_PORT);
         ccConfig.setJobHistorySize(0);
         ccConfig.setProfileDumpPeriod(-1);
-        ccConfig.setHeartbeatPeriod(50);
+        ccConfig.setHeartbeatPeriodMillis(50);
 
         // cluster controller
         cc = new ClusterControllerService(ccConfig);

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/8734988f/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/ClusterControllerService.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/ClusterControllerService.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/ClusterControllerService.java
index dfc79ed..a3fbb70 100644
--- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/ClusterControllerService.java
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/ClusterControllerService.java
@@ -207,7 +207,7 @@ public class ClusterControllerService implements IControllerService {
         webServer.start();
         info = new ClusterControllerInfo(ccConfig.getClientListenAddress(), ccConfig.getClientListenPort(),
                 webServer.getListeningPort());
-        timer.schedule(sweeper, 0, ccConfig.getHeartbeatPeriod());
+        timer.schedule(sweeper, 0, ccConfig.getHeartbeatPeriodMillis());
         jobLog.open();
         startApplication();
 

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/8734988f/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/NodeControllerState.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/NodeControllerState.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/NodeControllerState.java
index 7be6524..fe4ce89 100644
--- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/NodeControllerState.java
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/NodeControllerState.java
@@ -141,7 +141,7 @@ public class NodeControllerState {
 
     private int rrdPtr;
 
-    private int lastHeartbeatDuration;
+    private long lastHeartbeatNanoTime;
 
     private NodeCapacity capacity;
 
@@ -207,10 +207,11 @@ public class NodeControllerState {
 
         rrdPtr = 0;
         capacity = reg.getCapacity();
+        touchHeartbeat();
     }
 
     public synchronized void notifyHeartbeat(HeartbeatData hbData) {
-        lastHeartbeatDuration = 0;
+        touchHeartbeat();
         hbTime[rrdPtr] = System.currentTimeMillis();
         if (hbData != null) {
             heapInitSize[rrdPtr] = hbData.heapInitSize;
@@ -247,8 +248,16 @@ public class NodeControllerState {
         }
     }
 
-    public int incrementLastHeartbeatDuration() {
-        return lastHeartbeatDuration++;
+    public void touchHeartbeat() {
+        lastHeartbeatNanoTime = System.nanoTime();
+    }
+
+    public long nanosSinceLastHeartbeat() {
+        return System.nanoTime() - lastHeartbeatNanoTime;
+    }
+
+    public long getLastHeartbeatNanoTime() {
+        return lastHeartbeatNanoTime;
     }
 
     public NodeControllerRemoteProxy getNodeController() {

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/8734988f/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/cluster/NodeManager.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/cluster/NodeManager.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/cluster/NodeManager.java
index 2d43d42..a380967 100644
--- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/cluster/NodeManager.java
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/cluster/NodeManager.java
@@ -29,6 +29,7 @@ import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.TimeUnit;
 import java.util.logging.Logger;
 
 import org.apache.commons.lang3.tuple.Pair;
@@ -147,11 +148,13 @@ public class NodeManager implements INodeManager {
         Set<String> deadNodes = new HashSet<>();
         Set<JobId> affectedJobIds = new HashSet<>();
         Iterator<Map.Entry<String, NodeControllerState>> nodeIterator = nodeRegistry.entrySet().iterator();
+        long deadNodeNanosThreshold = TimeUnit.MILLISECONDS
+                .toNanos(ccConfig.getHeartbeatMaxMisses() * ccConfig.getHeartbeatPeriodMillis());
         while (nodeIterator.hasNext()) {
             Map.Entry<String, NodeControllerState> entry = nodeIterator.next();
             String nodeId = entry.getKey();
             NodeControllerState state = entry.getValue();
-            if (state.incrementLastHeartbeatDuration() >= ccConfig.getHeartbeatMaxMisses()) {
+            if (state.nanosSinceLastHeartbeat() >= deadNodeNanosThreshold) {
                 deadNodes.add(nodeId);
                 affectedJobIds.addAll(state.getActiveJobIds());
                 // Removes the node from node map.

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/8734988f/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/work/AbstractTaskLifecycleWork.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/work/AbstractTaskLifecycleWork.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/work/AbstractTaskLifecycleWork.java
index 3babf00..446bfd1 100644
--- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/work/AbstractTaskLifecycleWork.java
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/work/AbstractTaskLifecycleWork.java
@@ -27,6 +27,7 @@ import org.apache.hyracks.api.dataflow.TaskId;
 import org.apache.hyracks.api.job.ActivityCluster;
 import org.apache.hyracks.api.job.JobId;
 import org.apache.hyracks.control.cc.ClusterControllerService;
+import org.apache.hyracks.control.cc.NodeControllerState;
 import org.apache.hyracks.control.cc.job.ActivityPlan;
 import org.apache.hyracks.control.cc.job.IJobManager;
 import org.apache.hyracks.control.cc.job.JobRun;
@@ -75,6 +76,10 @@ public abstract class AbstractTaskLifecycleWork extends AbstractHeartbeatWork {
                 }
             }
         }
+        final NodeControllerState ncState = ccs.getNodeManager().getNodeControllerState(nodeId);
+        if (ncState != null) {
+            ncState.touchHeartbeat();
+        }
     }
 
     protected abstract void performEvent(TaskAttempt ta);

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/8734988f/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/work/RegisterNodeWork.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/work/RegisterNodeWork.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/work/RegisterNodeWork.java
index 5866ba5..d1d2208 100644
--- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/work/RegisterNodeWork.java
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/work/RegisterNodeWork.java
@@ -67,7 +67,7 @@ public class RegisterNodeWork extends SynchronizableWork {
             NodeParameters params = new NodeParameters();
             params.setClusterControllerInfo(ccs.getClusterControllerInfo());
             params.setDistributedState(ccs.getContext().getDistributedState());
-            params.setHeartbeatPeriod(ccs.getCCConfig().getHeartbeatPeriod());
+            params.setHeartbeatPeriod(ccs.getCCConfig().getHeartbeatPeriodMillis());
             params.setProfileDumpPeriod(ccs.getCCConfig().getProfileDumpPeriod());
             result = new CCNCFunctions.NodeRegistrationResult(params, null);
             ccs.getJobIdFactory().ensureMinimumId(reg.getMaxJobId() + 1);

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/8734988f/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/controllers/CCConfig.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/controllers/CCConfig.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/controllers/CCConfig.java
index cbc6146..c04d5b4 100644
--- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/controllers/CCConfig.java
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/controllers/CCConfig.java
@@ -51,7 +51,7 @@ public class CCConfig extends ControllerConfig {
         CLIENT_LISTEN_PORT(INTEGER, 1098),
         CONSOLE_LISTEN_ADDRESS(STRING, ADDRESS),
         CONSOLE_LISTEN_PORT(INTEGER, 16001),
-        HEARTBEAT_PERIOD(INTEGER, 10000), // TODO (mblow): add time unit
+        HEARTBEAT_PERIOD(LONG, 10000L), // TODO (mblow): add time unit
         HEARTBEAT_MAX_MISSES(INTEGER, 5),
         PROFILE_DUMP_PERIOD(INTEGER, 0),
         JOB_HISTORY_SIZE(INTEGER, 10),
@@ -176,8 +176,6 @@ public class CCConfig extends ControllerConfig {
         }
     }
 
-    private final ConfigManager configManager;
-
     private List<String> appArgs = new ArrayList<>();
 
     public CCConfig() {
@@ -186,7 +184,6 @@ public class CCConfig extends ControllerConfig {
 
     public CCConfig(ConfigManager configManager) {
         super(configManager);
-        this.configManager = configManager;
         configManager.register(Option.class);
         configManager.registerArgsListener(appArgs::addAll);
     }
@@ -207,10 +204,6 @@ public class CCConfig extends ControllerConfig {
         return configManager.toIni(false);
     }
 
-    public ConfigManager getConfigManager() {
-        return configManager;
-    }
-
     // QQQ Note that clusterListenAddress is *not directly used* yet. Both
     // the cluster listener and the web server listen on "all interfaces".
     // This IP address is only used to instruct the NC on which IP to call in.
@@ -270,11 +263,11 @@ public class CCConfig extends ControllerConfig {
         configManager.set(Option.CONSOLE_LISTEN_PORT, consoleListenPort);
     }
 
-    public int getHeartbeatPeriod() {
-        return getAppConfig().getInt(Option.HEARTBEAT_PERIOD);
+    public long getHeartbeatPeriodMillis() {
+        return getAppConfig().getLong(Option.HEARTBEAT_PERIOD);
     }
 
-    public void setHeartbeatPeriod(int heartbeatPeriod) {
+    public void setHeartbeatPeriodMillis(long heartbeatPeriod) {
         configManager.set(Option.HEARTBEAT_PERIOD, heartbeatPeriod);
     }
 

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/8734988f/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/controllers/ControllerConfig.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/controllers/ControllerConfig.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/controllers/ControllerConfig.java
index 1745e2a..19c89e0 100644
--- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/controllers/ControllerConfig.java
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/controllers/ControllerConfig.java
@@ -86,6 +86,10 @@ public class ControllerConfig implements Serializable {
         return configManager.getAppConfig();
     }
 
+    public ConfigManager getConfigManager() {
+        return configManager;
+    }
+
     public String getConfigFile() {
         return getAppConfig().getString(ControllerConfig.Option.CONFIG_FILE);
     }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/8734988f/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/controllers/NCConfig.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/controllers/NCConfig.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/controllers/NCConfig.java
index bd5895e..e8c96d4 100644
--- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/controllers/NCConfig.java
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/controllers/NCConfig.java
@@ -247,12 +247,7 @@ public class NCConfig extends ControllerConfig {
         return appArgs.toArray(new String[appArgs.size()]);
     }
 
-    public ConfigManager getConfigManager() {
-        return configManager;
-    }
-
-    @Override
-    public IApplicationConfig getAppConfig() {
+    public IApplicationConfig getNodeScopedAppConfig() {
         return appConfig;
     }
 

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/8734988f/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/controllers/NodeParameters.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/controllers/NodeParameters.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/controllers/NodeParameters.java
index 2264a3f..bf233a8 100644
--- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/controllers/NodeParameters.java
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/controllers/NodeParameters.java
@@ -29,7 +29,7 @@ public class NodeParameters implements Serializable {
 
     private Serializable distributedState;
 
-    private int heartbeatPeriod;
+    private long heartbeatPeriod;
 
     private int profileDumpPeriod;
 
@@ -49,11 +49,11 @@ public class NodeParameters implements Serializable {
         this.distributedState = distributedState;
     }
 
-    public int getHeartbeatPeriod() {
+    public long getHeartbeatPeriod() {
         return heartbeatPeriod;
     }
 
-    public void setHeartbeatPeriod(int heartbeatPeriod) {
+    public void setHeartbeatPeriod(long heartbeatPeriod) {
         this.heartbeatPeriod = heartbeatPeriod;
     }
 

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/8734988f/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/NodeControllerService.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/NodeControllerService.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/NodeControllerService.java
index 4a2c2e9..75d76c0 100644
--- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/NodeControllerService.java
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/NodeControllerService.java
@@ -366,7 +366,8 @@ public class NodeControllerService implements IControllerService {
     }
 
     private void startApplication() throws Exception {
-        serviceCtx = new NCServiceContext(this, serverCtx, ioManager, id, memoryManager, lccm, ncConfig.getAppConfig());
+        serviceCtx = new NCServiceContext(this, serverCtx, ioManager, id, memoryManager, lccm,
+                ncConfig.getNodeScopedAppConfig());
         application.init(serviceCtx);
         executor = Executors.newCachedThreadPool(serviceCtx.getThreadFactory());
         application.start(ncConfig.getAppArgsArray());
@@ -486,7 +487,7 @@ public class NodeControllerService implements IControllerService {
 
         private final HeartbeatData hbData;
 
-        HeartbeatTask(IClusterController cc, int heartbeatPeriod) {
+        HeartbeatTask(IClusterController cc, long heartbeatPeriod) {
             this.cc = cc;
             this.heartbeatPeriodNanos = TimeUnit.MILLISECONDS.toNanos(heartbeatPeriod);
             hbData = new HeartbeatData();
@@ -559,7 +560,7 @@ public class NodeControllerService implements IControllerService {
 
             hbData.diskReads = ioCounter.getReads();
             hbData.diskWrites = ioCounter.getWrites();
-            hbData.numCores = Runtime.getRuntime().availableProcessors() - 1; // Reserves one core for heartbeats.
+            hbData.numCores = Runtime.getRuntime().availableProcessors();
 
             try {
                 cc.nodeHeartbeat(id, hbData);
@@ -568,7 +569,11 @@ public class NodeControllerService implements IControllerService {
             } catch (InterruptedException e) {
                 throw e;
             } catch (Exception e) {
-                LOGGER.log(Level.SEVERE, "Exception sending heartbeat; will retry after 1s", e);
+                if (LOGGER.isLoggable(Level.FINE)) {
+                    LOGGER.log(Level.FINE, "Exception sending heartbeat; will retry after 1s", e);
+                } else {
+                    LOGGER.log(Level.SEVERE, "Exception sending heartbeat; will retry after 1s: " + e.toString());
+                }
                 return false;
             }
         }