17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 237c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate * 267c478bd9Sstevel@tonic-gate * ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate */ 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate package com.sun.solaris.domain.pools; 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate import java.io.*; 327c478bd9Sstevel@tonic-gate import java.nio.*; 337c478bd9Sstevel@tonic-gate import java.nio.channels.*; 347c478bd9Sstevel@tonic-gate import java.util.*; 357c478bd9Sstevel@tonic-gate import java.util.regex.*; 367c478bd9Sstevel@tonic-gate import java.text.DecimalFormat; 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate import com.sun.solaris.service.locality.*; 397c478bd9Sstevel@tonic-gate import com.sun.solaris.service.logging.*; 407c478bd9Sstevel@tonic-gate import com.sun.solaris.service.pools.*; 417c478bd9Sstevel@tonic-gate import com.sun.solaris.service.exception.*; 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate /** 447c478bd9Sstevel@tonic-gate * The <code>SystemSolver</code> class implements a dynamic resource 457c478bd9Sstevel@tonic-gate * allocation solver. The Solver takes a configuration and "solves" 467c478bd9Sstevel@tonic-gate * the resource allocation problem. 477c478bd9Sstevel@tonic-gate * 487c478bd9Sstevel@tonic-gate * This class operates upon a configuration which is suppplied during 497c478bd9Sstevel@tonic-gate * initialization. Its responsibilities include: 507c478bd9Sstevel@tonic-gate * <ul> 517c478bd9Sstevel@tonic-gate * <li><p> 527c478bd9Sstevel@tonic-gate * Maintaining decision history 537c478bd9Sstevel@tonic-gate * <li><p> 547c478bd9Sstevel@tonic-gate * Maintaining information about the locality domain 557c478bd9Sstevel@tonic-gate * <li><p> 567c478bd9Sstevel@tonic-gate * Maintaining a map of all elements and their associated set of objectives 577c478bd9Sstevel@tonic-gate * <li><p> 587c478bd9Sstevel@tonic-gate * Identifying objective expressions with a configuration 597c478bd9Sstevel@tonic-gate * </ul> 607c478bd9Sstevel@tonic-gate */ 617c478bd9Sstevel@tonic-gate class SystemSolver implements Solver { 627c478bd9Sstevel@tonic-gate /** 637c478bd9Sstevel@tonic-gate * The default location of this history file. 647c478bd9Sstevel@tonic-gate */ 657c478bd9Sstevel@tonic-gate public static final String DH_FILE_DEF_PATH = 667c478bd9Sstevel@tonic-gate "/var/adm/pool/history"; 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate /** 697c478bd9Sstevel@tonic-gate * The property overriding the default decision history path. 707c478bd9Sstevel@tonic-gate */ 717c478bd9Sstevel@tonic-gate public static final String DH_FILE_PROP_NAME = 727c478bd9Sstevel@tonic-gate "system.poold.history-file"; 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate /** 757c478bd9Sstevel@tonic-gate * The LocalityDomain extracted from the configuration. 767c478bd9Sstevel@tonic-gate */ 777c478bd9Sstevel@tonic-gate private LocalityDomain ldom; 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate /** 807c478bd9Sstevel@tonic-gate * The objective map used to link all elements with their set 817c478bd9Sstevel@tonic-gate * of objectives. 827c478bd9Sstevel@tonic-gate */ 837c478bd9Sstevel@tonic-gate private Map objMap; 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate /** 867c478bd9Sstevel@tonic-gate * The pattern used to identify objective expressions. 877c478bd9Sstevel@tonic-gate */ 887c478bd9Sstevel@tonic-gate private static final Pattern p0 = Pattern.compile(";"); 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate /** 917c478bd9Sstevel@tonic-gate * The configuration for which this solver is "solving". 927c478bd9Sstevel@tonic-gate */ 937c478bd9Sstevel@tonic-gate private Configuration conf; 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate /** 967c478bd9Sstevel@tonic-gate * Monitor providing statistics for this solver. 977c478bd9Sstevel@tonic-gate */ 987c478bd9Sstevel@tonic-gate private final Monitor monitor; 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate /** 1017c478bd9Sstevel@tonic-gate * The decision history maintainer. 1027c478bd9Sstevel@tonic-gate */ 1037c478bd9Sstevel@tonic-gate private DecisionHistory dh; 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate /** 1067c478bd9Sstevel@tonic-gate * The path to the decision history file. 1077c478bd9Sstevel@tonic-gate */ 1087c478bd9Sstevel@tonic-gate private String dhPath; 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate /** 1117c478bd9Sstevel@tonic-gate * The number of CPUs on the system. 1127c478bd9Sstevel@tonic-gate */ 1137c478bd9Sstevel@tonic-gate private int cpuCount; 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate /** 1167c478bd9Sstevel@tonic-gate * The number of locality triggered examinations made. 1177c478bd9Sstevel@tonic-gate */ 1187c478bd9Sstevel@tonic-gate private int examineCount; 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate /** 1217c478bd9Sstevel@tonic-gate * Constructs a solver which initialises a decision history 1227c478bd9Sstevel@tonic-gate * maintainer. The decision history is be used during operation 1237c478bd9Sstevel@tonic-gate * to veto historically-poor decisions output from the objective 1247c478bd9Sstevel@tonic-gate * function. 1257c478bd9Sstevel@tonic-gate */ SystemSolver(Monitor monitor)1267c478bd9Sstevel@tonic-gate SystemSolver(Monitor monitor) 1277c478bd9Sstevel@tonic-gate { 1287c478bd9Sstevel@tonic-gate /* 1297c478bd9Sstevel@tonic-gate * Create a HashMap to store all objectives. 1307c478bd9Sstevel@tonic-gate */ 1317c478bd9Sstevel@tonic-gate objMap = new HashMap(); 1327c478bd9Sstevel@tonic-gate this.monitor = monitor; 1337c478bd9Sstevel@tonic-gate } 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate /** 1367c478bd9Sstevel@tonic-gate * Initialize the solver for operation upon the supplied 1377c478bd9Sstevel@tonic-gate * configuration. Possible objective expressions set upon 1387c478bd9Sstevel@tonic-gate * target elements are identified and stored in an objective 1397c478bd9Sstevel@tonic-gate * map which associates elements with the set of their 1407c478bd9Sstevel@tonic-gate * objectives. 141*55fea89dSDan Cross * 1427c478bd9Sstevel@tonic-gate * @param conf The configuration to be manipulated. 1437c478bd9Sstevel@tonic-gate * @throws PoolsException If the initialization fails. 1447c478bd9Sstevel@tonic-gate */ initialize(Configuration conf)1457c478bd9Sstevel@tonic-gate public void initialize(Configuration conf) throws PoolsException 1467c478bd9Sstevel@tonic-gate { 1477c478bd9Sstevel@tonic-gate String oString = null; 1487c478bd9Sstevel@tonic-gate String exps[]; 1497c478bd9Sstevel@tonic-gate 1507c478bd9Sstevel@tonic-gate this.conf = conf; 1517c478bd9Sstevel@tonic-gate /* 1527c478bd9Sstevel@tonic-gate * Count the CPUs in the system, this is used to 1537c478bd9Sstevel@tonic-gate * control locality objective processing in the 1547c478bd9Sstevel@tonic-gate * examine() method. 1557c478bd9Sstevel@tonic-gate */ 1567c478bd9Sstevel@tonic-gate cpuCount = conf.getComponents(null).size(); 1577c478bd9Sstevel@tonic-gate examineCount = 0; 1587c478bd9Sstevel@tonic-gate /* 1597c478bd9Sstevel@tonic-gate * Remove any old objectives 1607c478bd9Sstevel@tonic-gate */ 1617c478bd9Sstevel@tonic-gate objMap.clear(); 162*55fea89dSDan Cross 1637c478bd9Sstevel@tonic-gate /* 1647c478bd9Sstevel@tonic-gate * Extract any configuration objectives 1657c478bd9Sstevel@tonic-gate */ 1667c478bd9Sstevel@tonic-gate try { 1677c478bd9Sstevel@tonic-gate oString = conf.getStringProperty( 1687c478bd9Sstevel@tonic-gate "system.poold.objectives"); 1697c478bd9Sstevel@tonic-gate if (oString.length() > 0) { 1707c478bd9Sstevel@tonic-gate Set oSet = new HashSet(); 1717c478bd9Sstevel@tonic-gate objMap.put(conf, oSet); 1727c478bd9Sstevel@tonic-gate Poold.CONF_LOG.log(Severity.DEBUG, 1737c478bd9Sstevel@tonic-gate "adding configuration objective " + 1747c478bd9Sstevel@tonic-gate oString); 1757c478bd9Sstevel@tonic-gate exps = p0.split(oString); 1767c478bd9Sstevel@tonic-gate for (int i = 0; i < exps.length; i++) { 1777c478bd9Sstevel@tonic-gate try { 1787c478bd9Sstevel@tonic-gate Expression exp = 1797c478bd9Sstevel@tonic-gate Expression.valueOf( 1807c478bd9Sstevel@tonic-gate exps[i]); 1817c478bd9Sstevel@tonic-gate addObjective(oSet, "system", 1827c478bd9Sstevel@tonic-gate exp); 1837c478bd9Sstevel@tonic-gate } catch (IllegalArgumentException iae) { 1847c478bd9Sstevel@tonic-gate Poold.utility.warn( 1857c478bd9Sstevel@tonic-gate Poold.CONF_LOG, iae, false); 1867c478bd9Sstevel@tonic-gate } 1877c478bd9Sstevel@tonic-gate } 1887c478bd9Sstevel@tonic-gate } 1897c478bd9Sstevel@tonic-gate } catch (PoolsException pe) { 1907c478bd9Sstevel@tonic-gate /* 1917c478bd9Sstevel@tonic-gate * Ignore as this means there is no objective 1927c478bd9Sstevel@tonic-gate * property 1937c478bd9Sstevel@tonic-gate */ 1947c478bd9Sstevel@tonic-gate } 1957c478bd9Sstevel@tonic-gate /* 1967c478bd9Sstevel@tonic-gate * Now extract all pset objectives 1977c478bd9Sstevel@tonic-gate */ 1987c478bd9Sstevel@tonic-gate Value typeProp = new Value("type", "pset"); 1997c478bd9Sstevel@tonic-gate List valueList = new LinkedList(); 2007c478bd9Sstevel@tonic-gate valueList.add(typeProp); 2017c478bd9Sstevel@tonic-gate Iterator resIt = conf.getResources(valueList).iterator(); 2027c478bd9Sstevel@tonic-gate typeProp.close(); 2037c478bd9Sstevel@tonic-gate while (resIt.hasNext()) { 2047c478bd9Sstevel@tonic-gate Resource resource = (Resource)resIt.next(); 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate try { 2077c478bd9Sstevel@tonic-gate oString = resource.getStringProperty( 2087c478bd9Sstevel@tonic-gate "pset.poold.objectives"); 2097c478bd9Sstevel@tonic-gate if (oString.length() > 0) { 2107c478bd9Sstevel@tonic-gate Set oSet = new HashSet(); 2117c478bd9Sstevel@tonic-gate objMap.put(resource, oSet); 2127c478bd9Sstevel@tonic-gate Poold.CONF_LOG.log(Severity.DEBUG, 2137c478bd9Sstevel@tonic-gate "adding " + 2147c478bd9Sstevel@tonic-gate resource.getStringProperty( 2157c478bd9Sstevel@tonic-gate "pset.name") + 2167c478bd9Sstevel@tonic-gate " objective \"" + oString + "\""); 2177c478bd9Sstevel@tonic-gate exps = p0.split(oString); 2187c478bd9Sstevel@tonic-gate for (int i = 0; i < exps.length; i++) { 2197c478bd9Sstevel@tonic-gate Expression exp = null; 2207c478bd9Sstevel@tonic-gate try { 2217c478bd9Sstevel@tonic-gate exp = Expression. 2227c478bd9Sstevel@tonic-gate valueOf(exps[i]); 2237c478bd9Sstevel@tonic-gate addObjective(oSet, 2247c478bd9Sstevel@tonic-gate "pset", exp); 2257c478bd9Sstevel@tonic-gate } catch 2267c478bd9Sstevel@tonic-gate (IllegalArgumentException e) 2277c478bd9Sstevel@tonic-gate { 2287c478bd9Sstevel@tonic-gate Poold.utility.warn( 2297c478bd9Sstevel@tonic-gate Poold.CONF_LOG, e, 2307c478bd9Sstevel@tonic-gate false); 2317c478bd9Sstevel@tonic-gate } 2327c478bd9Sstevel@tonic-gate } 2337c478bd9Sstevel@tonic-gate } 2347c478bd9Sstevel@tonic-gate } catch (PoolsException pe) { 2357c478bd9Sstevel@tonic-gate continue; 2367c478bd9Sstevel@tonic-gate } 2377c478bd9Sstevel@tonic-gate } 2387c478bd9Sstevel@tonic-gate Poold.CONF_LOG.log(Severity.DEBUG, "objective map: " + 2397c478bd9Sstevel@tonic-gate objMap.toString()); 240*55fea89dSDan Cross 2417c478bd9Sstevel@tonic-gate /* 2427c478bd9Sstevel@tonic-gate * Capture the LocalityDomain details. 2437c478bd9Sstevel@tonic-gate */ 2447c478bd9Sstevel@tonic-gate if (ldom != null) { 2457c478bd9Sstevel@tonic-gate ldom.close(); 2467c478bd9Sstevel@tonic-gate } 2477c478bd9Sstevel@tonic-gate try { 2487c478bd9Sstevel@tonic-gate ldom = new LocalityDomain(LocalityDomain.LGRP_VIEW_OS); 2497c478bd9Sstevel@tonic-gate } catch (Exception e) { 2507c478bd9Sstevel@tonic-gate Poold.utility.die(Poold.OPT_LOG, e); 2517c478bd9Sstevel@tonic-gate } 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate /* 2547c478bd9Sstevel@tonic-gate * Load or create the decision history. 2557c478bd9Sstevel@tonic-gate */ 2567c478bd9Sstevel@tonic-gate String newDhPath; 2577c478bd9Sstevel@tonic-gate try { 2587c478bd9Sstevel@tonic-gate newDhPath = conf.getStringProperty( 2597c478bd9Sstevel@tonic-gate DH_FILE_PROP_NAME); 2607c478bd9Sstevel@tonic-gate } catch (PoolsException pe) { 2617c478bd9Sstevel@tonic-gate newDhPath = DH_FILE_DEF_PATH; 2627c478bd9Sstevel@tonic-gate } 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate if (!newDhPath.equals(dhPath)) { 2657c478bd9Sstevel@tonic-gate try { 2667c478bd9Sstevel@tonic-gate dh = DecisionHistory.loadFromFile(newDhPath); 2677c478bd9Sstevel@tonic-gate Poold.CONF_LOG.log(Severity.DEBUG, 2687c478bd9Sstevel@tonic-gate "loaded history file " + newDhPath); 2697c478bd9Sstevel@tonic-gate } catch (Exception e) { 2707c478bd9Sstevel@tonic-gate if (!(e instanceof FileNotFoundException)) { 2717c478bd9Sstevel@tonic-gate Poold.CONF_LOG.log(Severity.WARNING, 2727c478bd9Sstevel@tonic-gate newDhPath + 2737c478bd9Sstevel@tonic-gate ": contents unusable; ignoring"); 2747c478bd9Sstevel@tonic-gate Poold.CONF_LOG.log(Severity.DEBUG, 2757c478bd9Sstevel@tonic-gate newDhPath + ": contents unusable", 2767c478bd9Sstevel@tonic-gate e); 2777c478bd9Sstevel@tonic-gate } 2787c478bd9Sstevel@tonic-gate /* 2797c478bd9Sstevel@tonic-gate * Use current DecisionHistory instead, 280*55fea89dSDan Cross * if any. 2817c478bd9Sstevel@tonic-gate */ 2827c478bd9Sstevel@tonic-gate if (dh == null) 2837c478bd9Sstevel@tonic-gate dh = new DecisionHistory(); 2847c478bd9Sstevel@tonic-gate } 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate /* 2877c478bd9Sstevel@tonic-gate * Try using the new path. 2887c478bd9Sstevel@tonic-gate */ 2897c478bd9Sstevel@tonic-gate try { 2907c478bd9Sstevel@tonic-gate dh.syncToFile(newDhPath); 2917c478bd9Sstevel@tonic-gate } catch (Exception e) { 2927c478bd9Sstevel@tonic-gate Poold.utility.die(Poold.CONF_LOG, 2937c478bd9Sstevel@tonic-gate new PooldException(newDhPath + 2947c478bd9Sstevel@tonic-gate ": couldn't synchronize history file") 2957c478bd9Sstevel@tonic-gate .initCause(e), false); 2967c478bd9Sstevel@tonic-gate } 2977c478bd9Sstevel@tonic-gate dhPath = newDhPath; 2987c478bd9Sstevel@tonic-gate } 2997c478bd9Sstevel@tonic-gate } 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate /** 3027c478bd9Sstevel@tonic-gate * Determine if the given resource has non-workload-dependent 303*55fea89dSDan Cross * objectives. 3047c478bd9Sstevel@tonic-gate * @param elem The element to examine. 3057c478bd9Sstevel@tonic-gate */ hasNonWorkloadDependentObjectives(Element elem)3067c478bd9Sstevel@tonic-gate private boolean hasNonWorkloadDependentObjectives(Element elem) 3077c478bd9Sstevel@tonic-gate { 3087c478bd9Sstevel@tonic-gate Set elemObj = (Set)objMap.get(elem); 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate /* 3117c478bd9Sstevel@tonic-gate * This code relies upon the fact that an element with 3127c478bd9Sstevel@tonic-gate * no objectives will not have an empty set, but rather 3137c478bd9Sstevel@tonic-gate * no value in the objMap. 3147c478bd9Sstevel@tonic-gate */ 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate if (elemObj == null) 3177c478bd9Sstevel@tonic-gate return (false); 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate Iterator elemObjIt = elemObj.iterator(); 3207c478bd9Sstevel@tonic-gate while (elemObjIt.hasNext()) 3217c478bd9Sstevel@tonic-gate if (elemObjIt.next() instanceof 3227c478bd9Sstevel@tonic-gate WorkloadDependentObjective) 3237c478bd9Sstevel@tonic-gate return (false); 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate return (true); 3267c478bd9Sstevel@tonic-gate } 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate /** 3297c478bd9Sstevel@tonic-gate * Determine if the given resource has workload-dependent 3307c478bd9Sstevel@tonic-gate * objectives. 3317c478bd9Sstevel@tonic-gate * @param elem The element to examine. 3327c478bd9Sstevel@tonic-gate */ hasWorkloadDependentObjectives(Element elem)3337c478bd9Sstevel@tonic-gate private boolean hasWorkloadDependentObjectives(Element elem) 3347c478bd9Sstevel@tonic-gate { 3357c478bd9Sstevel@tonic-gate Set elemObj = (Set)objMap.get(elem); 3367c478bd9Sstevel@tonic-gate 3377c478bd9Sstevel@tonic-gate /* 3387c478bd9Sstevel@tonic-gate * This code relies upon the fact that an element with 3397c478bd9Sstevel@tonic-gate * no objectives will not have an empty set, but rather 3407c478bd9Sstevel@tonic-gate * no value in the objMap. 3417c478bd9Sstevel@tonic-gate */ 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate if (elemObj == null) 3447c478bd9Sstevel@tonic-gate return (false); 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate Iterator elemObjIt = elemObj.iterator(); 3477c478bd9Sstevel@tonic-gate while (elemObjIt.hasNext()) 3487c478bd9Sstevel@tonic-gate if (elemObjIt.next() instanceof 3497c478bd9Sstevel@tonic-gate WorkloadDependentObjective) 3507c478bd9Sstevel@tonic-gate return (true); 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate return (false); 3537c478bd9Sstevel@tonic-gate } 3547c478bd9Sstevel@tonic-gate 3557c478bd9Sstevel@tonic-gate /** 3567c478bd9Sstevel@tonic-gate * Return true if the monitored configuration should be 3577c478bd9Sstevel@tonic-gate * reconfigured. All workload-dependent objectives are 3587c478bd9Sstevel@tonic-gate * examined to determine if the configuration is still 3597c478bd9Sstevel@tonic-gate * satisfying all specified objectives on all elements. If any 3607c478bd9Sstevel@tonic-gate * objectives are failing, then this method will return true. 3617c478bd9Sstevel@tonic-gate * 3627c478bd9Sstevel@tonic-gate * @param mon The monitoring object used to assess objective 3637c478bd9Sstevel@tonic-gate * compliance. 3647c478bd9Sstevel@tonic-gate */ examine(Monitor mon)3657c478bd9Sstevel@tonic-gate public boolean examine(Monitor mon) throws PoolsException, 3667c478bd9Sstevel@tonic-gate StaleMonitorException 3677c478bd9Sstevel@tonic-gate { 3687c478bd9Sstevel@tonic-gate /* 3697c478bd9Sstevel@tonic-gate * Take advantage of the guaranteed-valid monitor data 3707c478bd9Sstevel@tonic-gate * for measuring the improvement of any past decisions. 3717c478bd9Sstevel@tonic-gate */ 3727c478bd9Sstevel@tonic-gate dh.expireAndMeasureImprovements(mon); 3737c478bd9Sstevel@tonic-gate 3747c478bd9Sstevel@tonic-gate Iterator objIt = objMap.keySet().iterator(); 3757c478bd9Sstevel@tonic-gate boolean ret = false; 3767c478bd9Sstevel@tonic-gate boolean hasLocalityObjectives = false; 3777c478bd9Sstevel@tonic-gate boolean isMonitorValid = true; 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate /* 3807c478bd9Sstevel@tonic-gate * All objectives are examined, even though failure 3817c478bd9Sstevel@tonic-gate * could be detected earlier. This is because logging 3827c478bd9Sstevel@tonic-gate * of all objectives is required and the information 3837c478bd9Sstevel@tonic-gate * about failure can be stored and used during 3847c478bd9Sstevel@tonic-gate * solving. 3857c478bd9Sstevel@tonic-gate */ 3867c478bd9Sstevel@tonic-gate while (objIt.hasNext()) { 3877c478bd9Sstevel@tonic-gate Element elem = (Element) objIt.next(); 3887c478bd9Sstevel@tonic-gate Set elemObj = (Set) objMap.get(elem); 3897c478bd9Sstevel@tonic-gate Iterator elemObjIt = elemObj.iterator(); 3907c478bd9Sstevel@tonic-gate while (elemObjIt.hasNext()) { 3917c478bd9Sstevel@tonic-gate Objective obj = (Objective) elemObjIt.next(); 3927c478bd9Sstevel@tonic-gate Poold.OPT_LOG.log(Severity.DEBUG, 3937c478bd9Sstevel@tonic-gate "checking objective " + obj); 3947c478bd9Sstevel@tonic-gate if (obj instanceof WorkloadDependentObjective) { 3957c478bd9Sstevel@tonic-gate if (isValid()) { 3967c478bd9Sstevel@tonic-gate /* 3977c478bd9Sstevel@tonic-gate * If any objectives 3987c478bd9Sstevel@tonic-gate * are violated, then 3997c478bd9Sstevel@tonic-gate * we must 4007c478bd9Sstevel@tonic-gate * reconfigure, so 4017c478bd9Sstevel@tonic-gate * check them all in 4027c478bd9Sstevel@tonic-gate * turn. 4037c478bd9Sstevel@tonic-gate */ 4047c478bd9Sstevel@tonic-gate ret = ((WorkloadDependentObjective) 4057c478bd9Sstevel@tonic-gate obj).examine(conf, this, elem) || 4067c478bd9Sstevel@tonic-gate ret; 4077c478bd9Sstevel@tonic-gate } else 4087c478bd9Sstevel@tonic-gate isMonitorValid = false; 4097c478bd9Sstevel@tonic-gate } 4107c478bd9Sstevel@tonic-gate } 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate /* 4137c478bd9Sstevel@tonic-gate * Check if this is the first element, seen in 4147c478bd9Sstevel@tonic-gate * this pass, that has locality objectives. 4157c478bd9Sstevel@tonic-gate */ 4167c478bd9Sstevel@tonic-gate if (!hasLocalityObjectives && 4177c478bd9Sstevel@tonic-gate hasNonWorkloadDependentObjectives(elem)) 4187c478bd9Sstevel@tonic-gate hasLocalityObjectives = true; 4197c478bd9Sstevel@tonic-gate } 4207c478bd9Sstevel@tonic-gate if (isMonitorValid == false) { 4217c478bd9Sstevel@tonic-gate Poold.MON_LOG.log(Severity.INFO, 4227c478bd9Sstevel@tonic-gate "not evaluating workload-dependent objectives " + 4237c478bd9Sstevel@tonic-gate "until sufficient statistics are collected"); 4247c478bd9Sstevel@tonic-gate } 4257c478bd9Sstevel@tonic-gate /* 4267c478bd9Sstevel@tonic-gate * If we don't have locality objectives, we don't force 4277c478bd9Sstevel@tonic-gate * the reexamination. This is controlled by 4287c478bd9Sstevel@tonic-gate * hasLocalityObjectives. 4297c478bd9Sstevel@tonic-gate * 4307c478bd9Sstevel@tonic-gate * So that we don't continually trigger 4317c478bd9Sstevel@tonic-gate * reconfiguration examinations for locality 4327c478bd9Sstevel@tonic-gate * objectives we stop forcing recalculations when we 4337c478bd9Sstevel@tonic-gate * reach cpuCount / 2. This should be enough moves to 4347c478bd9Sstevel@tonic-gate * get good locality for those configurations which 4357c478bd9Sstevel@tonic-gate * have no WorkloadDependentObjectives. 4367c478bd9Sstevel@tonic-gate */ 4377c478bd9Sstevel@tonic-gate return (ret || (hasLocalityObjectives && (examineCount++ < 4387c478bd9Sstevel@tonic-gate cpuCount / 2))); 4397c478bd9Sstevel@tonic-gate } 4407c478bd9Sstevel@tonic-gate 4417c478bd9Sstevel@tonic-gate /** 4427c478bd9Sstevel@tonic-gate * Reallocate resources in a configuration to achieve user 4437c478bd9Sstevel@tonic-gate * specified objectives. Return true if the configuration has 4447c478bd9Sstevel@tonic-gate * been updated, false otherwise. 4457c478bd9Sstevel@tonic-gate * 4467c478bd9Sstevel@tonic-gate * This method should only be invoked if a previous 4477c478bd9Sstevel@tonic-gate * examination of the configuration which is monitored 4487c478bd9Sstevel@tonic-gate * indicates that objectives are failing. The monitored 4497c478bd9Sstevel@tonic-gate * configuration is re-opened for editing, locking that 4507c478bd9Sstevel@tonic-gate * configuration for the duration of this operation. 4517c478bd9Sstevel@tonic-gate * 4527c478bd9Sstevel@tonic-gate * @throws Exception If the solve fails. 4537c478bd9Sstevel@tonic-gate */ solve()4547c478bd9Sstevel@tonic-gate public boolean solve() throws Exception 4557c478bd9Sstevel@tonic-gate { 4567c478bd9Sstevel@tonic-gate boolean madeMove = false; 4577c478bd9Sstevel@tonic-gate /* 4587c478bd9Sstevel@tonic-gate * All solving operations must be done in an 4597c478bd9Sstevel@tonic-gate * "editable" context, so create a new modifiable 4607c478bd9Sstevel@tonic-gate * configuration which is at the same location as the 4617c478bd9Sstevel@tonic-gate * monitored configuration 4627c478bd9Sstevel@tonic-gate */ 4637c478bd9Sstevel@tonic-gate Configuration rwConf = new Configuration(conf.getLocation(), 4647c478bd9Sstevel@tonic-gate PoolInternal.PO_RDWR); 465*55fea89dSDan Cross 4667c478bd9Sstevel@tonic-gate try { 4677c478bd9Sstevel@tonic-gate /* 4687c478bd9Sstevel@tonic-gate * Build a resource set importance map for use 4697c478bd9Sstevel@tonic-gate * when propagating pool importance to each 4707c478bd9Sstevel@tonic-gate * possible solution. Use the same logic as 4717c478bd9Sstevel@tonic-gate * libpool and let a resource take the highest 4727c478bd9Sstevel@tonic-gate * importance value from all pools associated 4737c478bd9Sstevel@tonic-gate * with the set. 4747c478bd9Sstevel@tonic-gate */ 4757c478bd9Sstevel@tonic-gate Map resImp = new HashMap(); 4767c478bd9Sstevel@tonic-gate List poolList = rwConf.getPools(null); 4777c478bd9Sstevel@tonic-gate Iterator itPool = poolList.iterator(); 4787c478bd9Sstevel@tonic-gate while (itPool.hasNext()) { 4797c478bd9Sstevel@tonic-gate Pool pool = (Pool) itPool.next(); 4807c478bd9Sstevel@tonic-gate long newImp = pool. 4817c478bd9Sstevel@tonic-gate getLongProperty("pool.importance"); 4827c478bd9Sstevel@tonic-gate List resList = pool.getResources(null); 4837c478bd9Sstevel@tonic-gate Iterator itRes = resList.iterator(); 4847c478bd9Sstevel@tonic-gate while (itRes.hasNext()) { 4857c478bd9Sstevel@tonic-gate Resource res = (Resource) itRes.next(); 4867c478bd9Sstevel@tonic-gate if (resImp.containsKey(res)) { 4877c478bd9Sstevel@tonic-gate Long imp = (Long) resImp. 4887c478bd9Sstevel@tonic-gate get(res); 4897c478bd9Sstevel@tonic-gate if (newImp > imp.longValue()) 4907c478bd9Sstevel@tonic-gate resImp.put(res, 4917c478bd9Sstevel@tonic-gate new Long(newImp)); 4927c478bd9Sstevel@tonic-gate } else 4937c478bd9Sstevel@tonic-gate resImp.put(res, 494*55fea89dSDan Cross new Long(newImp)); 4957c478bd9Sstevel@tonic-gate } 4967c478bd9Sstevel@tonic-gate } 4977c478bd9Sstevel@tonic-gate /* 4987c478bd9Sstevel@tonic-gate * Consider all possible alternative 4997c478bd9Sstevel@tonic-gate * configurations. This list is generated as a 5007c478bd9Sstevel@tonic-gate * series of moves. Administrative constraints 5017c478bd9Sstevel@tonic-gate * are applied to the moves to prune the list of 5027c478bd9Sstevel@tonic-gate * possible configurations. 5037c478bd9Sstevel@tonic-gate */ 5047c478bd9Sstevel@tonic-gate Value val = new Value("type", "pset"); 5057c478bd9Sstevel@tonic-gate List valueList = new LinkedList(); 5067c478bd9Sstevel@tonic-gate valueList.add(val); 5077c478bd9Sstevel@tonic-gate 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate List resList = rwConf.getResources(valueList); 5107c478bd9Sstevel@tonic-gate val.close(); 5117c478bd9Sstevel@tonic-gate List donors = getDonors(resList); 5127c478bd9Sstevel@tonic-gate List receivers = getRecipients(resList); 5137c478bd9Sstevel@tonic-gate Poold.OPT_LOG.log(Severity.DEBUG, "donors: " + 5147c478bd9Sstevel@tonic-gate donors); 5157c478bd9Sstevel@tonic-gate Poold.OPT_LOG.log(Severity.DEBUG, "receivers: " + 5167c478bd9Sstevel@tonic-gate receivers); 5177c478bd9Sstevel@tonic-gate Iterator itDonor = donors.iterator(); 5187c478bd9Sstevel@tonic-gate List moves = new ArrayList(); 5197c478bd9Sstevel@tonic-gate while (itDonor.hasNext()) { 5207c478bd9Sstevel@tonic-gate Resource donor = (Resource) itDonor.next(); 5217c478bd9Sstevel@tonic-gate List processors = getProcessors(donor); 5227c478bd9Sstevel@tonic-gate Poold.OPT_LOG.log(Severity.DEBUG, 5237c478bd9Sstevel@tonic-gate "donor processors: " + processors); 5247c478bd9Sstevel@tonic-gate Iterator itProcessor = processors.iterator(); 5257c478bd9Sstevel@tonic-gate while (itProcessor.hasNext()) { 5267c478bd9Sstevel@tonic-gate Component cpu = (Component) itProcessor. 5277c478bd9Sstevel@tonic-gate next(); 5287c478bd9Sstevel@tonic-gate Iterator itReceiver = receivers. 5297c478bd9Sstevel@tonic-gate iterator(); 5307c478bd9Sstevel@tonic-gate while (itReceiver.hasNext()) { 5317c478bd9Sstevel@tonic-gate Resource receiver = 5327c478bd9Sstevel@tonic-gate (Resource) itReceiver. 5337c478bd9Sstevel@tonic-gate next(); 5347c478bd9Sstevel@tonic-gate /* 5357c478bd9Sstevel@tonic-gate * Can't move to yourself 5367c478bd9Sstevel@tonic-gate */ 5377c478bd9Sstevel@tonic-gate if (receiver == donor) 5387c478bd9Sstevel@tonic-gate continue; 5397c478bd9Sstevel@tonic-gate moves.add(new ComponentMove( 5407c478bd9Sstevel@tonic-gate donor, receiver, cpu)); 5417c478bd9Sstevel@tonic-gate } 5427c478bd9Sstevel@tonic-gate } 5437c478bd9Sstevel@tonic-gate } 5447c478bd9Sstevel@tonic-gate Poold.OPT_LOG.log(Severity.DEBUG, 5457c478bd9Sstevel@tonic-gate "potential moves: " + moves); 5467c478bd9Sstevel@tonic-gate /* 5477c478bd9Sstevel@tonic-gate * Now that we have our alternative configurations, 5487c478bd9Sstevel@tonic-gate * score each configuration by applying all objectives 5497c478bd9Sstevel@tonic-gate * to each configuration. Hold the scores in the 5507c478bd9Sstevel@tonic-gate * score set. 5517c478bd9Sstevel@tonic-gate */ 5527c478bd9Sstevel@tonic-gate HashSet scores = new HashSet(); 5537c478bd9Sstevel@tonic-gate Iterator itMoves = moves.iterator(); 5547c478bd9Sstevel@tonic-gate while (itMoves.hasNext()) { 5557c478bd9Sstevel@tonic-gate double totalContrib = 0; 5567c478bd9Sstevel@tonic-gate Move move = (Move) itMoves.next(); 5577c478bd9Sstevel@tonic-gate Iterator objIt = objMap.keySet().iterator(); 5587c478bd9Sstevel@tonic-gate while (objIt.hasNext()) { 5597c478bd9Sstevel@tonic-gate Element elem = (Element) objIt.next(); 5607c478bd9Sstevel@tonic-gate Set elemObj = (Set) objMap.get(elem); 5617c478bd9Sstevel@tonic-gate Iterator elemObjIt = elemObj.iterator(); 5627c478bd9Sstevel@tonic-gate while (elemObjIt.hasNext()) { 5637c478bd9Sstevel@tonic-gate Objective obj = 5647c478bd9Sstevel@tonic-gate (Objective)elemObjIt.next(); 5657c478bd9Sstevel@tonic-gate if (obj instanceof 5667c478bd9Sstevel@tonic-gate LocalityObjective) 5677c478bd9Sstevel@tonic-gate ((LocalityObjective)obj) 5687c478bd9Sstevel@tonic-gate .prepare(ldom, 5697c478bd9Sstevel@tonic-gate (Resource)elem); 5707c478bd9Sstevel@tonic-gate /* 5717c478bd9Sstevel@tonic-gate * If the monitor is 5727c478bd9Sstevel@tonic-gate * invalid, do not 5737c478bd9Sstevel@tonic-gate * process 5747c478bd9Sstevel@tonic-gate * WorkloadDependentObjectives 5757c478bd9Sstevel@tonic-gate * since they have an 5767c478bd9Sstevel@tonic-gate * implicit dependency 5777c478bd9Sstevel@tonic-gate * on the monitor 5787c478bd9Sstevel@tonic-gate * data. 5797c478bd9Sstevel@tonic-gate */ 5807c478bd9Sstevel@tonic-gate if (obj instanceof 5817c478bd9Sstevel@tonic-gate WorkloadDependentObjective) 5827c478bd9Sstevel@tonic-gate if (!isValid()) 5837c478bd9Sstevel@tonic-gate continue; 5847c478bd9Sstevel@tonic-gate double contrib = obj.calculate( 5857c478bd9Sstevel@tonic-gate rwConf, move, elem); 5867c478bd9Sstevel@tonic-gate if (contrib < -1 || contrib > 1) 5877c478bd9Sstevel@tonic-gate throw new 5887c478bd9Sstevel@tonic-gate IllegalOFValueException( 5897c478bd9Sstevel@tonic-gate "x: " + contrib + 5907c478bd9Sstevel@tonic-gate " is invalid, legal " + 5917c478bd9Sstevel@tonic-gate "range is -1 <= x <= " + 5927c478bd9Sstevel@tonic-gate "1"); 5937c478bd9Sstevel@tonic-gate /* 5947c478bd9Sstevel@tonic-gate * Modify the basic 5957c478bd9Sstevel@tonic-gate * score by the 5967c478bd9Sstevel@tonic-gate * importance of the 5977c478bd9Sstevel@tonic-gate * objective and (if 5987c478bd9Sstevel@tonic-gate * appropriate) the 5997c478bd9Sstevel@tonic-gate * importance of an 6007c478bd9Sstevel@tonic-gate * associated pool. 6017c478bd9Sstevel@tonic-gate */ 6027c478bd9Sstevel@tonic-gate if (resImp.containsKey(elem)) { 6037c478bd9Sstevel@tonic-gate contrib *= ((Long) 6047c478bd9Sstevel@tonic-gate resImp.get(elem)). 6057c478bd9Sstevel@tonic-gate longValue(); 6067c478bd9Sstevel@tonic-gate } 607*55fea89dSDan Cross 6087c478bd9Sstevel@tonic-gate totalContrib += contrib * 6097c478bd9Sstevel@tonic-gate obj.getExpression(). 6107c478bd9Sstevel@tonic-gate getImportance(); 6117c478bd9Sstevel@tonic-gate } 6127c478bd9Sstevel@tonic-gate } 6137c478bd9Sstevel@tonic-gate Poold.OPT_LOG.log(Severity.DEBUG, 6147c478bd9Sstevel@tonic-gate "scored move (" + move + ") " + 6157c478bd9Sstevel@tonic-gate totalContrib); 6167c478bd9Sstevel@tonic-gate scores.add(new ScoreMove(move, totalContrib)); 6177c478bd9Sstevel@tonic-gate } 6187c478bd9Sstevel@tonic-gate if (scores.size() != 0) { 6197c478bd9Sstevel@tonic-gate /* 6207c478bd9Sstevel@tonic-gate * Try to find a move to apply which 6217c478bd9Sstevel@tonic-gate * yields a positive contribution. 6227c478bd9Sstevel@tonic-gate */ 6237c478bd9Sstevel@tonic-gate Object scoresArray[] = scores.toArray(); 6247c478bd9Sstevel@tonic-gate Arrays.sort(scoresArray, 6257c478bd9Sstevel@tonic-gate Collections.reverseOrder()); 6267c478bd9Sstevel@tonic-gate if ((madeMove = processMoves(rwConf, 6277c478bd9Sstevel@tonic-gate scoresArray, false)) == false) 6287c478bd9Sstevel@tonic-gate madeMove = processMoves(rwConf, 6297c478bd9Sstevel@tonic-gate scoresArray, true); 6307c478bd9Sstevel@tonic-gate } else 6317c478bd9Sstevel@tonic-gate Poold.OPT_LOG.log(Severity.INFO, 6327c478bd9Sstevel@tonic-gate "no moves found"); 6337c478bd9Sstevel@tonic-gate rwConf.close(); 6347c478bd9Sstevel@tonic-gate Poold.OPT_LOG.log(Severity.DEBUG, 6357c478bd9Sstevel@tonic-gate "synchronizing decision history"); 6367c478bd9Sstevel@tonic-gate dh.syncToFile(dhPath); 6377c478bd9Sstevel@tonic-gate } catch (Exception ex) { 6387c478bd9Sstevel@tonic-gate rwConf.close(); 6397c478bd9Sstevel@tonic-gate throw ex; 6407c478bd9Sstevel@tonic-gate } 6417c478bd9Sstevel@tonic-gate return (madeMove); 6427c478bd9Sstevel@tonic-gate } 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate /* 6457c478bd9Sstevel@tonic-gate * Process the supplied array of scored moves, trying to find 6467c478bd9Sstevel@tonic-gate * a move to apply. Return true if a move could be applied, 6477c478bd9Sstevel@tonic-gate * false otherwise. 6487c478bd9Sstevel@tonic-gate * 6497c478bd9Sstevel@tonic-gate * @param conf The configuration to be modified. 6507c478bd9Sstevel@tonic-gate * @param scores The areay of scored moves to be tried. 6517c478bd9Sstevel@tonic-gate * @param ignoreDH Ignore Decision History details. 6527c478bd9Sstevel@tonic-gate */ processMoves(Configuration rwConf, Object scores[], boolean ignoreDH)653*55fea89dSDan Cross private boolean processMoves(Configuration rwConf, Object scores[], 6547c478bd9Sstevel@tonic-gate boolean ignoreDH) throws PoolsException, StaleMonitorException 6557c478bd9Sstevel@tonic-gate { 6567c478bd9Sstevel@tonic-gate boolean madeMove = false; 6577c478bd9Sstevel@tonic-gate 6587c478bd9Sstevel@tonic-gate for (int i = 0; i < scores.length; i++) { 6597c478bd9Sstevel@tonic-gate ScoreMove move = (ScoreMove) scores[i]; 6607c478bd9Sstevel@tonic-gate if (move.getScore() <= 0) { 6617c478bd9Sstevel@tonic-gate if (ignoreDH) 6627c478bd9Sstevel@tonic-gate Poold.OPT_LOG.log(Severity.INFO, 6637c478bd9Sstevel@tonic-gate move + " not applied as " + 6647c478bd9Sstevel@tonic-gate "benefit not significant"); 6657c478bd9Sstevel@tonic-gate break; 6667c478bd9Sstevel@tonic-gate } 6677c478bd9Sstevel@tonic-gate if ((madeMove = applyMove(rwConf, move, ignoreDH)) == 6687c478bd9Sstevel@tonic-gate true) 6697c478bd9Sstevel@tonic-gate break; 6707c478bd9Sstevel@tonic-gate } 6717c478bd9Sstevel@tonic-gate return (madeMove); 6727c478bd9Sstevel@tonic-gate } 673*55fea89dSDan Cross 6747c478bd9Sstevel@tonic-gate /* 6757c478bd9Sstevel@tonic-gate * Attempt to apply the supplied move to the 6767c478bd9Sstevel@tonic-gate * configuration. Return true if the move could be applied, 6777c478bd9Sstevel@tonic-gate * false otherwise. 6787c478bd9Sstevel@tonic-gate * 6797c478bd9Sstevel@tonic-gate * @param conf The configuration to be modified. 6807c478bd9Sstevel@tonic-gate * @param move The move to be applied. 6817c478bd9Sstevel@tonic-gate * @param ignoreDH Ignore Decision History details. 6827c478bd9Sstevel@tonic-gate */ applyMove(Configuration conf, ScoreMove move, boolean ignoreDH)6837c478bd9Sstevel@tonic-gate private boolean applyMove(Configuration conf, ScoreMove move, 6847c478bd9Sstevel@tonic-gate boolean ignoreDH) 6857c478bd9Sstevel@tonic-gate throws PoolsException, StaleMonitorException 6867c478bd9Sstevel@tonic-gate { 6877c478bd9Sstevel@tonic-gate boolean madeMove = false; 6887c478bd9Sstevel@tonic-gate boolean wdpInvolved = false; 6897c478bd9Sstevel@tonic-gate double utilization = 0.0; 6907c478bd9Sstevel@tonic-gate 6917c478bd9Sstevel@tonic-gate Poold.OPT_LOG.log(Severity.DEBUG, "selected " + move); 6927c478bd9Sstevel@tonic-gate if (hasWorkloadDependentObjectives(move.getMove().getTo()) || 6937c478bd9Sstevel@tonic-gate hasWorkloadDependentObjectives(conf)) { 6947c478bd9Sstevel@tonic-gate Poold.OPT_LOG.log(Severity.DEBUG, 6957c478bd9Sstevel@tonic-gate "Attempting to retrieve utilization for:" + move 6967c478bd9Sstevel@tonic-gate .getMove().getTo()); 6977c478bd9Sstevel@tonic-gate utilization = monitor.getUtilization(move 6987c478bd9Sstevel@tonic-gate .getMove().getTo()); 6997c478bd9Sstevel@tonic-gate wdpInvolved = true; 7007c478bd9Sstevel@tonic-gate } 7017c478bd9Sstevel@tonic-gate 7027c478bd9Sstevel@tonic-gate /* 7037c478bd9Sstevel@tonic-gate * Unless a move can be vetoed (i.e. decision history 7047c478bd9Sstevel@tonic-gate * is effective and there are is a workload-dependent 7057c478bd9Sstevel@tonic-gate * involved), the move should alwways be applied. 7067c478bd9Sstevel@tonic-gate */ 7077c478bd9Sstevel@tonic-gate if (ignoreDH || !wdpInvolved || !dh.veto(move.getMove(), 7087c478bd9Sstevel@tonic-gate utilization)) { 7097c478bd9Sstevel@tonic-gate Poold.OPT_LOG.log(Severity.INFO, 7107c478bd9Sstevel@tonic-gate "applying move " + move.getMove()); 7117c478bd9Sstevel@tonic-gate move.getMove().apply(); 7127c478bd9Sstevel@tonic-gate ResourceMonitor mon = getMonitor().get(move.getMove(). 7137c478bd9Sstevel@tonic-gate getFrom()); 7147c478bd9Sstevel@tonic-gate mon.resetData("utilization"); 7157c478bd9Sstevel@tonic-gate mon = getMonitor().get(move.getMove().getTo()); 7167c478bd9Sstevel@tonic-gate mon.resetData("utilization"); 7177c478bd9Sstevel@tonic-gate try { 7187c478bd9Sstevel@tonic-gate Poold.OPT_LOG.log(Severity.DEBUG, 7197c478bd9Sstevel@tonic-gate "committing configuration"); 7207c478bd9Sstevel@tonic-gate conf.commit(0); 7217c478bd9Sstevel@tonic-gate try { 7227c478bd9Sstevel@tonic-gate if (move.getMove() instanceof 7237c478bd9Sstevel@tonic-gate ComponentMove) 7247c478bd9Sstevel@tonic-gate if (wdpInvolved) 7257c478bd9Sstevel@tonic-gate dh.recordProcessorMove( 7267c478bd9Sstevel@tonic-gate (ComponentMove)move 7277c478bd9Sstevel@tonic-gate .getMove(), 7287c478bd9Sstevel@tonic-gate utilization, 7297c478bd9Sstevel@tonic-gate monitor 7307c478bd9Sstevel@tonic-gate .getSampleCount()); 7317c478bd9Sstevel@tonic-gate else 7327c478bd9Sstevel@tonic-gate Poold.OPT_LOG.log( 7337c478bd9Sstevel@tonic-gate Severity.DEBUG, 7347c478bd9Sstevel@tonic-gate "decision not " + 7357c478bd9Sstevel@tonic-gate "recorded due to " + 7367c478bd9Sstevel@tonic-gate "lack of workload-" 7377c478bd9Sstevel@tonic-gate + "dependent " + 7387c478bd9Sstevel@tonic-gate "objectives"); 7397c478bd9Sstevel@tonic-gate } catch (Exception e) { 7407c478bd9Sstevel@tonic-gate Poold.OPT_LOG.log(Severity.INFO, 7417c478bd9Sstevel@tonic-gate "couldn't update " + 7427c478bd9Sstevel@tonic-gate "decision history (" + 7437c478bd9Sstevel@tonic-gate e.toString() + ")"); 7447c478bd9Sstevel@tonic-gate } 7457c478bd9Sstevel@tonic-gate madeMove = true; 7467c478bd9Sstevel@tonic-gate } catch (PoolsException pe) { 7477c478bd9Sstevel@tonic-gate conf.rollback(); 7487c478bd9Sstevel@tonic-gate Poold.OPT_LOG.log(Severity.INFO, 7497c478bd9Sstevel@tonic-gate "move failed, possibly due to a " + 7507c478bd9Sstevel@tonic-gate "bound process in a 1-processor " + 7517c478bd9Sstevel@tonic-gate "set"); 7527c478bd9Sstevel@tonic-gate } 7537c478bd9Sstevel@tonic-gate } else { 7547c478bd9Sstevel@tonic-gate /* 7557c478bd9Sstevel@tonic-gate * Move was vetoed. 7567c478bd9Sstevel@tonic-gate */ 7577c478bd9Sstevel@tonic-gate if (!ignoreDH && wdpInvolved) 7587c478bd9Sstevel@tonic-gate Poold.OPT_LOG.log(Severity.INFO, 7597c478bd9Sstevel@tonic-gate move.getMove() + " not applied due to " + 7607c478bd9Sstevel@tonic-gate "poor past results"); 7617c478bd9Sstevel@tonic-gate } 7627c478bd9Sstevel@tonic-gate return (madeMove); 7637c478bd9Sstevel@tonic-gate } 7647c478bd9Sstevel@tonic-gate 7657c478bd9Sstevel@tonic-gate /** 7667c478bd9Sstevel@tonic-gate * Add an objective based on the supplied expression to the 7677c478bd9Sstevel@tonic-gate * supplied set of objectives. 7687c478bd9Sstevel@tonic-gate * 7697c478bd9Sstevel@tonic-gate * @param oSet Set of objectives to be extended 7707c478bd9Sstevel@tonic-gate * @param type Type of element to which the expression is applied 7717c478bd9Sstevel@tonic-gate * @param exp Expression to be used in the objective 7727c478bd9Sstevel@tonic-gate * @throws IllegalArgumentException If a duplicate objective 7737c478bd9Sstevel@tonic-gate * is identified or an invalid expression is supplied for this 7747c478bd9Sstevel@tonic-gate * type of element 7757c478bd9Sstevel@tonic-gate */ addObjective(Set oSet, String type, Expression exp)7767c478bd9Sstevel@tonic-gate private void addObjective(Set oSet, String type, Expression exp) 7777c478bd9Sstevel@tonic-gate throws IllegalArgumentException 7787c478bd9Sstevel@tonic-gate { 7797c478bd9Sstevel@tonic-gate Objective o = AbstractObjective.getInstance(type, exp); 7807c478bd9Sstevel@tonic-gate Poold.CONF_LOG.log(Severity.DEBUG, "parsed objective " + o); 7817c478bd9Sstevel@tonic-gate /* 7827c478bd9Sstevel@tonic-gate * Check the set of objectives and find contradictions. 7837c478bd9Sstevel@tonic-gate */ 7847c478bd9Sstevel@tonic-gate Iterator itObjs = oSet.iterator(); 7857c478bd9Sstevel@tonic-gate while (itObjs.hasNext()) { 7867c478bd9Sstevel@tonic-gate Objective other = (Objective) itObjs.next(); 7877c478bd9Sstevel@tonic-gate if (o.getExpression().contradicts( 7887c478bd9Sstevel@tonic-gate other.getExpression())) 7897c478bd9Sstevel@tonic-gate throw new IllegalArgumentException( 7907c478bd9Sstevel@tonic-gate "contradictory objectives:" + other + 7917c478bd9Sstevel@tonic-gate ", " + o); 7927c478bd9Sstevel@tonic-gate } 793*55fea89dSDan Cross 7947c478bd9Sstevel@tonic-gate if (oSet.add(o) != true) 7957c478bd9Sstevel@tonic-gate throw new IllegalArgumentException( 7967c478bd9Sstevel@tonic-gate "duplicate objective:" + o); 7977c478bd9Sstevel@tonic-gate } 7987c478bd9Sstevel@tonic-gate 7997c478bd9Sstevel@tonic-gate /** 8007c478bd9Sstevel@tonic-gate * Return a list of resource sets prepared to receive 8017c478bd9Sstevel@tonic-gate * resources 8027c478bd9Sstevel@tonic-gate * 8037c478bd9Sstevel@tonic-gate * The list consists of all resource setss (of the supplied 8047c478bd9Sstevel@tonic-gate * type) whose size is < their max constraint. 8057c478bd9Sstevel@tonic-gate * 8067c478bd9Sstevel@tonic-gate * @param resList The list of all resource sets from which 8077c478bd9Sstevel@tonic-gate * recipients will be chosen 8087c478bd9Sstevel@tonic-gate * @throws PoolsException if there is an error manipulation 8097c478bd9Sstevel@tonic-gate * the pool resources 810*55fea89dSDan Cross */ getRecipients(List resList)8117c478bd9Sstevel@tonic-gate private List getRecipients(List resList) throws PoolsException 8127c478bd9Sstevel@tonic-gate { 8137c478bd9Sstevel@tonic-gate List recipientList = new ArrayList(); 8147c478bd9Sstevel@tonic-gate long size, max; 8157c478bd9Sstevel@tonic-gate for (int i = 0; i < resList.size(); i++) { 8167c478bd9Sstevel@tonic-gate Resource res; 8177c478bd9Sstevel@tonic-gate res = (Resource)resList.get(i); 8187c478bd9Sstevel@tonic-gate String type = res.getStringProperty("type"); 8197c478bd9Sstevel@tonic-gate size = res.getLongProperty(type+".size"); 8207c478bd9Sstevel@tonic-gate max = res.getLongProperty(type+".max"); 8217c478bd9Sstevel@tonic-gate if (size < max) 8227c478bd9Sstevel@tonic-gate recipientList.add(res); 8237c478bd9Sstevel@tonic-gate } 8247c478bd9Sstevel@tonic-gate return (recipientList); 8257c478bd9Sstevel@tonic-gate } 826*55fea89dSDan Cross 8277c478bd9Sstevel@tonic-gate /** 8287c478bd9Sstevel@tonic-gate * Return a list of resource sets prepared to donate resources 8297c478bd9Sstevel@tonic-gate * 8307c478bd9Sstevel@tonic-gate * The list consists of all resource sets (of the supplied 8317c478bd9Sstevel@tonic-gate * type) whose size (minus the number of pinned resources 8327c478bd9Sstevel@tonic-gate * where applicable) is > their min constraint. 8337c478bd9Sstevel@tonic-gate * 8347c478bd9Sstevel@tonic-gate * @param resList The list of all resource sets from which 8357c478bd9Sstevel@tonic-gate * recipients will be chosen 8367c478bd9Sstevel@tonic-gate * @throws PoolsException if there is an error manipulation 8377c478bd9Sstevel@tonic-gate * the pool resources 8387c478bd9Sstevel@tonic-gate */ getDonors(List resList)8397c478bd9Sstevel@tonic-gate private List getDonors(List resList) throws PoolsException 8407c478bd9Sstevel@tonic-gate { 8417c478bd9Sstevel@tonic-gate List donorList = new ArrayList(); 8427c478bd9Sstevel@tonic-gate long size, min; 8437c478bd9Sstevel@tonic-gate for (int i = 0; i < resList.size(); i++) { 8447c478bd9Sstevel@tonic-gate Value bValue; 8457c478bd9Sstevel@tonic-gate Resource res; 8467c478bd9Sstevel@tonic-gate List pinned; 8477c478bd9Sstevel@tonic-gate ArrayList valueList = new ArrayList(); 8487c478bd9Sstevel@tonic-gate 8497c478bd9Sstevel@tonic-gate res = (Resource)resList.get(i); 8507c478bd9Sstevel@tonic-gate String type = res.getStringProperty("type"); 8517c478bd9Sstevel@tonic-gate size = res.getLongProperty(type+".size"); 8527c478bd9Sstevel@tonic-gate bValue = new Value("cpu.pinned", true); 8537c478bd9Sstevel@tonic-gate valueList.add(bValue); 8547c478bd9Sstevel@tonic-gate pinned = res.getComponents(valueList); 8557c478bd9Sstevel@tonic-gate bValue.close(); 8567c478bd9Sstevel@tonic-gate min = res.getLongProperty(type+".min"); 8577c478bd9Sstevel@tonic-gate if (pinned.size() > min) 8587c478bd9Sstevel@tonic-gate size -= pinned.size() - min; 8597c478bd9Sstevel@tonic-gate if (size > min) 8607c478bd9Sstevel@tonic-gate donorList.add(res); 8617c478bd9Sstevel@tonic-gate } 8627c478bd9Sstevel@tonic-gate return (donorList); 8637c478bd9Sstevel@tonic-gate } 8647c478bd9Sstevel@tonic-gate 8657c478bd9Sstevel@tonic-gate /** 8667c478bd9Sstevel@tonic-gate * Return a list of Processors for the supplied resource. 8677c478bd9Sstevel@tonic-gate * 8687c478bd9Sstevel@tonic-gate * The list consists of all Processors (excluding the pinned 8697c478bd9Sstevel@tonic-gate * Processors) in the set. 8707c478bd9Sstevel@tonic-gate * 8717c478bd9Sstevel@tonic-gate * @param set The resource for which Processors should be found 8727c478bd9Sstevel@tonic-gate * @throws PoolsException if there is an error manipulation 8737c478bd9Sstevel@tonic-gate * the pool resources 8747c478bd9Sstevel@tonic-gate */ getProcessors(Resource set)8757c478bd9Sstevel@tonic-gate private List getProcessors(Resource set) throws PoolsException 8767c478bd9Sstevel@tonic-gate { 8777c478bd9Sstevel@tonic-gate Iterator it = set.getComponents(null).iterator(); 8787c478bd9Sstevel@tonic-gate List ret = new ArrayList(); 8797c478bd9Sstevel@tonic-gate 8807c478bd9Sstevel@tonic-gate while (it.hasNext()) { 8817c478bd9Sstevel@tonic-gate Component cpu = (Component) it.next(); 8827c478bd9Sstevel@tonic-gate try 8837c478bd9Sstevel@tonic-gate { 8847c478bd9Sstevel@tonic-gate if (cpu.getBoolProperty("cpu.pinned") == false) 8857c478bd9Sstevel@tonic-gate ret.add(cpu); 8867c478bd9Sstevel@tonic-gate } catch (PoolsException pe) 8877c478bd9Sstevel@tonic-gate { 8887c478bd9Sstevel@tonic-gate ret.add(cpu); 8897c478bd9Sstevel@tonic-gate } 8907c478bd9Sstevel@tonic-gate } 8917c478bd9Sstevel@tonic-gate return (ret); 8927c478bd9Sstevel@tonic-gate } 8937c478bd9Sstevel@tonic-gate 8947c478bd9Sstevel@tonic-gate /** 8957c478bd9Sstevel@tonic-gate * Return true if the solver is capable of working with 8967c478bd9Sstevel@tonic-gate * statistically valid data. 8977c478bd9Sstevel@tonic-gate */ isValid()8987c478bd9Sstevel@tonic-gate public boolean isValid() 8997c478bd9Sstevel@tonic-gate { 9007c478bd9Sstevel@tonic-gate return (monitor.isValid()); 9017c478bd9Sstevel@tonic-gate } 9027c478bd9Sstevel@tonic-gate 9037c478bd9Sstevel@tonic-gate /** 9047c478bd9Sstevel@tonic-gate * Return the monitor used by this solver. 9057c478bd9Sstevel@tonic-gate */ getMonitor()9067c478bd9Sstevel@tonic-gate public Monitor getMonitor() 9077c478bd9Sstevel@tonic-gate { 9087c478bd9Sstevel@tonic-gate return (monitor); 9097c478bd9Sstevel@tonic-gate } 9107c478bd9Sstevel@tonic-gate 9117c478bd9Sstevel@tonic-gate /** 9127c478bd9Sstevel@tonic-gate * Return the set of objectives associated with the supplied 9137c478bd9Sstevel@tonic-gate * element. 9147c478bd9Sstevel@tonic-gate * 9157c478bd9Sstevel@tonic-gate * @param elem Retrieve objectives for this element. 9167c478bd9Sstevel@tonic-gate */ getObjectives(Element elem)9177c478bd9Sstevel@tonic-gate public Set getObjectives(Element elem) 9187c478bd9Sstevel@tonic-gate { 9197c478bd9Sstevel@tonic-gate return ((Set)objMap.get(elem)); 9207c478bd9Sstevel@tonic-gate } 9217c478bd9Sstevel@tonic-gate 9227c478bd9Sstevel@tonic-gate /** 9237c478bd9Sstevel@tonic-gate * Holds details about the score of a proposed configuration 9247c478bd9Sstevel@tonic-gate * move. Each move must be scored so that they can ranked in 9257c478bd9Sstevel@tonic-gate * terms of increasing desirability 9267c478bd9Sstevel@tonic-gate */ 9277c478bd9Sstevel@tonic-gate static class ScoreMove implements Comparable { 9287c478bd9Sstevel@tonic-gate /** 9297c478bd9Sstevel@tonic-gate * The move which is being scored. 9307c478bd9Sstevel@tonic-gate */ 9317c478bd9Sstevel@tonic-gate private final Move m; 9327c478bd9Sstevel@tonic-gate 9337c478bd9Sstevel@tonic-gate /** 9347c478bd9Sstevel@tonic-gate * The score of the move. 9357c478bd9Sstevel@tonic-gate */ 9367c478bd9Sstevel@tonic-gate private final double score; 937*55fea89dSDan Cross 9387c478bd9Sstevel@tonic-gate /** 9397c478bd9Sstevel@tonic-gate * Score formatter. 9407c478bd9Sstevel@tonic-gate */ 9417c478bd9Sstevel@tonic-gate private static final DecimalFormat scoreFormat = 9427c478bd9Sstevel@tonic-gate new DecimalFormat("0.00"); 9437c478bd9Sstevel@tonic-gate 9447c478bd9Sstevel@tonic-gate /** 9457c478bd9Sstevel@tonic-gate * Constructor. 9467c478bd9Sstevel@tonic-gate * 9477c478bd9Sstevel@tonic-gate * @param m The move under consideration. 9487c478bd9Sstevel@tonic-gate * @param score The score of the move. 9497c478bd9Sstevel@tonic-gate */ ScoreMove(Move m, double score)9507c478bd9Sstevel@tonic-gate public ScoreMove(Move m, double score) 9517c478bd9Sstevel@tonic-gate { 9527c478bd9Sstevel@tonic-gate this.m = m; 9537c478bd9Sstevel@tonic-gate this.score = score; 9547c478bd9Sstevel@tonic-gate } 9557c478bd9Sstevel@tonic-gate compareTo(Object o)9567c478bd9Sstevel@tonic-gate public int compareTo(Object o) 9577c478bd9Sstevel@tonic-gate { 9587c478bd9Sstevel@tonic-gate ScoreMove other = (ScoreMove) o; 9597c478bd9Sstevel@tonic-gate 9607c478bd9Sstevel@tonic-gate return ((score < other.getScore()) ? -1 : 9617c478bd9Sstevel@tonic-gate (score > other.getScore()) ? 1 : 0); 9627c478bd9Sstevel@tonic-gate } 9637c478bd9Sstevel@tonic-gate toString()9647c478bd9Sstevel@tonic-gate public String toString() 9657c478bd9Sstevel@tonic-gate { 9667c478bd9Sstevel@tonic-gate return ("move (" + m + ") score " 9677c478bd9Sstevel@tonic-gate + scoreFormat.format(score)); 9687c478bd9Sstevel@tonic-gate } 9697c478bd9Sstevel@tonic-gate 9707c478bd9Sstevel@tonic-gate /** 9717c478bd9Sstevel@tonic-gate * Return the score. 9727c478bd9Sstevel@tonic-gate */ getScore()9737c478bd9Sstevel@tonic-gate double getScore() 9747c478bd9Sstevel@tonic-gate { 9757c478bd9Sstevel@tonic-gate return (score); 9767c478bd9Sstevel@tonic-gate } 9777c478bd9Sstevel@tonic-gate 9787c478bd9Sstevel@tonic-gate /** 9797c478bd9Sstevel@tonic-gate * Return the move. 9807c478bd9Sstevel@tonic-gate */ getMove()9817c478bd9Sstevel@tonic-gate Move getMove() 9827c478bd9Sstevel@tonic-gate { 9837c478bd9Sstevel@tonic-gate return (m); 9847c478bd9Sstevel@tonic-gate } 985*55fea89dSDan Cross } 9867c478bd9Sstevel@tonic-gate } 987