/* * Copyright 2012 dominictootell * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.greencheek.processio.service.io; import org.greencheek.processio.domain.CurrentProcessIO; import org.greencheek.processio.service.io.ProcessIOReader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.*; import java.nio.charset.Charset; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Reads the /proc/PID/io file system for the given pid. It reads the values for the read_bytes and write_bytes * from the file. On a redhat system the contents of the /proc/PID/io look like the following: * <pre> rchar: 49820184 wchar: 79916 syscr: 142929 syscw: 265 read_bytes: 18790563840 write_bytes: 2250752000 cancelled_write_bytes: 16384 * </pre> * This class would return from {@link #getCurrentProcessIO()} a {@link CurrentProcessIO} object that holds the values * 18790563840 for {@link org.greencheek.processio.domain.CurrentProcessIO#getCurrentReadBytes()}, and * 2250752000 for {@link org.greencheek.processio.domain.CurrentProcessIO#getCurrentWriteBytes()}. The * {@link org.greencheek.processio.domain.CurrentProcessIO#getCurrentSampleTimeInMillis()} is the time after which those * tow values are read, the CurrentProcessIO object created * * <p> * User: dominictootell * Date: 22/04/2012 * Time: 17:46 * </p> */ public class FileSystemProcIOProcessIOReader implements ProcessIOReader { private static final Logger log = LoggerFactory.getLogger(FileSystemProcIOProcessIOReader.class); private static final String PROC_IO_LOCATION = "/proc/%d/io"; private static final Pattern READ_BYTES_PATTERN = Pattern.compile("^\\s*read_bytes\\s*:\\s*(\\d+)[^\\d]*$"); private static final Pattern WRITE_BYTES_PATTERN = Pattern.compile("^\\s*write_bytes\\s*:\\s*(\\d+)[^\\d]*$"); private final File procIOLocation; public FileSystemProcIOProcessIOReader(File location) { procIOLocation = new File(location.getAbsolutePath()); } public FileSystemProcIOProcessIOReader(int pid) { this(new File(String.format(PROC_IO_LOCATION,pid))); } /** * Reads the read_bytes and write_bytes from the current process io /proc file. * If the /proc/PID/io file is not readable then it returns * {@value org.greencheek.processio.service.io.ProcessIOReader#NON_READABLE_PROCESS_IO} * * @return The current io of the jvm process */ @Override public CurrentProcessIO getCurrentProcessIO() { if(!procIOLocation.canRead()) { log.warn("Unable to read process io location: {}",procIOLocation.getAbsolutePath()); return NON_READABLE_PROCESS_IO; } FileInputStream fis = null; try { fis = new FileInputStream(procIOLocation); } catch (FileNotFoundException e) { log.warn("Not found process io location: {}",procIOLocation.getAbsolutePath()); return NON_READABLE_PROCESS_IO; } InputStreamReader is = null; BufferedReader br = null; Long readBytes = null; Long writeBytes = null; try { is = new InputStreamReader(fis, Charset.forName("UTF-8")); br = new BufferedReader(is); String strLine; //Read File Line By Line while ((strLine = br.readLine()) != null) { // Print the content on the console Matcher readMatcher = READ_BYTES_PATTERN.matcher(strLine); Matcher writeMatcher = WRITE_BYTES_PATTERN.matcher(strLine); if(readMatcher.matches()) { try { readBytes = Long.parseLong(readMatcher.group(1)); } catch (NumberFormatException e) {} } if(writeMatcher.matches()) { try { writeBytes = Long.parseLong(writeMatcher.group(1)); } catch (NumberFormatException e) {} } } } catch (IOException e) { log.warn("Unable to read process io location: {}",procIOLocation.getAbsolutePath()); return NON_READABLE_PROCESS_IO; } finally { if(br!=null) { try { br.close(); } catch (IOException e) { } } } if(readBytes==null || writeBytes==null) { log.warn("Unable read with the read_bytes or write_bytes from io location: {}",procIOLocation.getAbsolutePath()); return NON_READABLE_PROCESS_IO; } else { return new CurrentProcessIO(System.currentTimeMillis(),readBytes,writeBytes); } } }