All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.spikeify.commands.InfoFetcher Maven / Gradle / Ivy

There is a newer version: 0.2.35
Show newest version
package com.spikeify.commands;

import com.aerospike.client.IAerospikeClient;
import com.aerospike.client.Info;
import com.aerospike.client.async.IAsyncClient;
import com.aerospike.client.cluster.Node;
import com.aerospike.client.query.IndexCollectionType;
import com.aerospike.client.query.IndexType;
import com.spikeify.IndexingService;

import java.util.*;

/**
 * A command chain for fetching various information from database.
 */
@SuppressWarnings("WeakerAccess")
public class InfoFetcher {

	protected final IAerospikeClient synClient;

	public static final String CONFIG_SET_NAME = "set_name";
	public static final String CONFIG_NS_NAME = "ns_name";
	public static final String CONFIG_SET_PARAM = "sets";
	public static final String CONFIG_SET_INDEXES = "sindex";
	public static final String CONFIG_NAMESPACES_PARAM = "namespaces";
	public static final String CONFIG_RECORDS_COUNT = "n_objects";
	public static final String CONFIG_BUILD = "build";
	public static final String CONFIG_NAMESPACE = "get-config:context=namespace;id=";
	public static final String REPLICATION_FACTOR = "repl-factor";

	public InfoFetcher(IAsyncClient synClient) {

		this.synClient = synClient;
	}

	public static class Build {

		public int major;
		public int minor;
		public int release;

		public Build(int major, int minor, int release) {

			this.major = major;
			this.minor = minor;
			this.release = release;
		}
	}

	/**
	 * Returns the server build.
	 *
	 * @return server build string
	 */
	public Build getServerBuild() {

		String build = null;
		Node[] nodes = synClient.getNodes();
		if (nodes == null || nodes.length == 0) {
			throw new IllegalStateException("No Aerospike nodes found.");
		}
		build = Info.request(synClient.getInfoPolicyDefault(), nodes[0], CONFIG_BUILD);
		String[] buildNumbers = build.split("\\.");

		return new Build(Integer.valueOf(buildNumbers[0]), Integer.valueOf(buildNumbers[1]), Integer.valueOf(buildNumbers[2]));
	}

	public String[] getNamespaceConfig(String namespace) {

		String build = null;
		Node[] nodes = synClient.getNodes();
		if (nodes == null || nodes.length == 0) {
			throw new IllegalStateException("No Aerospike nodes found.");
		}
		return Info.request(synClient.getInfoPolicyDefault(), nodes[0], CONFIG_NAMESPACE + namespace).split(";");
	}

	public long getDefaultTTL(String namespace) {
		Node[] nodes = synClient.getNodes();
		if (nodes == null || nodes.length == 0) {
			throw new IllegalStateException("No Aerospike nodes found.");
		}
		String[] config = Info.request(synClient.getInfoPolicyDefault(), nodes[0], CONFIG_NAMESPACE + namespace).split(";");

		return Long.valueOf(parseConfigString(config, "default-ttl", "0"));
	}

	public boolean isUDFEnabled(String namespace) {
		Node[] nodes = synClient.getNodes();
		if (nodes == null || nodes.length == 0) {
			throw new IllegalStateException("No Aerospike nodes found.");
		}
		String[] config = Info.request(synClient.getInfoPolicyDefault(), nodes[0], CONFIG_NAMESPACE + namespace).split(";");

		return Boolean.valueOf(parseConfigString(config, "ldt-enabled", "false"));
	}

	public int getReplicationFactor(String namespace) {
		Node[] nodes = synClient.getNodes();
		if (nodes == null || nodes.length == 0) {
			throw new IllegalStateException("No Aerospike nodes found.");
		}
		String[] configStrings = Info.request(synClient.getInfoPolicyDefault(), nodes[0], CONFIG_NAMESPACE + namespace).split(";");
		for (String configString : configStrings) {
			String[] configLine = configString.split("=");
			if (configLine.length == 2 && configLine[0].equals(REPLICATION_FACTOR)) {
				return Integer.valueOf(configLine[1]);
			}
		}
		return 1;
	}

	/**
	 * Returns the number of records in given namespace and set.
	 *
	 * @param namespace The namespace.
	 * @param clazz     The name of the set.
	 * @return number of records in given namespace and set
	 */
	public int getRecordCount(String namespace, Class clazz) {

		return getRecordCount(namespace, IndexingService.getSetName(clazz));
	}

	/**
	 * Returns the number of records in given namespace and set.
	 *
	 * @param namespace The namespace.
	 * @param setName   The name of the set.
	 * @return number of records in given namespace and set
	 */
	public int getRecordCount(String namespace, String setName) {

		int count = 0;

		int replicationFactor = getReplicationFactor(namespace);

		Node[] nodes = synClient.getNodes();
		int nodeCount = nodes.length;
		for (Node node : nodes) {
			String[] nodeSets = Info.request(synClient.getInfoPolicyDefault(), node, CONFIG_SET_PARAM + "/" + namespace + "/" + setName).split(":");
			count += Integer.valueOf(parseConfigString(nodeSets, CONFIG_RECORDS_COUNT, "0"));
		}
		return count / Math.min(replicationFactor, nodeCount);
	}

	/**
	 * Fetches all namespaces available in database..
	 *
	 * @return A set of namespaces
	 */
	public Set getNamespaces() {

		Set nsNames = new HashSet<>();
		Node[] nodes = synClient.getNodes();
		for (Node node : nodes) {
			String nodeNsNames = Info.request(synClient.getInfoPolicyDefault(), node, CONFIG_NAMESPACES_PARAM);
			String[] nsNamesArray = nodeNsNames.split(";");
			Collections.addAll(nsNames, nsNamesArray);
		}
		return nsNames;
	}

	/**
	 * Fetches all Sets available in database.
	 *
	 * @return A map of sets and the namespaces they belong to
	 */
	public Map getSets() {

		Map setNames = new HashMap<>();

		Node[] nodes = synClient.getNodes();
		for (Node node : nodes) {
			String nodeSets = Info.request(synClient.getInfoPolicyDefault(), node, CONFIG_SET_PARAM);
			String[] set = nodeSets.split(";");
			for (String setString : set) {
				Map config = parseConfigString(setString);
				setNames.put(config.get(CONFIG_SET_NAME), config.get(CONFIG_NS_NAME));
			}
		}

		return setNames;
	}

	/**
	 * Fetches all indexes available in namespace..
	 *
	 * @param namespace namespace
	 * @return map of index name / {@link IndexInfo}
	 */
	public Map getIndexes(String namespace) {

		return getIndexes(namespace, (String) null);
	}

	/**
	 * Fetches all indexes of specific set available in namespace..
	 *
	 * @param namespace namespace
	 * @param clazz     entity type
	 * @return map of index name / {@link IndexInfo}
	 */
	public Map getIndexes(String namespace, Class clazz) {

		return getIndexes(namespace, IndexingService.getSetName(clazz));
	}

	/**
	 * Fetches all indexes of specific set available in namespace..
	 *
	 * @param namespace namespace
	 * @param setName   entity name / table name
	 * @return map of index info (index_name / info)
	 */
	public Map getIndexes(String namespace, String setName) {

		Map indexInfoSet = new HashMap<>();
		Node[] nodes = synClient.getNodes();
		for (Node node : nodes) {

			String indexInfo = Info.request(synClient.getInfoPolicyDefault(), node, CONFIG_SET_INDEXES + "/" + namespace);
			String[] set = indexInfo.split(";");

			for (String setString : set) {
				IndexInfo info = new IndexInfo(setString);

				// only if all data is given add to list
				if ((setName == null || setName.equals(info.setName)) &&
						info.isComplete()) {
					indexInfoSet.put(info.name, info);
				}
			}
		}

		return indexInfoSet;
	}


	public IndexInfo findIndex(String namespace, String setName, String fieldName) {

		Map list = getIndexes(namespace, setName);
		for (IndexInfo info : list.values()) {
			if (info.fieldName.equals(fieldName)) {
				return info;
			}
		}

		return null;
	}


	private Map parseConfigString(String configString) {

		Map result = new HashMap<>();
		String[] chunks = configString.split(":");
		for (String chunk : chunks) {
			String[] chunkParts = chunk.split("=");
			if (chunkParts.length == 2) {
				result.put(chunkParts[0], chunkParts[1]);
			}
		}
		return result;
	}

	private String parseConfigString(String[] configStrings, String paramName, String defaultValue) {

		for (String chunk : configStrings) {
			String[] chunkParts = chunk.split("=");
			if (chunkParts.length == 2 && paramName.equals(chunkParts[0])) {
				return chunkParts[1];
			}
		}

		return defaultValue;
	}

	/**
	 * Holds information about index
	 */
	public class IndexInfo {

		public String namespace;

		public String setName;

		public String fieldName;

		public String name;

		public IndexType indexType;

		public IndexCollectionType collectionType = IndexCollectionType.DEFAULT;

		public boolean synced;
		public boolean canRead;
		public boolean canWrite;

		public IndexInfo(String nodeInfo) {

			// index info is parsed from string ... in format
			// ns=test:set=EntityOne:indexname=index_one:num_bins=1:bins=one:type=INT SIGNED:indextype=NONE:path=one:sync_state=synced:state=RW;
			Map chunks = parseConfigString(nodeInfo);
			for (String key : chunks.keySet()) {
				String value = chunks.get(key);

				if (value != null) { // prevent null pointer if nothing found
					switch (key) {
						case "ns":
							namespace = value;
							break;

						case "set":
							setName = value;
							break;

						case "indexname":
							name = value;
							break;

						case "path":
							fieldName = value;
							break;

						case "type":
							if (value.equals("NUMERIC") || value.startsWith("INT")) {
								indexType = IndexType.NUMERIC;
							} else if (value.equals("TEXT") || value.equals("STRING")) {
								indexType = IndexType.STRING;
							} else {
								throw new IllegalStateException("Unknown index type: " + value);
							}
							break;

						case "indextype":

							try {
								collectionType = IndexCollectionType.valueOf(value);
							} catch (IllegalArgumentException e) {
								collectionType = IndexCollectionType.DEFAULT;
							}

							break;

						case "sync_state":
							synced = "synced".equals(value);
							break;

						case "state":
							canRead = value.contains("R");
							canWrite = value.contains("W");
							break;
					}
				}
			}
		}

		public boolean isComplete() {

			return name != null &&
					namespace != null &&
					setName != null &&
					fieldName != null;
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy