001/* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013package org.vmutil.options; 014 015import org.vmmagic.pragma.Uninterruptible; 016import org.vmmagic.unboxed.*; 017 018/** 019 * The abstract base class for all option sets. 020 * <p> 021 * Concrete instantiations of this class include logic. 022 * <p> 023 * All options within the system should have a unique name. No 024 * two options shall have a name that is the same when a case 025 * insensitive comparison between the names with spaces removed 026 * is performed. Only basic alphanumeric characters and spaces 027 * are allowed. 028 * <p> 029 * The VM is required to provide a one way mapping function that 030 * takes the name and creates a VM style name, such as mapping 031 * "No Finalizer" to noFinalizer. The VM may not remove any letters 032 * when performing this mapping but may remove spaces and change 033 * the case of any character. 034 */ 035public abstract class OptionSet { 036 private Option head; 037 private Option tail; 038 private final boolean loggingChanges; 039 040 /** 041 * Initialize the option set so that options can be created. 042 */ 043 protected OptionSet() { 044 head = null; 045 tail = null; 046 loggingChanges = false; 047 } 048 049 /** 050 * Register the option to this set, computing its key in the process. 051 * 052 * @param o The option to register. 053 * @param name the option's name 054 * @return the computed key for the option 055 */ 056 final String register(Option o, String name) { 057 if (tail == null) { 058 tail = head = o; 059 } else { 060 tail.setNext(o); 061 tail = o; 062 } 063 return computeKey(name); 064 } 065 066 /** 067 * Using the VM determined key, look up the corresponding option, 068 * or return <code>null</code> if an option can not be found. 069 * 070 * @param key The (unique) option key. 071 * @return The option, or <code>null</code>. 072 */ 073 public final Option getOption(String key) { 074 Option o = getFirst(); 075 while (o != null) { 076 if (o.getKey().equals(key)) { 077 return o; 078 } 079 o = o.getNext(); 080 } 081 return null; 082 } 083 084 /** 085 * Return the first option. This can be used with the getNext method to 086 * iterate through the options. 087 * 088 * @return The first option, or <code>null</code> if no options exist. 089 */ 090 public final Option getFirst() { 091 return head; 092 } 093 094 /** 095 * Log an option change 096 * @param o The option that changed 097 */ 098 public void logChange(Option o) { 099 if (loggingChanges) { 100 logString("Option Update: "); 101 log(o); 102 } 103 } 104 105 /** 106 * Log the option value in plain text. 107 * 108 * @param o The option to log. 109 */ 110 public void log(Option o) { 111 logString("Option '"); 112 logString(o.getKey()); 113 logString("' = "); 114 logValue(o, false); 115 logNewLine(); 116 } 117 118 /** 119 * Log the option value in XML. 120 * 121 * @param o The option to log. 122 */ 123 public void logXml(Option o) { 124 logString("<option name=\""); 125 logString(o.getKey()); 126 logString("\" value=\""); 127 logValue(o, true); 128 logString("\"/>"); 129 logNewLine(); 130 } 131 132 /** 133 * Log the option values in XML. 134 */ 135 public void logXml() { 136 logString("<options>"); 137 logNewLine(); 138 139 for (Option o = getFirst(); o != null; o = o.getNext()) { 140 logXml(o); 141 } 142 143 logString("</options>"); 144 logNewLine(); 145 } 146 147 /** 148 * Format and log an option value. 149 * 150 * @param o The option. 151 * @param forXml Is this part of XML output? 152 */ 153 protected abstract void logValue(Option o, boolean forXml); 154 155 /** 156 * Log a string. 157 * 158 * @param s the string to log 159 */ 160 protected abstract void logString(String s); 161 162 /** 163 * Print a new line. 164 */ 165 protected abstract void logNewLine(); 166 167 /** 168 * Determine the VM specific key for a given option name. Option names are 169 * space delimited with capitalised words (e.g. "GC Verbosity Level"). 170 * 171 * @param name The option name. 172 * @return The VM specific key. 173 */ 174 protected abstract String computeKey(String name); 175 176 /** 177 * A non-fatal error occurred during the setting of an option. This method 178 * calls into the VM and shall not cause the system to stop. 179 * 180 * @param o The responsible option. 181 * @param message The message associated with the warning. 182 */ 183 protected abstract void warn(Option o, String message); 184 185 /** 186 * A fatal error occurred during the setting of an option. This method 187 * calls into the VM and is required to cause the system to stop. 188 * 189 * @param o The responsible option. 190 * @param message The error message associated with the failure. 191 */ 192 protected abstract void fail(Option o, String message); 193 194 /** 195 * Convert bytes into pages, rounding up if necessary. 196 * 197 * @param bytes The number of bytes. 198 * @return The corresponding number of pages. 199 */ 200 @Uninterruptible 201 protected abstract int bytesToPages(Extent bytes); 202 203 /** 204 * Convert from pages into bytes. 205 * @param pages the number of pages. 206 * @return The corresponding number of bytes. 207 */ 208 @Uninterruptible 209 protected abstract Extent pagesToBytes(int pages); 210} 211