package org.ourgrid.worker.business.requester; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.StringTokenizer; import org.ourgrid.common.internal.IResponseTO; import org.ourgrid.common.internal.response.LoggerResponseTO; import org.ourgrid.worker.WorkerConstants; import org.ourgrid.worker.business.controller.IdlenessDetectorController; import org.ourgrid.worker.business.dao.IdlenessDetectorDAO; import org.ourgrid.worker.business.dao.WorkerDAOFactory; import org.ourgrid.worker.request.LinuxIdlenessDetectorActionRequestTO; import com.sun.jna.Library; import com.sun.jna.Native; public class LinuxNativeIdlenessDetectorActionRequester extends AbstractScheduledIdlenessDetectorActionRequester<LinuxIdlenessDetectorActionRequestTO> { private LinkedList<String[ ]> currentStatus = new LinkedList<String[ ]>(); private LinkedList<String[ ]> oldStatus = new LinkedList<String[ ]>(); public List<IResponseTO> execute(LinuxIdlenessDetectorActionRequestTO request) { List<IResponseTO> responses = new ArrayList<IResponseTO>(); // if (isIdle(responses, request.getXIdleTimeLibPath())) { // IdlenessDetectorController.getInstance().resumeWorker(responses); // } else { // IdlenessDetectorController.getInstance().pauseWorker(responses); // } return responses; } private interface XIdleTime extends Library { public long getIdleTime(); } private boolean isIdle(List<IResponseTO> responses, String xIdleTimeLibPath) { IdlenessDetectorDAO idlenessDetectorDAO = WorkerDAOFactory.getInstance().getIdlenessDetectorDAO(); boolean idle = super.isIdle(); if (!idlenessDetectorDAO.isActive()) { return idle; } try { //make sure that xIdleTimeLibPath is an absolute path File libXIdleTimeFile = new File(xIdleTimeLibPath); if (!libXIdleTimeFile.isAbsolute()) { xIdleTimeLibPath = libXIdleTimeFile.getAbsolutePath(); } XIdleTime xIdleTime = (XIdleTime) Native.loadLibrary(xIdleTimeLibPath, XIdleTime.class); long idleTime = xIdleTime.getIdleTime(); if (idleTime > -1) { return idle && (idleTime >= idlenessDetectorDAO.getIdlenessTime()); } } catch ( Exception e ) { responses.add(new LoggerResponseTO("Error on load the XIdleTime lib.", LoggerResponseTO.ERROR, e)); } responses.add(new LoggerResponseTO("Wasn't able to use XIdleTime lib idleness" + " detector. Trying the old method.", LoggerResponseTO.DEBUG)); try { if ( !currentStatus.isEmpty() ) { this.oldStatus = currentStatus; } this.currentStatus = new LinkedList<String[ ]>(); this.readInterruptsFile(currentStatus); } catch ( IOException ioe ) { responses.add(new LoggerResponseTO("Error on reading interrupt files.", LoggerResponseTO.ERROR, ioe)); } if ( this.checkIdleness() ) { idlenessDetectorDAO.incrementTime(WorkerConstants.IDLENESSDETECTOR_VERIFICATION_TIME); } else { idlenessDetectorDAO.resetTime(); } return idle && (idlenessDetectorDAO.getTime() >= idlenessDetectorDAO.getIdlenessTime()); } /** * Complets the work of this.isIdle() method. It makes the comparation * itself. * * @return <code>true</code> if the computer is idle and * <code>false</code> otherwise. */ private boolean checkIdleness() { if (this.oldStatus.isEmpty()) { try { readInterruptsFile(oldStatus); } catch (IOException e) { e.printStackTrace(); } return false; } boolean idle = true; Iterator<String[ ]> it = currentStatus.iterator(); while ( it.hasNext() && idle == true ) { String[ ] device = it.next(); if ( device.length == 4 ) { String name = device[3]; String deviceId = device[0]; if ( name.equals( "keyboard" ) || name.equals( "PS/2Mouse" ) || deviceId.equals( "1:" ) || deviceId.equals( "12:" ) ) { String interrupt = device[1]; int index = currentStatus.indexOf( device ); String[ ] oldStatusObj = oldStatus.get( index ); String oldInterrupt = oldStatusObj[1]; if ( !interrupt.equals( oldInterrupt ) ) idle = false; } } } return idle; } /** * This method will get the last status of interruptions provided by the * linux system. It reads the file "/proc/interrupts" and stores the actual * state at a data structure. * * @throws IOException signalize the non existence of the "/proc/interrupts" * file or if it could not be correctly used. Note that the file * should exist if you are using Linux system. If not PLEASE * REPORT!!! */ private void readInterruptsFile(LinkedList<String[]> status) throws IOException { BufferedReader interruptState = null; try { interruptState = new BufferedReader( new FileReader( "/proc/interrupts" ) ); interruptState.readLine(); // Ignoring the first line that is not a // device. String deviceStatus = interruptState.readLine(); while ( deviceStatus != null ) { this.storeStatus( deviceStatus, status ); deviceStatus = interruptState.readLine(); } interruptState.close(); } catch ( IOException e ) { throw e; } finally { if ( interruptState != null ) { try { interruptState.close(); } catch ( IOException e1 ) { } } } } /** * Stores informations about a device at a array and puts it at the List * mantained by this class. The number of informations about the devices can * vary and because of this the algorithm is a bit more complicated. * * @param interruptFileLine A line readed from the interruptions file. */ private void storeStatus( String interruptFileLine, LinkedList<String[]> status ) { String[ ] info; StringTokenizer dsTokenizer = new StringTokenizer( interruptFileLine, " " ); int tokensNumber = dsTokenizer.countTokens(); if ( tokensNumber > 4 ) { info = new String[ 4 ]; } else { info = new String[ tokensNumber ]; } for ( int counter = 0; counter < info.length; counter++ ) { info[counter] = dsTokenizer.nextToken().trim(); } if ( tokensNumber == 5 ) { info[3] = info[3] + dsTokenizer.nextToken().trim(); } // Store the readed informations always at the actualStatus list. status.addLast( info ); } }