
com.tangosol.license.ProcessorInfo Maven / Gradle / Ivy
/*
* Copyright (c) 2000, 2020, Oracle and/or its affiliates.
*
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
package com.tangosol.license;
import com.tangosol.coherence.config.Config;
import com.tangosol.util.Base;
import com.tangosol.util.UID;
import com.tangosol.net.CacheFactory;
import com.tangosol.run.xml.SimpleElement;
import com.tangosol.run.xml.SimpleParser;
import com.tangosol.run.xml.XmlElement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.regex.Pattern;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.security.Signature;
import java.security.cert.CertificateFactory;
import java.security.cert.Certificate;
/**
* Provides information regarding host platform's CPUs.
*
* The following terms are used to describe CPUs:
*
* Execution-Unit - a logical unit on which tasks may be scheduled by the OS
* Socket - a physical piece of hardware which houses one or more
* execution units
* - CPU-Descriptor - a Map containing information about a single execution unit
*
* Multi-core and hyper-threaded CPUs are examples of CPUs with multiple
* Execution-Units per Socket. The Operating System and Java will typically
* report each Execution-Unit as a unique CPU. For instance a quad-core box
* will appear to the OS and Java as having four CPUs.
*
* @author mf 2006.09.25
*/
public class ProcessorInfo
extends Base
{
// ---- constructor(s) --------------------------------------------------
/**
* Construct a ProcessorInfo object, and compute information about this
* machine.
*/
public ProcessorInfo()
{
inspectMachine();
}
/**
* Construct a ProcessorInfo object, and compute information about this
* machine.
*
* @param uid Coherence UID to include in each descriptor
*/
public ProcessorInfo(UID uid)
{
m_sUid = uid.toString();
inspectMachine();
}
/**
* Construct a ProcessorInfo object, and compute information about the
* machine specified in the supplied descriptor array
*
* @param amapCpu the CPU descriptors
*/
public ProcessorInfo(Map[] amapCpu)
{
loadDictionary();
m_amapCpu = amapCpu;
m_cSocket = getSocketCount(amapCpu);
m_cCpu = computeCpuCount(amapCpu.length);
}
// ---- accessors -------------------------------------------------------
/**
* Return an array of Maps describing this machines processors.
*
* @return array of processor maps
*/
public Map[] getDescriptors()
{
return m_amapCpu.clone();
}
/**
* Return the total number of execution units for this machine.
*
* @return unit count
*/
public int getExecutionUnitCount()
{
return getExecutionUnitCount(m_amapCpu);
}
/**
* Return the total number of sockets for this machine.
*
* @return socket count
*/
public int getSocketCount()
{
return m_cSocket;
}
/**
* Return the total number of CPUs for this machine.
*
* @return cpu count
*/
public int getCpuCount()
{
return m_cCpu;
}
// ---- Object methods -------------------------------------------------
/**
* Return a string representation of this machines CPU information.
*
* @return CPU information as a string
*/
public String toString()
{
int cSockets = getSocketCount();
int cUnits = getExecutionUnitCount();
int cCpus = getCpuCount();
StringBuffer sb = new StringBuffer()
.append(toXml())
.append("\n\n\n");
return sb.toString();
}
// ---- helper methods --------------------------------------------------
/**
* Load the processor dictionary.
*/
protected void loadDictionary()
{
SimpleParser sp = new SimpleParser();
ClassLoader cl = Base.class.getClassLoader();
if (cl == null)
{
cl = getContextClassLoader();
}
InputStream in = null;
XmlElement xmlDoc;
try
{
in = cl.getResourceAsStream(DICTIONARY_XML);
if (in == null)
{
throw new Exception(DICTIONARY_XML + " not found");
}
xmlDoc = sp.parseXml(in);
if (!xmlDoc.getName().equals(DICTIONARY))
{
throw new Exception(DICTIONARY_XML + " does not contain "
+ DICTIONARY + " element");
}
}
catch (Exception e)
{
log("Error loading " + DICTIONARY_XML +": " + e);
return;
}
finally
{
if (in != null)
{
try
{
in.close();
}
catch (IOException e) {}
}
}
// load signature
Signature signature;
try
{
in = cl.getResourceAsStream("tangosol.cer");
CertificateFactory factory = CertificateFactory.getInstance("X.509");
Certificate cert = factory.generateCertificate(in);
signature = Signature.getInstance("SHA1withDSA");
signature.initVerify(cert.getPublicKey());
}
catch (Exception e)
{
log("Error during signature preparation: " + e);
return;
}
finally
{
if (in != null)
{
try
{
in.close();
}
catch (IOException e) {}
}
}
List listTemplates = new ArrayList();
for (Iterator i = xmlDoc.getElements(TEMPLATE); i.hasNext(); )
{
XmlElement xml = (XmlElement) i.next();
HashMap map = new HashMap();
List list = xml.getElementList();
StringBuffer sbConcat = new StringBuffer();
XmlElement xmlExUnits = null;
String sSig = null;
for (ListIterator j = list.listIterator(); j.hasNext(); )
{
XmlElement xmlSub = (XmlElement) j.next();
String sName = xmlSub.getName();
String sValue = xmlSub.getString();
if (sName.equals(SIGNATURE))
{
sSig = sValue;
continue;
}
sbConcat.append(xmlSub);
if (sName.equals(EXECUTION_UNITS))
{
xmlExUnits = xmlSub;
}
if (xmlSub.getSafeAttribute("regex").getBoolean())
{
Pattern pat = Pattern.compile(sValue);
map.put(sName, pat);
}
else
{
map.put(sName, sValue);
}
}
if (sSig != null && xmlExUnits != null)
{
try
{
ByteArrayOutputStream streamRaw = new ByteArrayOutputStream();
DataOutputStream streamSig = new DataOutputStream(streamRaw);
streamSig.writeUTF(sbConcat.toString());
signature.update(streamRaw.toByteArray());
if (signature.verify(Base.parseHex(sSig)))
{
// valid signature, add the template
listTemplates.add(map);
// check for threads attribute
int cThreads = xmlExUnits.getSafeAttribute("thread-count").getInt(0);
int cExUnits = xmlExUnits.getInt(0);
if (cThreads > 0)
{
// add additional definition for when threading is disabled
// this will only be used if we detect that there aren't
// enough logical cores during matching
Map mapClone = (Map) map.clone();
mapClone.put(EXECUTION_UNITS, Integer.toString(cExUnits - cThreads));
listTemplates.add(mapClone);
}
}
else
{
log("Skipping processor template with invalid signature:\n" + xml);
}
}
catch (Exception e)
{
// error validating, skip it
if (m_fVerbose)
{
log("Error while validating template:\n" + xml);
log(e);
}
}
}
}
m_amapCpuTemplate = (Map[]) listTemplates.toArray(
new Map[listTemplates.size()]);
}
/**
* Retrieve the value for a environment variable.
*
* @param sEnvName the variable name
*
* @return the env variable name or null if it is unset
*/
protected String getEnv(String sEnvName)
{
if (m_mapEnv == null)
{
try
{
return System.getenv(sEnvName);
}
catch (Throwable e)
{
// System.getenv isn't supported, avoid future use
if (m_fVerbose)
{
log("getEnv unavailable: " + e);
log(e);
}
}
// try to read environment by launching a shell
try
{
Runtime rt = Runtime.getRuntime();
String[] asCmd;
if (System.getProperty("os.name").indexOf("Windows") == -1)
{
// Unix
asCmd = new String[] {"sh", "-c", "set"};
}
else
{
// Windows
asCmd = new String[] {"cmd", "/c", "set"};
}
Process proc = rt.exec(asCmd);
InputStream in = proc.getInputStream();
LineNumberReader reader = new LineNumberReader(new InputStreamReader(in));
Map mapEnv = new HashMap();
for (String sLine = reader.readLine(); sLine != null; sLine = reader.readLine())
{
// split at = sign
int ofEq = sLine.indexOf('=');
if (ofEq > 0 && ofEq + 1 < sLine.length())
{
String sName = sLine.substring(0, ofEq).trim();
String sValue = sLine.substring(ofEq + 1).trim();
mapEnv.put(sName.toUpperCase(), sValue);
}
}
// save for future use
m_mapEnv = mapEnv;
}
catch (Exception e)
{
// we have no way to get env variables, try system properties
if (m_fVerbose)
{
log("Environment variables unavailable: " + e);
log(e);
}
try
{
m_mapEnv = System.getProperties();
}
catch (Exception e2)
{
if (m_fVerbose)
{
log("System property map unavailable: " + e);
log(e);
}
return System.getProperty(sEnvName.toUpperCase());
}
}
}
return (String) m_mapEnv.get(sEnvName.toUpperCase());
}
/**
* Return an array of processor descriptions for the current machine,
* based on information Windows specific information.
*
* @return array of processor descriptions
*/
protected Map[] inspectWindows()
{
// Windows XP includes a number of useful environment variables;
// for example:
// Results for single CPU Intel
// PROCESSOR_ARCHITECTURE=x86
// PROCESSOR_IDENTIFIER=x86 Family 6 Model 13 Stepping 8, GenuineIntel
// PROCESSOR_LEVEL=6
// PROCESSOR_REVISION=0d08
// NUMBER_OF_PROCESSORS=1
// Results for dual CPU AMD
// PROCESSOR_ARCHITECTURE=x86
// PROCESSOR_IDENTIFIER=x86 Family 15 Model 5 Stepping 1, AuthenticAMD
// PROCESSOR_LEVEL=15
// PROCESSOR_REVISION=0501
// NUMBER_OF_PROCESSORS=2
// NOTE: LEVEL == FAMILY, REVISION ~ Stepping
// likely that NUMBER_OF_PROCESSORS == cores
// TODO: check Win2K, Win2003, Vista
Map mapInfo = new HashMap();
mapInfo.put(ENVIRONMENT, "Windows");
mapInfo.put(ARCHITECTURE, getEnv("PROCESSOR_ARCHITECTURE"));
if (m_sUid != null)
{
mapInfo.put(COHERENCE_UID, m_sUid);
}
// parse proc id to get additional info
String sId = getEnv("PROCESSOR_IDENTIFIER");
mapInfo.put(DESCRIPTION, sId);
// get Family, Model, Stepping, and Vendor
String[] sTok = sId.split(" |,");
int cTokens = sTok.length;
mapInfo.put(VENDOR, sTok[cTokens - 1]);
for (int i = 0; i < cTokens; ++i)
{
if (sTok[i].equals("Family") && i + 1 < cTokens)
{
mapInfo.put(FAMILY, sTok[++i]);
}
else if (sTok[i].equals("Model") && i + 1 < cTokens)
{
mapInfo.put(MODEL, sTok[++i]);
}
else if (sTok[i].equals("Stepping") && i + 1 < cTokens)
{
mapInfo.put(STEPPING, sTok[++i]);
}
}
// treat each processor the same
mapInfo = Collections.unmodifiableMap(mapInfo);
Map[] amapCpu = new Map[Runtime.getRuntime().availableProcessors()];
Arrays.fill(amapCpu, mapInfo);
return amapCpu;
}
/**
* Return an array of processor descriptions for the current machine,
* based on information Linux specific information.
*
* @return array of processor descriptions
*/
protected Map[] inspectLinux()
throws Exception
{
// look at contents of /proc/cpuinfo
FileInputStream in = new FileInputStream("/proc/cpuinfo");
LineNumberReader reader = new LineNumberReader(new InputStreamReader(in));
// file format is id : value
// there is one info block per processor, each has a "processor"
// element at the start
String sArch = System.getProperty("os.arch");
List listInfo = new ArrayList();
Map mapInfo = null;
for (String sLine = reader.readLine(); sLine != null; sLine = reader.readLine())
{
int iColon = sLine.indexOf(':');
if (iColon > 0 && iColon + 1 < sLine.length())
{
String sName = sLine.substring(0, iColon).trim();
String sValue = sLine.substring(iColon + 1).trim();
if (sName.equals("processor"))
{
// new processor
if (mapInfo != null)
{
listInfo.add(Collections.unmodifiableMap(mapInfo));
}
mapInfo = new HashMap();
mapInfo.put(ENVIRONMENT, "Linux");
mapInfo.put(ARCHITECTURE, sArch);
if (m_sUid != null)
{
mapInfo.put(COHERENCE_UID, m_sUid);
}
}
else if (sName.equals("vendor_id"))
{
mapInfo.put(VENDOR, sValue);
}
else if (sName.equals("cpu family"))
{
mapInfo.put(FAMILY, sValue);
}
else if (sName.equals("model"))
{
mapInfo.put(MODEL, sValue);
}
else if (sName.equals("stepping"))
{
mapInfo.put(STEPPING, sValue);
}
else if (sName.equals("cpu cores"))
{
// Sometimes Linux identifies cores/cpu
mapInfo.put(EXECUTION_UNITS, sValue);
}
else
{
// include other info, this will be useful
// for generating new templates especially
// for non x86 processors
sName = sName.replace(' ', '-');
mapInfo.put(sName, sValue);
}
}
}
in.close();
if (mapInfo != null)
{
listInfo.add(Collections.unmodifiableMap(mapInfo));
}
return (Map[]) listInfo.toArray(new Map[listInfo.size()]);
}
/**
* Return an array of processor descriptions for the current machine
* based solely on information available from the JVM.
*
* @return array of processor descriptions
*/
protected Map[] inspectJava()
{
// Use System properties
Map mapInfo = new HashMap();
mapInfo.put(ENVIRONMENT, System.getProperty("os.name"));
mapInfo.put(ARCHITECTURE, System.getProperty("os.arch"));
if (m_sUid != null)
{
mapInfo.put(COHERENCE_UID, m_sUid);
}
// treat each processor the same
mapInfo = Collections.unmodifiableMap(mapInfo);
Map[] amapCpu = new Map[Runtime.getRuntime().availableProcessors()];
Arrays.fill(amapCpu, mapInfo);
return amapCpu;
}
/**
* Inspect this machine and determine its CPU descriptors.
*/
public void inspectMachine()
{
try
{
loadDictionary();
// start by identifying the OS we are on
Map[] amapCpu = null;
try
{
String sOs = System.getProperty("os.name");
if (sOs.indexOf("Windows") != -1)
{
amapCpu = inspectWindows();
}
else if (sOs.indexOf("Linux") != -1)
{
amapCpu = inspectLinux();
}
// TODO: Solaris, SunOs "/usr/sbin/psrinfo -vp" or "/usr/sbin/psrinfo -v"
// see http://solaris.reys.net/english/2006/07/t2000_first_impressions for
// info on psrinfo example formatting
// TODO: AIX "lsdev -Cc processor"
// See http://www.unixguide.net/unixguide.shtml for details on
// calculating CPU info for various UNIXs
}
catch (Throwable e)
{
// error reading OS specific CPU information
// eat the exception and use pure Java info
if (m_fVerbose)
{
log("Error in OS specific analysis falling back on pure Java approach: " + e);
log(e);
}
}
if (amapCpu == null || amapCpu.length == 0)
{
amapCpu = inspectJava();
}
// allow for socket count to be increased for license testing
int cCfgSocket = Config.getInteger("coherence.socket", 1);
int cCfgCpu = Config.getInteger("coherence.cpu", 1);
m_amapCpu = amapCpu;
m_cSocket = Math.max(cCfgSocket, getSocketCount(amapCpu));
m_cCpu = Math.max(cCfgCpu, computeCpuCount(Runtime.getRuntime().
availableProcessors()));
}
catch (Throwable t)
{
// ensure that we always succeed
log("unable to identify processor info");
log(t);
m_cSocket = m_cCpu = Runtime.getRuntime().availableProcessors();
}
}
/**
* Return the CPU descriptors as an XmlElement
*
* @return XML representation
*/
public XmlElement toXml()
{
Map[] amapCpu = m_amapCpu;
XmlElement xmlRoot = new SimpleElement(MACHINE);
List listXml = xmlRoot.getElementList();
for (int i = 0, c = amapCpu.length; i < c; ++i)
{
listXml.add(toXml(DESCRIPTOR, amapCpu[i]));
}
return xmlRoot;
}
/**
* Return a Map as an XmlElement
*
* @param sParent the parent element name
* @param map the map to translate
*
* @return XML representation
*/
public static XmlElement toXml(String sParent, Map map)
{
XmlElement xml = new SimpleElement(sParent);
for (Iterator j = map.entrySet().iterator(); j.hasNext(); )
{
Map.Entry entry = (Map.Entry) j.next();
Object oKey = entry.getKey();
Object oValue = entry.getValue();
if (oKey != null && oValue != null)
{
xml.addElement(oKey.toString()).
setString(oValue.toString());
}
}
return xml;
}
/**
* Return a set of CPU descriptors from an XmlElement
*
* @return the descriptor represented as a Map
*/
public static Map[] fromXml(XmlElement xmlDoc)
{
if (xmlDoc == null)
{
return null;
}
List listMaps = new ArrayList();
for (Iterator i = xmlDoc.getElements(DESCRIPTOR); i.hasNext(); )
{
XmlElement xml = (XmlElement) i.next();
Map map = new HashMap();
List list = xml.getElementList();
for (ListIterator j = list.listIterator(); j.hasNext(); )
{
XmlElement xmlSub = (XmlElement) j.next();
map.put(xmlSub.getName(), xmlSub.getValue());
}
listMaps.add(map);
}
return (Map[]) listMaps.toArray(new Map[listMaps.size()]);
}
/**
* Count the number of sockets based on the supplied processor maps.
*
* @param amapCpu the array of processor descriptors
*
* @return socket count
*/
public int getSocketCount(Map[] amapCpu)
{
if (amapCpu == null)
{
return 1;
}
retry:
while (true)
{
try
{
int cCpus = amapCpu.length;
int[] acUnits = new int[cCpus];
// lookup core count for each CPU
for (int i = 0; i < cCpus; ++i)
{
acUnits[i] = lookupExecutionUnits(amapCpu[i]);
}
// account for clones; a clone is a "duplicate" CPU descriptor;
// an n execution-unit processor will have n-1 clones
int cSocket = 0;
for (int i = 0; i < cCpus; ++i)
{
int cUnits = acUnits[i];
if (cUnits > 0)
{
++cSocket;
// search for clones, to keep things simple a clone is any other
// cpu with the same core count. Note: we could look for a more
// exact clone, i.e. same vendor, family, model, but this would
// be architecture specific, and really wouldn't help much
int cClones = cUnits - 1; // there should be n-1 clones
for (int j = i + 1; j < cCpus && cClones > 0; ++j)
{
if (acUnits[j] == cUnits)
{
// a clone found
acUnits[j] = 0;
--cClones;
}
}
if (cClones > 0)
{
// not all clones were found; this is most often
// caused by multi-core chips which support
// multi-threading but have it disabled. Thus
// the definition may be incorrect for this machine
// remove it and retry, note this assumes that
// there will be a fall-back less specific definition
// which will still properly detect the multiple
// cores
if (m_fVerbose)
{
log("Missing " + cClones + " siblings for "
+ toXml(DESCRIPTOR, amapCpu[i]));
}
if (removeDefinition(amapCpu[i]))
{
if (m_fVerbose)
{
log("Definition dropped, rechecking");
}
// definition was removed, recheck
continue retry;
}
else
{
// fall back on "socket == cpu"
log("Unable to resolve " + cClones + " siblings for "
+ toXml(DESCRIPTOR, amapCpu[i]));
return Math.max(cCpus, 1);
}
}
}
}
return Math.max(cSocket, 1);
}
catch (Throwable e)
{
if (m_fVerbose)
{
log("Error in matching CPUs: " + e);
log(e);
}
return Math.max(amapCpu.length, 1);
}
}
}
/**
* compute the total number of cores for this machine.
*
* @param cCores the core count
*
* @return core count
*/
protected int computeCpuCount(int cCores)
{
try
{
// compensate for hyper-threading (aka Symmetrical Multi Threading)
// which doubles the number of CPUs for Intel processors
// Note: this system property is not intended for use in socket counting
if (cCores % 2 == 0 && Config.getBoolean("coherence.smt.enabled"))
{
return Math.max((cCores >>> 1), 1);
}
else
{
// Note: this system property is not intended for use in socket counting
String sFactor = Config.getProperty("coherence.smt.factor");
if (sFactor != null)
{
int nFactor = Integer.parseInt(sFactor);
if (cCores % nFactor == 0)
{
return Math.max((cCores / nFactor), 1);
}
}
}
}
catch (Throwable e)
{
if (m_fVerbose)
{
log("Error in counting physical cores: " + e);
log(e);
}
}
// fall back on CPU == core
return Math.max(cCores, 1);
}
/**
* Lookup a CPU from the dictionary based on the supplied descriptor.
*
* @param mapCpu the CPU to lookup
*
* @return the best match from the dictionary, or null if none is found
*/
public Map lookupCpu(Map mapCpu)
{
Map[] amapTemplate = m_amapCpuTemplate;
if (amapTemplate == null)
{
return null;
}
if (m_fVerbose)
{
log("Searching for matching template for CPU:\n"
+ toXml(DESCRIPTOR, mapCpu));
}
// scan through templates and find the closest match
Map mapMatch = null;
nextTemplate:
for (int i = 0, c = amapTemplate.length, cMatchSize = 0; i < c; ++i)
{
Map mapTemplate = amapTemplate[i];
// each piece of the template (other then EXECUTION_UNITS) must be
// in this descriptor
if (mapTemplate != null &&
mapTemplate.size() > cMatchSize)
{
for (Iterator iter = mapTemplate.entrySet().iterator();
iter.hasNext(); )
{
Map.Entry entry = (Map.Entry) iter.next();
Object oKey = entry.getKey();
Object oValue = entry.getValue();
if (oKey.equals(EXECUTION_UNITS))
{
// match of this element is not required
continue;
}
String sDescriptorValue = (String) mapCpu.get(oKey);
boolean fMatch =
sDescriptorValue != null &&
(oValue instanceof String &&
oValue.equals(sDescriptorValue)
|| oValue instanceof Pattern &&
((Pattern) oValue).matcher(sDescriptorValue).matches());
if (!fMatch)
{
// no match, move to the next template
continue nextTemplate;
}
}
// this template is the best match so far
if (m_fVerbose)
{
if (mapMatch == null)
{
log("Found matching template\n"
+ toXml(TEMPLATE, mapTemplate));
}
else
{
// better match
log("Found better match\n"
+ toXml(TEMPLATE, mapTemplate));
}
}
cMatchSize = mapTemplate.size();
mapMatch = mapTemplate;
}
}
if (mapMatch == null && m_fVerbose)
{
log("No matching template found");
}
return mapMatch;
}
/**
* Count the number of execution units based on the supplied processor map.
*
* @param mapCpu the processor specs to use in computing core count
*
* @return unit count
*/
public int lookupExecutionUnits(Map mapCpu)
{
if (mapCpu == null)
{
return 0;
}
// check if descriptor was able to compute the core count
String sUnits = m_fForceLookup ? null : (String) mapCpu.get(EXECUTION_UNITS);
if (sUnits == null)
{
Map mapMatch = lookupCpu(mapCpu);
if (mapMatch != null)
{
sUnits = (String) mapMatch.get(EXECUTION_UNITS);
}
}
else if (m_fVerbose)
{
log("Using descriptor supplied execution units of " + sUnits);
}
// if we didn't find a matching print, fall back on 1:1 assumption
return sUnits == null ? 1 : Integer.parseInt(sUnits);
}
/**
* Remove the definition for this CPU from the dictionary.
*
* This is used in the event that the dictionary match and the inspected
* CPUs do not align. For instance when inspecting processors which
* support both multi-core and hyper-threading.
*
* @param mapCpu the CPU for which to remove the associated definition
*
* @return true iff a definition was removed
*/
public boolean removeDefinition(Map mapCpu)
{
Map[] amapTemplate = m_amapCpuTemplate;
Map mapMatch = lookupCpu(mapCpu);
if (mapMatch != null)
{
// null out this ref from dictionary
for (int i = 0, c = amapTemplate.length; i < c; ++i)
{
if (amapTemplate[i] == mapMatch)
{
amapTemplate[i] = null;
return true;
}
}
}
return false;
}
/**
* Count the number of execution units based on the supplied processor maps.
*
* @param amapCpu the array of processor descriptors
*
* @return unit count
*/
public int getExecutionUnitCount(Map[] amapCpu)
{
// assume that reported CPU count is really core count
return amapCpu == null ? 0 : amapCpu.length;
}
/**
* Log an issue related to processor identification.
*
* @param sMsg the message to log
*/
public static void log(String sMsg)
{
// all issues are logged at a rather high debug level as we'll always
// fallback on assuming that the number of sockets is equal to the
// JVMs CPU count.
CacheFactory.log(sMsg, 7);
}
/**
* Log an exception related to processor identification.
*
* @param t the exception
*/
public static void log(Throwable t)
{
log(printStackTrace(t));
}
/**
* Report info for the available processors.
*
* @param asArg [fingerprint]
*/
public static void main(String[] asArg)
{
if (asArg.length > 0)
{
// output the fingerprint (and analyse) the CPUs from the
// fingerprint in the supplied file
try
{
FileInputStream in = new FileInputStream(asArg[0]);
SimpleParser sp = new SimpleParser();
System.out.println(new ProcessorInfo(fromXml(sp.parseXml(in))));
}
catch (IOException e)
{
log("Error reading " + asArg[0] + ": " + e);
}
}
else
{
// output fingerprint for this machine
System.out.println(new ProcessorInfo());
}
}
// ---- data members ----------------------------------------------------
/**
* Optional Customer UID.
*/
protected String m_sUid;
/**
* Map containing environment variables, keys are stored in upper case.
* The presence of this Map indicates that System.getenv is unusable.
*/
protected Map m_mapEnv;
/**
* Array of Maps describing the machine's processors.
*/
protected Map[] m_amapCpu;
/**
* The computed socket count.
*/
protected int m_cSocket;
/**
* The computed CPU count.
*/
protected int m_cCpu;
/**
* Array of known CPU fingerprints.
*/
protected Map[] m_amapCpuTemplate;
/**
* If true a template lookup is forced even when the fingerprint appears
* to contain sufficient information to avoid it.
*/
protected boolean m_fForceLookup = Config.getBoolean("coherence.cpu.forcelookup");
/**
* If true include verbose logging relating to CPU analysis.
*/
protected boolean m_fVerbose = Config.getBoolean("coherence.cpu.verbose");
// ----- constants ------------------------------------------------------
// general identifiers
public static final String ENVIRONMENT = "environment";
public static final String DESCRIPTION = "description";
public static final String ARCHITECTURE = "architecture";
public static final String VENDOR = "vendor";
public static final String COHERENCE_UID = "coherence-uid";
// x86 identifiers
public static final String FAMILY = "family";
public static final String MODEL = "model";
public static final String STEPPING = "stepping";
public static final String EXECUTION_UNITS = "execution-units";
// Xml
public static final String DICTIONARY_XML = "processor-dictionary.xml";
public static final String MACHINE = "machine";
public static final String DICTIONARY = "processor-dictionary";
public static final String DESCRIPTOR = "processor-descriptor";
public static final String TEMPLATE = "processor-template";
public static final String SIGNATURE = "signature";
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy