/*
 * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.jvmstat.perfdata.monitor.protocol.local;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.io.FilenameFilter;
import sun.jvmstat.PlatformSupport;

Class to provide translations from the local Vm Identifier name space into the file system name space and vice-versa.

Provides a factory for creating a File object to the backing store file for instrumentation shared memory region for a JVM identified by its Local Java Virtual Machine Identifier, or lvmid.

Author:Brian Doherty
See Also:
Since:1.5
/** * Class to provide translations from the local Vm Identifier * name space into the file system name space and vice-versa. * <p> * Provides a factory for creating a File object to the backing * store file for instrumentation shared memory region for a JVM * identified by its Local Java Virtual Machine Identifier, or * <em>lvmid</em>. * * @author Brian Doherty * @since 1.5 * @see java.io.File */
public class PerfDataFile { private PerfDataFile() { };
The file name prefix for PerfData shared memory files.

This prefix must be kept in sync with the prefix used by the JVM.

/** * The file name prefix for PerfData shared memory files. * <p> * This prefix must be kept in sync with the prefix used by the JVM. */
public static final String dirNamePrefix = "hsperfdata_";
The directory name pattern for the user directories.
/** * The directory name pattern for the user directories. */
public static final String userDirNamePattern = "hsperfdata_\\S*";
The file name pattern for PerfData shared memory files.

This pattern must be kept in synch with the file name pattern used by the 1.4.2 and later HotSpot JVM.

/** * The file name pattern for PerfData shared memory files. * <p> * This pattern must be kept in synch with the file name pattern * used by the 1.4.2 and later HotSpot JVM. */
public static final String fileNamePattern = "^[0-9]+$";
The file name pattern for 1.4.1 PerfData shared memory files.

This pattern must be kept in synch with the file name pattern used by the 1.4.1 HotSpot JVM.

/** * The file name pattern for 1.4.1 PerfData shared memory files. * <p> * This pattern must be kept in synch with the file name pattern * used by the 1.4.1 HotSpot JVM. */
public static final String tmpFileNamePattern = "^hsperfdata_[0-9]+(_[1-2]+)?$";
Platform Specific methods for looking up temporary directories and process IDs.
/** * Platform Specific methods for looking up temporary directories * and process IDs. */
private static final PlatformSupport platSupport = PlatformSupport.getInstance();
Get a File object for the instrumentation backing store file for the JVM identified by the given local Vm Identifier.

This method looks for the most up to date backing store file for the given lvmid. It will search all the user specific directories in the temporary directory for the host operating system, which may be influenced by platform specific environment variables.

Params:
  • lvmid – the local Java Virtual Machine Identifier for the target
See Also:
Returns:File - a File object to the backing store file for the named shared memory region of the target JVM.
/** * Get a File object for the instrumentation backing store file * for the JVM identified by the given local Vm Identifier. * <p> * This method looks for the most up to date backing store file for * the given {@code lvmid}. It will search all the user specific * directories in the temporary directory for the host operating * system, which may be influenced by platform specific environment * variables. * * @param lvmid the local Java Virtual Machine Identifier for the target * @return File - a File object to the backing store file for the named * shared memory region of the target JVM. * @see java.io.File * @see #getTempDirectories() */
public static File getFile(int lvmid) { if (lvmid == 0) { /* * lvmid == 0 is used to indicate the current Java Virtual Machine. * If the SDK provided an API to get a unique Java Virtual Machine * identifier, then a filename could be constructed with that * identifier. In absence of such an api, return null. */ return null; } List<String> tmpDirs = getTempDirectories(null, lvmid); File newest = null; for (String dir : tmpDirs) { /* * iterate over all files in all directories in this tmpDir that * match the file name patterns. */ File tmpDir = new File(dir); String[] files = tmpDir.list(new FilenameFilter() { public boolean accept(File dir, String name) { if (!name.startsWith(dirNamePrefix)) { return false; } File candidate = new File(dir, name); return ((candidate.isDirectory() || candidate.isFile()) && candidate.canRead()); } }); long newestTime = 0; for (String file : files) { File f = new File(dir + file); File candidate = null; if (f.exists() && f.isDirectory()) { /* * found a directory matching the name patterns. This * is a 1.4.2 hsperfdata_<user> directory. Check for * file named <lvmid> in that directory */ String name = f.getAbsolutePath() + File.separator + lvmid; candidate = new File(name); // Try NameSpace Id if Host Id doesn't exist. if (!candidate.exists()) { name = f.getAbsolutePath() + File.separator + platSupport.getNamespaceVmId(lvmid); candidate = new File(name); } } else if (f.exists() && f.isFile()) { /* * found a file matching the name patterns. This * is a 1.4.1 hsperfdata_<lvmid> file. */ candidate = f; } else { // unexpected - let conditional below filter this one out candidate = f; } if (candidate.exists() && candidate.isFile() && candidate.canRead()) { long modTime = candidate.lastModified(); if (modTime >= newestTime) { newestTime = modTime; newest = candidate; } } } } return newest; }
Return the File object for the backing store file for the specified Java Virtual Machine.

This method looks for the most up to date backing store file for the JVM identified by the given user name and lvmid. The directory searched is the temporary directory for the host operating system, which may be influenced by environment variables.

Params:
  • user – the user name
  • lvmid – the local Java Virtual Machine Identifier for the target
See Also:
Returns:File - a File object to the backing store file for the named shared memory region of the target JVM.
/** * Return the File object for the backing store file for the specified Java * Virtual Machine. * <p> * This method looks for the most up to date backing store file for * the JVM identified by the given user name and lvmid. The directory * searched is the temporary directory for the host operating system, * which may be influenced by environment variables. * * @param user the user name * @param lvmid the local Java Virtual Machine Identifier for the target * @return File - a File object to the backing store file for the named * shared memory region of the target JVM. * @see java.io.File * @see #getTempDirectories() */
public static File getFile(String user, int lvmid) { if (lvmid == 0) { /* * lvmid == 0 is used to indicate the current Java Virtual Machine. * If the SDK provided an API to get a unique Java Virtual Machine * identifier, then a filename could be constructed with that * identifier. In absence of such an api, return null. */ return null; } // first try for 1.4.2 and later JVMs List<String> tmpDirs = getTempDirectories(user, lvmid); String basename; File f; for (String dir : tmpDirs) { basename = dir + lvmid; f = new File(basename); if (f.exists() && f.isFile() && f.canRead()) { return f; } // Try NameSpace Id if Host Id doesn't exist. basename = dir + platSupport.getNamespaceVmId(lvmid); f = new File(basename); if (f.exists() && f.isFile() && f.canRead()) { return f; } } // No hit on 1.4.2 JVMs, try 1.4.1 files long newestTime = 0; File newest = null; for (int i = 0; i < 2; i++) { if (i == 0) { basename = getTempDirectory() + Integer.toString(lvmid); } else { basename = getTempDirectory() + Integer.toString(lvmid) + Integer.toString(i); } f = new File(basename); if (f.exists() && f.isFile() && f.canRead()) { long modTime = f.lastModified(); if (modTime >= newestTime) { newestTime = modTime; newest = f; } } } return newest; }
Method to extract a local Java Virtual Machine Identifier from the file name of the given File object.
Params:
  • file – A File object representing the name of a shared memory region for a target JVM
Throws:
Returns:int - the local Java Virtual Machine Identifier for the target associated with the file
/** * Method to extract a local Java Virtual Machine Identifier from the * file name of the given File object. * * @param file A File object representing the name of a * shared memory region for a target JVM * @return int - the local Java Virtual Machine Identifier for the target * associated with the file * @throws java.lang.IllegalArgumentException Thrown if the file name * does not conform to the expected pattern */
public static int getLocalVmId(File file) { try { // try 1.4.2 and later format first return(platSupport.getLocalVmId(file)); } catch (NumberFormatException e) { } // now try the 1.4.1 format String name = file.getName(); if (name.startsWith(dirNamePrefix)) { int first = name.indexOf('_'); int last = name.lastIndexOf('_'); try { if (first == last) { return Integer.parseInt(name.substring(first + 1)); } else { return Integer.parseInt(name.substring(first + 1, last)); } } catch (NumberFormatException e) { } } throw new IllegalArgumentException("file name does not match pattern"); }
Return the name of the temporary directory being searched for HotSpot PerfData backing store files.

This method generally returns the value of the java.io.tmpdir property. However, on some platforms it may return a different directory, as the JVM implementation may store the PerfData backing store files in a different directory for performance reasons.

Returns:String - the name of the temporary directory.
/** * Return the name of the temporary directory being searched for * HotSpot PerfData backing store files. * <p> * This method generally returns the value of the java.io.tmpdir * property. However, on some platforms it may return a different * directory, as the JVM implementation may store the PerfData backing * store files in a different directory for performance reasons. * * @return String - the name of the temporary directory. */
public static String getTempDirectory() { return PlatformSupport.getTemporaryDirectory(); }
Return the name of the temporary directory to be searched for HotSpot PerfData backing store files for a given user.

This method generally returns the name of a subdirectory of the directory indicated in the java.io.tmpdir property. However, on some platforms it may return a different directory, as the JVM implementation may store the PerfData backing store files in a different directory for performance reasons.

Returns:String - the name of the temporary directory.
/** * Return the name of the temporary directory to be searched * for HotSpot PerfData backing store files for a given user. * <p> * This method generally returns the name of a subdirectory of * the directory indicated in the java.io.tmpdir property. However, * on some platforms it may return a different directory, as the * JVM implementation may store the PerfData backing store files * in a different directory for performance reasons. * * @return String - the name of the temporary directory. */
public static String getTempDirectory(String user) { return getTempDirectory() + dirNamePrefix + user + File.separator; }
Return the names of the temporary directories being searched for HotSpot PerfData backing store files.

This method returns the traditional host temp directory but also includes a list of temp directories used by containers.

Returns:List - A List of temporary directories to search.
/** * Return the names of the temporary directories being searched for * HotSpot PerfData backing store files. * <p> * This method returns the traditional host temp directory but also * includes a list of temp directories used by containers. * * @return List<String> - A List of temporary directories to search. */
public static List<String> getTempDirectories(String userName, int vmid) { List<String> list = platSupport.getTemporaryDirectories(vmid); if (userName == null) { return list; } List<String> nameList = list.stream() .map(name -> name + dirNamePrefix + userName + File.separator) .collect(Collectors.toList()); return nameList; } }