diff --git a/src/java/voldemort/VoldemortAdminTool.java b/src/java/voldemort/VoldemortAdminTool.java index a267858d60..00b9a8cb20 100644 --- a/src/java/voldemort/VoldemortAdminTool.java +++ b/src/java/voldemort/VoldemortAdminTool.java @@ -583,6 +583,10 @@ private static void synchronizeMetadataVersion(AdminClient adminClient, int base Properties props = new Properties(); try { props.load(new ByteArrayInputStream(valueObject.getBytes())); + if(props.size() == 0) { + System.err.println("The specified node does not have any versions metadata ! Exiting ..."); + System.exit(-1); + } adminClient.setMetadataversion(props); System.out.println("Metadata versions synchronized successfully."); } catch(IOException e) { diff --git a/src/java/voldemort/client/AbstractStoreClientFactory.java b/src/java/voldemort/client/AbstractStoreClientFactory.java index 2ca94503a0..0b21d7e4e4 100644 --- a/src/java/voldemort/client/AbstractStoreClientFactory.java +++ b/src/java/voldemort/client/AbstractStoreClientFactory.java @@ -193,10 +193,10 @@ public Store getRawStore(String storeName, String clusterXmlString, FailureDetector fd) { - if(logger.isDebugEnabled()) { - logger.debug("Client zone-id [" + clientZoneId - + "] Attempting to obtain metadata for store [" + storeName + "] "); + logger.info("Client zone-id [" + clientZoneId + + "] Attempting to obtain metadata for store [" + storeName + "] "); + if(logger.isDebugEnabled()) { for(URI uri: bootstrapUrls) { logger.debug("Client Bootstrap url [" + uri + "]"); } diff --git a/src/java/voldemort/client/ClientConfig.java b/src/java/voldemort/client/ClientConfig.java index 0091110301..59081b113d 100644 --- a/src/java/voldemort/client/ClientConfig.java +++ b/src/java/voldemort/client/ClientConfig.java @@ -89,6 +89,14 @@ public class ClientConfig { private volatile int clientRegistryRefreshInterval = 3600 * 12; private volatile int asyncJobThreadPoolSize = 2; + /* SystemStore client config */ + private volatile int sysMaxConnectionsPerNode = 2; + private volatile int sysRoutingTimeout = 5000; + private volatile int sysSocketTimeout = 5000; + private volatile int sysConnectionTimeout = 1500; + private volatile boolean sysEnableJmx = false; + private volatile boolean sysEnablePipelineRoutedStore = true; + public ClientConfig() {} /* Propery names for propery-based configuration */ @@ -130,9 +138,15 @@ public ClientConfig() {} public static final String MAX_BOOTSTRAP_RETRIES = "max_bootstrap_retries"; public static final String CLIENT_CONTEXT_NAME = "voldemort_client_context"; public static final String ASYNC_CHECK_METADATA_INTERVAL = "check_metadata_interval"; - private static final String USE_DEFAULT_CLIENT = "use_default_client"; + public static final String USE_DEFAULT_CLIENT = "use_default_client"; public static final String CLIENT_REGISTRY_REFRESH_INTERVAL = "client_registry_refresh_interval"; public static final String ASYNC_JOB_THREAD_POOL_SIZE = "async_job_thread_pool_size"; + public static final String SYS_MAX_CONNECTIONS_PER_NODE = "sys_max_connections_per_node"; + public static final String SYS_ROUTING_TIMEOUT_MS = "sys_routing_timeout_ms"; + public static final String SYS_CONNECTION_TIMEOUT_MS = "sys_connection_timeout_ms"; + public static final String SYS_SOCKET_TIMEOUT_MS = "sys_socket_timeout_ms"; + public static final String SYS_ENABLE_JMX = "sys_enable_jmx"; + public static final String SYS_ENABLE_PIPELINE_ROUTED_STORE = "sys_enable_pipeline_routed_store"; /** * Instantiate the client config using a properties file @@ -310,6 +324,94 @@ private void setProperties(Properties properties) { if(props.containsKey(ASYNC_JOB_THREAD_POOL_SIZE)) { this.setAsyncJobThreadPoolSize(props.getInt(ASYNC_JOB_THREAD_POOL_SIZE)); } + + /* Check for system store paramaters if any */ + if(props.containsKey(SYS_MAX_CONNECTIONS_PER_NODE)) { + this.setSysMaxConnectionsPerNode(props.getInt(SYS_MAX_CONNECTIONS_PER_NODE)); + } + + if(props.containsKey(SYS_ROUTING_TIMEOUT_MS)) { + this.setSysRoutingTimeout(props.getInt(SYS_ROUTING_TIMEOUT_MS)); + } + + if(props.containsKey(SYS_SOCKET_TIMEOUT_MS)) { + this.setSysSocketTimeout(props.getInt(SYS_SOCKET_TIMEOUT_MS)); + } + + if(props.containsKey(SYS_CONNECTION_TIMEOUT_MS)) { + this.setSysConnectionTimeout(props.getInt(SYS_CONNECTION_TIMEOUT_MS)); + } + + if(props.containsKey(SYS_ENABLE_JMX)) { + this.setSysEnableJmx(props.getBoolean(SYS_ENABLE_JMX)); + } + + if(props.containsKey(SYS_ENABLE_PIPELINE_ROUTED_STORE)) { + this.setSysEnablePipelineRoutedStore(props.getBoolean(SYS_ENABLE_PIPELINE_ROUTED_STORE)); + } + + } + + private ClientConfig setSysMaxConnectionsPerNode(int maxConnectionsPerNode) { + if(maxConnectionsPerNode <= 0) + throw new IllegalArgumentException("Value must be greater than zero."); + this.sysMaxConnectionsPerNode = maxConnectionsPerNode; + return this; + } + + public int getSysMaxConnectionsPerNode() { + return this.sysMaxConnectionsPerNode; + } + + private ClientConfig setSysRoutingTimeout(int sysRoutingTimeout) { + if(sysRoutingTimeout <= 0) + throw new IllegalArgumentException("Value must be greater than zero."); + this.sysRoutingTimeout = sysRoutingTimeout; + return this; + } + + public int getSysRoutingTimeout() { + return this.sysRoutingTimeout; + } + + private ClientConfig setSysSocketTimeout(int sysSocketTimeout) { + if(sysSocketTimeout <= 0) + throw new IllegalArgumentException("Value must be greater than zero."); + this.sysSocketTimeout = sysSocketTimeout; + return this; + } + + public int getSysSocketTimeout() { + return this.sysSocketTimeout; + } + + private ClientConfig setSysConnectionTimeout(int sysConnectionTimeout) { + if(sysConnectionTimeout <= 0) + throw new IllegalArgumentException("Value must be greater than zero."); + this.sysConnectionTimeout = sysConnectionTimeout; + return this; + } + + public int getSysConnectionTimeout() { + return this.sysConnectionTimeout; + } + + public boolean getSysEnableJmx() { + return this.sysEnableJmx; + } + + public ClientConfig setSysEnableJmx(boolean sysEnableJmx) { + this.sysEnableJmx = sysEnableJmx; + return this; + } + + public boolean getSysEnablePipelineRoutedStore() { + return this.sysEnablePipelineRoutedStore; + } + + public ClientConfig setSysEnablePipelineRoutedStore(boolean sysEnablePipelineRoutedStore) { + this.sysEnablePipelineRoutedStore = sysEnablePipelineRoutedStore; + return this; } public int getMaxConnectionsPerNode() { diff --git a/src/java/voldemort/client/ClientInfo.java b/src/java/voldemort/client/ClientInfo.java index d2dfcfb00f..0f28941176 100644 --- a/src/java/voldemort/client/ClientInfo.java +++ b/src/java/voldemort/client/ClientInfo.java @@ -48,6 +48,7 @@ public class ClientInfo implements Serializable { private long updateTime; private String releaseVersion; private ClientConfig config; + private long clusterMetadataVersion; public ClientInfo(String storeName, String clientContext, @@ -64,6 +65,7 @@ public ClientInfo(String storeName, this.updateTime = bootstrapTime; this.releaseVersion = version; this.config = config; + this.clusterMetadataVersion = 0; if(logger.isDebugEnabled()) { logger.debug(this.toString()); @@ -161,6 +163,10 @@ public synchronized ClientConfig getClientConfig() { return this.config; } + public synchronized void setClusterMetadataVersion(long newVersion) { + this.clusterMetadataVersion = newVersion; + } + /** * At the moment we're not checking if the Config objects are similar. TODO: * reevaluate in the future. @@ -195,6 +201,7 @@ public synchronized String toString() { builder.append("storeName=").append(storeName).append("\n"); builder.append("updateTime=").append(updateTime).append("\n"); builder.append("releaseVersion=").append(releaseVersion).append("\n"); + builder.append("clusterMetadataVersion=").append(clusterMetadataVersion).append("\n"); /** * Append the Client Config information. Right now we only track the @@ -222,6 +229,18 @@ public synchronized String toString() { builder.append("failuredetector_implementation=") .append(this.config.getFailureDetectorImplementation()) .append("\n"); + builder.append("failuredetector_threshold=") + .append(this.config.getFailureDetectorThreshold()) + .append("\n"); + builder.append("failuredetector_threshold_count_minimum=") + .append(this.config.getFailureDetectorThresholdCountMinimum()) + .append("\n"); + builder.append("failuredetector_threshold_interval=") + .append(this.config.getFailureDetectorThresholdInterval()) + .append("\n"); + builder.append("failuredetector_threshold_async_recovery_interval=") + .append(this.config.getFailureDetectorAsyncRecoveryInterval()) + .append("\n"); return builder.toString(); } diff --git a/src/java/voldemort/client/SystemStore.java b/src/java/voldemort/client/SystemStore.java index 814265b732..4303002a75 100644 --- a/src/java/voldemort/client/SystemStore.java +++ b/src/java/voldemort/client/SystemStore.java @@ -14,22 +14,91 @@ import voldemort.versioning.Version; import voldemort.versioning.Versioned; +/* + * A client interface for interacting with System stores (managed by the + * cluster). The naming convention is kept consistent with SocketStore (which is + * also a client interface). + */ public class SystemStore { private final Logger logger = Logger.getLogger(SystemStore.class); - private final SocketStoreClientFactory systemStoreFactory; + private final SocketStoreClientFactory socketStoreFactory; private final String storeName; private volatile Store sysStore; + /** + * Wrapper for the actual SystemStore constructor. Used when we dont have + * custom Cluster XML, failure detector or a base Voldemort Client config to + * be used with this system store client. + * + * @param storeName Name of the system store + * @param bootstrapUrls Bootstrap URLs used to connect to + * @param clientZoneID Primary zone ID for this system store client + * (determines routing strategy) + */ public SystemStore(String storeName, String[] bootstrapUrls, int clientZoneID) { - this(storeName, bootstrapUrls, clientZoneID, null, null); + this(storeName, bootstrapUrls, clientZoneID, null, null, new ClientConfig()); } + /** + * Wrapper for the actual SystemStore constructor. Used when we dont have + * custom Cluster XML or failure detector to be used with this system store + * client. + * + * @param storeName Name of the system store + * @param bootstrapUrls Bootstrap URLs used to connect to + * @param clientZoneID Primary zone ID for this system store client + * (determines routing strategy) + * @param baseConfig Base Voldemort Client config which specifies properties + * for this system store client + */ + public SystemStore(String storeName, + String[] bootstrapUrls, + int clientZoneID, + ClientConfig baseConfig) { + this(storeName, bootstrapUrls, clientZoneID, null, null, baseConfig); + } + + /** + * SystemStore Constructor wrapper for the actual constructor. Used when we + * dont want to specify a base Voldemort Client Config. + * + * @param storeName Name of the system store + * @param bootstrapUrls Bootstrap URLs used to connect to + * @param clientZoneID Primary zone ID for this system store client + * (determines routing strategy) + * @param clusterXml Custom ClusterXml to be used for this system store + * client + * @param fd Failure Detector to be used with this system store client + */ public SystemStore(String storeName, String[] bootstrapUrls, int clientZoneID, String clusterXml, FailureDetector fd) { + this(storeName, bootstrapUrls, clientZoneID, clusterXml, fd, new ClientConfig()); + } + + /** + * SystemStore Constructor that creates a system store client which can be + * used to interact with the system stores managed by the cluster + * + * @param storeName Name of the system store + * @param bootstrapUrls Bootstrap URLs used to connect to + * @param clientZoneID Primary zone ID for this system store client + * (determines routing strategy) + * @param clusterXml Custom ClusterXml to be used for this system store + * client + * @param fd Failure Detector to be used with this system store client + * @param baseConfig Base Voldemort Client config which specifies properties + * for this system store client + */ + public SystemStore(String storeName, + String[] bootstrapUrls, + int clientZoneID, + String clusterXml, + FailureDetector fd, + ClientConfig baseConfig) { String prefix = storeName.substring(0, SystemStoreConstants.NAME_PREFIX.length()); if(!SystemStoreConstants.NAME_PREFIX.equals(prefix)) throw new VoldemortException("Illegal system store : " + storeName); @@ -37,17 +106,17 @@ public SystemStore(String storeName, ClientConfig config = new ClientConfig(); config.setSelectors(1) .setBootstrapUrls(bootstrapUrls) - .setMaxConnectionsPerNode(2) - .setConnectionTimeout(1500, TimeUnit.MILLISECONDS) - .setSocketTimeout(5000, TimeUnit.MILLISECONDS) - .setRoutingTimeout(5000, TimeUnit.MILLISECONDS) - .setEnableJmx(false) - .setEnablePipelineRoutedStore(true) + .setMaxConnectionsPerNode(baseConfig.getSysMaxConnectionsPerNode()) + .setConnectionTimeout(baseConfig.getSysConnectionTimeout(), TimeUnit.MILLISECONDS) + .setSocketTimeout(baseConfig.getSysSocketTimeout(), TimeUnit.MILLISECONDS) + .setRoutingTimeout(baseConfig.getSysRoutingTimeout(), TimeUnit.MILLISECONDS) + .setEnableJmx(baseConfig.getSysEnableJmx()) + .setEnablePipelineRoutedStore(baseConfig.getSysEnablePipelineRoutedStore()) .setClientZoneId(clientZoneID); - this.systemStoreFactory = new SystemStoreClientFactory(config); + this.socketStoreFactory = new SocketStoreClientFactory(config); this.storeName = storeName; try { - this.sysStore = this.systemStoreFactory.getSystemStore(this.storeName, clusterXml, fd); + this.sysStore = this.socketStoreFactory.getSystemStore(this.storeName, clusterXml, fd); } catch(Exception e) { logger.debug("Error while creating a system store client for store : " + this.storeName); } diff --git a/src/java/voldemort/client/SystemStoreClientFactory.java b/src/java/voldemort/client/SystemStoreClientFactory.java deleted file mode 100644 index 2cbd832464..0000000000 --- a/src/java/voldemort/client/SystemStoreClientFactory.java +++ /dev/null @@ -1,14 +0,0 @@ -package voldemort.client; - -public class SystemStoreClientFactory extends SocketStoreClientFactory { - - public SystemStoreClientFactory(ClientConfig config) { - super(config); - } - - @Override - public int getNextJmxId() { - // for system store, we don't increment jmx id - return getCurrentJmxId(); - } -} diff --git a/src/java/voldemort/client/SystemStoreRepository.java b/src/java/voldemort/client/SystemStoreRepository.java index e8e19f5d41..38289a91b2 100644 --- a/src/java/voldemort/client/SystemStoreRepository.java +++ b/src/java/voldemort/client/SystemStoreRepository.java @@ -29,7 +29,8 @@ public void createSystemStores(ClientConfig config, String clusterXml, FailureDe config.getBootstrapUrls(), config.getClientZoneId(), clusterXml, - fd); + fd, + config); this.sysStoreMap.put(storeName.name(), sysStore); } } diff --git a/src/java/voldemort/client/ZenStoreClient.java b/src/java/voldemort/client/ZenStoreClient.java index afe82b4f04..6db6492cbf 100644 --- a/src/java/voldemort/client/ZenStoreClient.java +++ b/src/java/voldemort/client/ZenStoreClient.java @@ -65,7 +65,8 @@ public class ZenStoreClient extends DefaultStoreClient { private final SchedulerService scheduler; private ClientInfo clientInfo; private String clusterXml; - private AsyncMetadataVersionManager asyncCheckMetadata = null; + private AsyncMetadataVersionManager asyncMetadataManager = null; + private ClientRegistryRefresher clientRegistryRefresher = null; public ZenStoreClient(String storeName, InconsistencyResolver> resolver, @@ -111,23 +112,24 @@ public ZenStoreClient(String storeName, // Initialize the background thread for checking metadata version if(config != null) { - asyncCheckMetadata = scheduleMetadataChecker(clientId.toString(), - config.getAsyncMetadataRefreshInMs()); + asyncMetadataManager = scheduleAsyncMetadataVersionManager(clientId.toString(), + config.getAsyncMetadataRefreshInMs()); } - registerClient(clientId, config.getClientRegistryUpdateInSecs()); + clientRegistryRefresher = registerClient(clientId, config.getClientRegistryUpdateInSecs()); logger.info("Voldemort client created: " + clientId + "\n" + clientInfo); } - private void registerClient(String jobId, int interval) { + private ClientRegistryRefresher registerClient(String jobId, int interval) { + ClientRegistryRefresher refresher = null; if(this.sysRepository.getClientRegistryStore() != null) { try { Version version = this.sysRepository.getClientRegistryStore() .putSysStore(clientId, clientInfo.toString()); - ClientRegistryRefresher refresher = new ClientRegistryRefresher(this.sysRepository, - clientId, - clientInfo, - version); + refresher = new ClientRegistryRefresher(this.sysRepository, + clientId, + clientInfo, + version); GregorianCalendar cal = new GregorianCalendar(); cal.add(Calendar.SECOND, interval); @@ -148,10 +150,12 @@ private void registerClient(String jobId, int interval) { logger.warn(SystemStoreConstants.SystemStoreName.voldsys$_client_registry.name() + "not found. Unable to registry with voldemort cluster."); } + return refresher; } - private AsyncMetadataVersionManager scheduleMetadataChecker(String jobId, long interval) { - AsyncMetadataVersionManager asyncCheckMetadata = null; + private AsyncMetadataVersionManager scheduleAsyncMetadataVersionManager(String jobId, + long interval) { + AsyncMetadataVersionManager asyncMetadataManager = null; SystemStore versionStore = this.sysRepository.getVersionStore(); if(versionStore == null) { logger.warn("Metadata version system store not found. Cannot run Metadata version check thread."); @@ -166,14 +170,14 @@ public Void call() throws Exception { } }; - asyncCheckMetadata = new AsyncMetadataVersionManager(this.sysRepository, - rebootstrapCallback); + asyncMetadataManager = new AsyncMetadataVersionManager(this.sysRepository, + rebootstrapCallback); // schedule the job to run every 'checkInterval' period, starting // now if(scheduler != null) { - scheduler.schedule(jobId + asyncCheckMetadata.getClass().getName(), - asyncCheckMetadata, + scheduler.schedule(jobId + asyncMetadataManager.getClass().getName(), + asyncMetadataManager, new Date(), interval); logger.info("Metadata version check thread started. Frequency = Every " + interval @@ -182,7 +186,7 @@ public Void call() throws Exception { logger.warn("Metadata version check thread won't start because the scheduler service is not configured."); } } - return asyncCheckMetadata; + return asyncMetadataManager; } @Override @@ -209,16 +213,26 @@ public void bootStrap() { * Metadata exception). This will prevent another bootstrap via the * Async metadata checker */ - if(asyncCheckMetadata != null) { - asyncCheckMetadata.updateMetadataVersions(); + if(asyncMetadataManager != null) { + asyncMetadataManager.updateMetadataVersions(); } /* * Every time we bootstrap, update the bootstrap time */ if(this.clientInfo != null) { + if(this.asyncMetadataManager != null) { + this.clientInfo.setClusterMetadataVersion(this.asyncMetadataManager.getClusterMetadataVersion()); + } this.clientInfo.setBootstrapTime(System.currentTimeMillis()); } + + if(this.clientRegistryRefresher == null) { + logger.error("Unable to publish the client registry after bootstrap. Client Registry Refresher is NULL."); + } else { + logger.info("Publishing client registry after Bootstrap."); + this.clientRegistryRefresher.publishRegistry(); + } } public String getClientId() { @@ -228,7 +242,7 @@ public String getClientId() { @JmxGetter(name = "getClusterMetadataVersion") public String getClusterMetadataVersion() { String result = "Current Cluster Metadata Version : " - + this.asyncCheckMetadata.getClusterMetadataVersion(); + + this.asyncMetadataManager.getClusterMetadataVersion(); return result; } diff --git a/src/java/voldemort/client/protocol/admin/AdminClient.java b/src/java/voldemort/client/protocol/admin/AdminClient.java index f2a6915e46..a2dcfe2d80 100644 --- a/src/java/voldemort/client/protocol/admin/AdminClient.java +++ b/src/java/voldemort/client/protocol/admin/AdminClient.java @@ -245,7 +245,8 @@ public void initSystemStoreClient() { } /** - * Increment the metadata version for the given key (cluster or store) + * Update the metadata version for the given key (cluster or store). The new + * value set is the current timestamp. * * @param versionKey The metadata key for which Version should be * incremented @@ -253,17 +254,17 @@ public void initSystemStoreClient() { public void updateMetadataversion(String versionKey) { initSystemStoreClient(); Properties props = MetadataVersionStoreUtils.getProperties(this.sysStoreVersion); + long newValue = 0; if(props != null && props.getProperty(versionKey) != null) { logger.debug("Version obtained = " + props.getProperty(versionKey)); - long newValue = Long.parseLong(props.getProperty(versionKey)) + 1; - props.setProperty(versionKey, Long.toString(newValue)); + newValue = System.currentTimeMillis(); } else { logger.debug("Current version is null. Assuming version 0."); if(props == null) { props = new Properties(); } - props.setProperty(versionKey, "0"); } + props.setProperty(versionKey, Long.toString(newValue)); MetadataVersionStoreUtils.setProperties(this.sysStoreVersion, props); } diff --git a/src/java/voldemort/client/scheduler/AsyncMetadataVersionManager.java b/src/java/voldemort/client/scheduler/AsyncMetadataVersionManager.java index fe55c4c8d4..f90862dc12 100644 --- a/src/java/voldemort/client/scheduler/AsyncMetadataVersionManager.java +++ b/src/java/voldemort/client/scheduler/AsyncMetadataVersionManager.java @@ -18,6 +18,9 @@ * init if the initial version turns out to be null, it means that no change has * been done to that store since it was created. In this case, we assume version * '0'. + * + * At the moment, this only tracks the cluster.xml changes. TODO: Extend this to + * track other stuff (like stores.xml) */ public class AsyncMetadataVersionManager implements Runnable { @@ -84,7 +87,11 @@ public Long fetchNewVersion(String versionKey, Long curVersion, Properties versi logger.debug("MetadataVersion check => Obtained " + versionKey + " version : " + newVersion); - if(!newVersion.equals(curVersion)) { + /* + * Check if the new version is greater than the current one. We + * should not re-bootstrap on a stale version. + */ + if(newVersion > curVersion) { return newVersion; } } else { @@ -103,8 +110,10 @@ public Long fetchNewVersion(String versionKey, Long curVersion, Properties versi public void run() { try { - // Get the properties object from the system store (containing - // versions) + /* + * Get the properties object from the system store (containing + * versions) + */ Properties versionProps = MetadataVersionStoreUtils.getProperties(this.sysRepository.getMetadataVersionStore()); Long newClusterVersion = fetchNewVersion(CLUSTER_VERSION_KEY, currentClusterVersion, @@ -112,39 +121,20 @@ public void run() { // If nothing has been updated, continue if(newClusterVersion != null) { - - logger.info("Metadata version mismatch detected."); - - // Determine a random delta delay between 0 to DELTA_MAX to - // sleep - int delta = randomGenerator.nextInt(DELTA_MAX); - + logger.info("Metadata version mismatch detected. Re-bootstrapping !!!"); try { - logger.info("Sleeping for delta : " + delta + " (ms) before re-bootstrapping."); - Thread.sleep(delta); - } catch(InterruptedException e) { - // do nothing, continue. - } - - /* - * Do another check for mismatch here since the versions might - * have been updated while we were sleeping - */ - if(!newClusterVersion.equals(currentClusterVersion)) { - - try { - logger.info("Updating cluster version"); - currentClusterVersion = newClusterVersion; - - this.storeClientThunk.call(); - } catch(Exception e) { - if(logger.isDebugEnabled()) { - e.printStackTrace(); - logger.debug(e.getMessage()); - } + logger.info("Updating cluster version"); + currentClusterVersion = newClusterVersion; + + this.storeClientThunk.call(); + } catch(Exception e) { + if(logger.isDebugEnabled()) { + e.printStackTrace(); + logger.debug(e.getMessage()); } } } + } catch(Exception e) { logger.debug("Could not retrieve metadata versions from the server."); } @@ -155,9 +145,12 @@ public Long getClusterMetadataVersion() { return this.currentClusterVersion; } - // Fetch the latest versions for cluster and store + // Fetch the latest versions for cluster metadata public void updateMetadataVersions() { Properties versionProps = MetadataVersionStoreUtils.getProperties(this.sysRepository.getMetadataVersionStore()); - this.currentClusterVersion = fetchNewVersion(CLUSTER_VERSION_KEY, null, versionProps); + Long newVersion = fetchNewVersion(CLUSTER_VERSION_KEY, null, versionProps); + if(newVersion != null) { + this.currentClusterVersion = newVersion; + } } } diff --git a/src/java/voldemort/client/scheduler/ClientRegistryRefresher.java b/src/java/voldemort/client/scheduler/ClientRegistryRefresher.java index e92ad00e56..cbffd3bfa9 100644 --- a/src/java/voldemort/client/scheduler/ClientRegistryRefresher.java +++ b/src/java/voldemort/client/scheduler/ClientRegistryRefresher.java @@ -51,22 +51,26 @@ public ClientRegistryRefresher(SystemStoreRepository sysRepository, logger.info("Initial version obtained from client registry: " + version); } - public void run() { - - if(hadConflict) { - // if we previously had a conflict during update, we will try to get - // a newer version before update this time. This case shall not - // happen under regular circumstances. But it is just avoid update - // keeping failing when strange situations occur. - lastVersion = this.systemStoreRepository.getClientRegistryStore() - .getSysStore(clientId) - .getVersion(); - hadConflict = false; - } - clientInfo.setUpdateTime(System.currentTimeMillis()); - logger.info("updating client registry with the following info for client: " + clientId - + "\n" + clientInfo); + /* + * Procedure to publish client registry info in the system store. + */ + public synchronized void publishRegistry() { try { + if(hadConflict) { + /* + * if we previously had a conflict during update, we will try to + * get a newer version before update this time. This case shall + * not happen under regular circumstances. But it is just avoid + * update keeping failing when strange situations occur. + */ + lastVersion = this.systemStoreRepository.getClientRegistryStore() + .getSysStore(clientId) + .getVersion(); + hadConflict = false; + } + clientInfo.setUpdateTime(System.currentTimeMillis()); + logger.info("updating client registry with the following info for client: " + clientId + + "\n" + clientInfo); lastVersion = this.systemStoreRepository.getClientRegistryStore() .putSysStore(clientId, new Versioned(clientInfo.toString(), @@ -84,4 +88,8 @@ public void run() { + e); } } + + public void run() { + publishRegistry(); + } } diff --git a/src/java/voldemort/cluster/failuredetector/BannagePeriodFailureDetector.java b/src/java/voldemort/cluster/failuredetector/BannagePeriodFailureDetector.java index 218992fa59..62966c9dca 100644 --- a/src/java/voldemort/cluster/failuredetector/BannagePeriodFailureDetector.java +++ b/src/java/voldemort/cluster/failuredetector/BannagePeriodFailureDetector.java @@ -49,6 +49,7 @@ */ @JmxManaged(description = "Detects the availability of the nodes on which a Voldemort cluster runs") +@Deprecated public class BannagePeriodFailureDetector extends AbstractFailureDetector { public BannagePeriodFailureDetector(FailureDetectorConfig failureDetectorConfig) { diff --git a/src/java/voldemort/store/configuration/FileBackedCachingStorageEngine.java b/src/java/voldemort/store/configuration/FileBackedCachingStorageEngine.java index 62830af188..ac9216e4cf 100644 --- a/src/java/voldemort/store/configuration/FileBackedCachingStorageEngine.java +++ b/src/java/voldemort/store/configuration/FileBackedCachingStorageEngine.java @@ -31,6 +31,15 @@ import voldemort.versioning.Version; import voldemort.versioning.Versioned; +/* + * A Storage Engine used to persist the keys and values in a human readable + * format on disk. The data is primarily served off of the cache. After each + * put, the entire cache state is flushed to the backing file. The data is UTF-8 + * serialized when writing to the file in order to make it human readable. + * + * The primary purpose of this storage engine is for maintaining the cluster + * metadata which is characterized by low QPS and not latency sensitive. + */ public class FileBackedCachingStorageEngine implements StorageEngine { private final static Logger logger = Logger.getLogger(FileBackedCachingStorageEngine.class); diff --git a/test/unit/voldemort/store/system/SystemStoreTest.java b/test/unit/voldemort/store/system/SystemStoreTest.java index a9f5e67ab2..4f6b12ffbf 100644 --- a/test/unit/voldemort/store/system/SystemStoreTest.java +++ b/test/unit/voldemort/store/system/SystemStoreTest.java @@ -118,6 +118,7 @@ public void testCustomClusterXmlStore() { @Test public void testIllegalSystemStore() { try { + @SuppressWarnings("unused") SystemStore sysVersionStore = new SystemStore("test-store", bootStrapUrls, this.CLIENT_ZONE_ID,