
oracle.kv.impl.admin.topo.TopologyCandidate Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of oracle-nosql-server Show documentation
Show all versions of oracle-nosql-server Show documentation
NoSQL Database Server - supplies build and runtime support for the server (store) side of the Oracle NoSQL Database.
The newest version!
/*-
* Copyright (C) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This file was distributed by Oracle as part of a version of Oracle NoSQL
* Database made available at:
*
* http://www.oracle.com/technetwork/database/database-technologies/nosqldb/downloads/index.html
*
* Please see the LICENSE file included in the top-level directory of the
* appropriate version of Oracle NoSQL Database for a copy of the license and
* additional information.
*/
package oracle.kv.impl.admin.topo;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import oracle.kv.impl.admin.param.DatacenterParams;
import oracle.kv.impl.admin.param.Parameters;
import oracle.kv.impl.admin.param.RepNodeParams;
import oracle.kv.impl.admin.param.StorageNodeParams;
import oracle.kv.impl.param.ParameterMap;
import oracle.kv.impl.param.SizeParameter;
import oracle.kv.impl.topo.Datacenter;
import oracle.kv.impl.topo.DatacenterId;
import oracle.kv.impl.topo.RepNodeId;
import oracle.kv.impl.topo.StorageNodeId;
import oracle.kv.impl.topo.Topology;
import oracle.kv.impl.util.TopologyPrinter;
import org.codehaus.jackson.node.ObjectNode;
import com.sleepycat.persist.model.Entity;
import com.sleepycat.persist.model.PrimaryKey;
/**
* The topology candidate packages:
* - a user provided name
* - a target topology that is a prospective layout for the store
* - information about how we arrived at the target topology, used to illuminate
* the decision process for the user, and as a debugging aid.
*
* Candidates are generated and updated in response to user actions. The
* "topology create" command makes the initial candidate, while commands such
* as "topology redistribute" modify a candidate. Candidates are only
* blueprints for potential store layouts. A topology that is actually deployed
* is represented by a RealizedTopology instance.
*
* version 0: original
* version 1: add rnLogDirAssignments
*/
@Entity(version=1)
public class TopologyCandidate implements Serializable {
private static final long serialVersionUID = 1L;
/**
* NO_NAME is used for situations where we need compatibility with R1,
* which is before candidates existed, or for topology changing commands
* that do not require a user created candidate topology. For example, the
* migrate-sn command changes the topology, but since the parameters to the
* command adequately describe the change, that command doesn't require
* that the user supply a candidate,
*/
public static final String NO_NAME = "none";
/**
* Candidate names containing this substring are reserved for system use.
*/
public static final String RESERVED_SUBSTRING = "$";
/**
* Candidate names starting with this prefix are reserved for internal
* system use. These names are for topology candidates that are not
* intended to be referred to by users.
*/
public static final String INTERNAL_NAME_PREFIX = "$$internal-";
@PrimaryKey
private String candidateName;
private Topology topology;
/**
* Map of the rep nodes which have assigned storage directories. The
* map contains the directory path. The directory size needs to be
* obtained from the parameters.
*
* Note that we now use "storage directory" instead of "mount point", but
* since the field is serialized it would be a pain to change.
*/
private Map mountPointAssignments;
/**
* Map of the rep nodes which have assigned RN log directories. The
* map contains the RN log directory path. The directory size needs to be
* obtained from the parameters.
*/
private Map rnLogDirAssignments;
/* For debugging/auditing */
private Map maxShards;
private DatacenterId smallestDC;
private List auditTrail;
/* For DPL */
@SuppressWarnings("unused")
private TopologyCandidate() {
}
public TopologyCandidate(String name, Topology topoCopy) {
candidateName = name;
topology = topoCopy;
maxShards = new HashMap<>();
auditTrail = new ArrayList<>();
mountPointAssignments = new HashMap<>();
rnLogDirAssignments = new HashMap<>();
log("starting number of shards: " + topoCopy.getRepGroupMap().size());
log("number of partitions: " + topoCopy.getPartitionMap().size());
}
/**
* Constructor for creating a copy of an existing candidate. Debug and
* auditing information is _not_ copied from the source candidate.
*/
private TopologyCandidate(TopologyCandidate source) {
this(source.getName(), source.getTopology().getCopy());
mountPointAssignments.putAll(source.mountPointAssignments);
rnLogDirAssignments.putAll(source.rnLogDirAssignments);
}
/**
* Gets a copy of this candidate. The debug and auditing information is
* cleared in the returned candidate.
*/
public TopologyCandidate getCopy() {
return new TopologyCandidate(this);
}
public Topology getTopology() {
return topology;
}
public void resetTopology(Topology topo) {
topology = topo;
}
public String getName() {
return candidateName;
}
public void setShardsPerDC(DatacenterId dcId, int numShards) {
maxShards.put(dcId, numShards);
}
public void setSmallestDC(DatacenterId dcId) {
smallestDC = dcId;
}
String getSmallestDCName(Parameters params) {
if (smallestDC != null) {
return smallestDC + "/" + params.get(smallestDC).getName();
}
return null;
}
/**
* Display the candidate. If verbose is specified, show the fields meant
* for auditing/debug use.
*/
String display(Parameters params) {
StringBuilder sb = new StringBuilder();
sb.append("name= ").append(candidateName);
sb.append("\nzones= ").append(getDatacenters());
sb.append("\n");
sb.append(TopologyPrinter.printTopology(this, params, false));
return sb.toString();
}
public String displayAsJson(Parameters params) {
ObjectNode jsonNode = TopologyPrinter.getTopoJson(topology, params);
jsonNode.put("name", candidateName);
return jsonNode.toString();
}
public Set getDatacenters() {
Set dcIds = new HashSet<>();
for (Datacenter dc : topology.getDatacenterMap().getAll()) {
dcIds.add(dc.getResourceId());
}
return dcIds;
}
public String showDatacenters(Parameters params) {
StringBuilder sb = new StringBuilder();
for (Map.Entry entry : maxShards.entrySet()) {
DatacenterId dcId = entry.getKey();
DatacenterParams dcp = params.get(dcId);
sb.append(dcId).append("/").append(dcp.getName());
sb.append(" maximum shards= ").append(entry.getValue());
sb.append("\n");
}
return sb.toString();
}
String showAudit() {
StringBuilder sb = new StringBuilder();
sb.append("[Audit]\n");
for(String s : auditTrail) {
sb.append(s).append("\n");
}
return sb.toString();
}
/**
* Save some information about the building of the topology, for audit/
* debugging assistance later.
*/
public void log(String s) {
auditTrail.add(s);
}
/**
* Saves the specified directory path assignment.
*
* @param rnId the rn to be assigned
* @param path the directory path the rn is assigned to
*/
void saveDirectoryAssignment(RepNodeId rnId, String path) {
mountPointAssignments.put(rnId, path);
}
/**
* Removes the assignment for the specified rn.
*
* @param rnId the rn to remove
*/
void removeDirectoryAssignment(RepNodeId rnId) {
mountPointAssignments.remove(rnId);
}
/**
* Gets a map of directory paths. There will be one entry for
* each rep node which has a directory assignment.
*/
public Map getDirectoryAssignments() {
return mountPointAssignments;
}
/**
* Saves the specified RN log directory path assignment.
*
* @param rnId the rn to be assigned
* @param path the rn log directory path the rn is assigned to
*/
void saveRNLogDirectoryAssignment(RepNodeId rnId, String path) {
rnLogDirAssignments.put(rnId, path);
}
/**
* Removes the assignment for the specified RN log dir.
*
* @param rnId the rn to remove
*/
void removeRNLogDirectoryAssignment(RepNodeId rnId) {
rnLogDirAssignments.remove(rnId);
}
/**
* Gets a map of RN log directory paths. There will be one entry for
* each rep node which has a RN log directory assignment.
*/
public Map getRNLogDirectoryAssignments() {
return rnLogDirAssignments;
}
/**
* Gets a StorageDirectory instance for the specified rep node. If the
* rep node is not assigned a directory, the returned StorageDirectory will
* be for the root directory.
*/
StorageDirectory getStorageDir(RepNodeId rnId, Parameters params) {
return getStorageDir(rnId, this, topology, params);
}
/**
* Gets a RNlogDirectory instance for the specified rep node. If the
* rep node is not assigned a RN log directory, the returned RN log
* Directory will be for the root directory.
*/
LogDirectory getRNLogDir(RepNodeId rnId, Parameters params) {
return getRNLogDir(rnId, this, params);
}
/**
* Gets a map of StorageDirectory instances. There will be one entry for
* each rep node which has a directory assignment.
*/
public Map
getStorageDirAssignments(Parameters params) {
final Map sdm =
new HashMap<>(mountPointAssignments.size());
for (RepNodeId rnId : mountPointAssignments.keySet()) {
sdm.put(rnId, getStorageDir(rnId, params));
}
return sdm;
}
/**
* Gets a map of RNlogDirectory instances. There will be one entry for
* each rep node which has a directory assignment.
*/
public Map
getRNLogDirAssignments(Parameters params) {
final Map sdm =
new HashMap<>(rnLogDirAssignments.size());
for (RepNodeId rnId : rnLogDirAssignments.keySet()) {
sdm.put(rnId, getRNLogDir(rnId, params));
}
return sdm;
}
/**
* Gets a StorageDirectory instance for the specified rep node. If
* candidate is not null the candidate assignments are checked first for
* a directory path otherwise the path is obtained from the rep node
* parameters. The directory size is obtained from the storage node
* parameters.
*/
static StorageDirectory getStorageDir(RepNodeId rnId,
TopologyCandidate candidate,
Topology topo,
Parameters params) {
/*
* If a candidate was specified and it contains an assignment use that,
* otherwise check the rep node parameters for directory path.
*/
final String path;
if ((candidate != null) &&
candidate.mountPointAssignments.containsKey(rnId)) {
path = candidate.mountPointAssignments.get(rnId);
} else {
final RepNodeParams rnp = params.get(rnId);
path = (rnp == null) ? null : rnp.getStorageDirectoryPath();
}
/*
* Get the size from the storage note parameters. If path is null use
* the root directory's size.
*/
final StorageNodeId snId = topo.get(rnId).getStorageNodeId();
final StorageNodeParams snp = params.get(snId);
final long size;
if (path == null) {
size = snp.getRootDirSize();
} else {
final ParameterMap storageDirMap = snp.getStorageDirMap();
size = (storageDirMap == null) ? 0L :
SizeParameter.getSize(storageDirMap.get(path));
}
return new StorageDirectory(path, size);
}
/**
* Gets a RNLogDirectory instance for the specified rep node. If
* candidate is not null the candidate assignments are checked first for
* a directory path otherwise the path is obtained from the rep node
* parameters. The directory size is set to default 0L till rnlogdirsize
* is exposed.
*/
static LogDirectory getRNLogDir(RepNodeId rnId,
TopologyCandidate candidate,
Parameters params) {
/*
* If a candidate was specified and it contains an assignment use that,
* otherwise check the rep node parameters for directory path.
*/
final String path;
if ((candidate != null) &&
candidate.rnLogDirAssignments.containsKey(rnId)) {
path = candidate.rnLogDirAssignments.get(rnId);
} else {
final RepNodeParams rnp = params.get(rnId);
path = (rnp == null) ? null : rnp.getLogDirectoryPath();
}
return new LogDirectory(path, 0L);
}
private void readObject(ObjectInputStream in)
throws ClassNotFoundException, IOException {
in.defaultReadObject();
/* After an upgrade rnLogDirAssignments can be null */
if (rnLogDirAssignments == null) {
rnLogDirAssignments = new HashMap<>();
}
}
@Override
public String toString() {
return "TopologyCandidate[" + candidateName + "]";
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy