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 */ 013 package org.vmutil.options; 014 015 import org.vmmagic.pragma.Uninterruptible; 016 import 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 */ 035 public abstract class OptionSet { 036 private Option head; 037 private Option tail; 038 private 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 */ 054 final String register(Option o, String name) { 055 if (tail == null) { 056 tail = head = o; 057 } else { 058 tail.setNext(o); 059 tail = o; 060 } 061 return computeKey(name); 062 } 063 064 /** 065 * Using the VM determined key, look up the corresponding option, 066 * or return <code>null</code> if an option can not be found. 067 * 068 * @param key The (unique) option key. 069 * @return The option, or <code>null</code>. 070 */ 071 public final Option getOption(String key) { 072 Option o = getFirst(); 073 while (o != null) { 074 if (o.getKey().equals(key)) { 075 return o; 076 } 077 o = o.getNext(); 078 } 079 return null; 080 } 081 082 /** 083 * Return the first option. This can be used with the getNext method to 084 * iterate through the options. 085 * 086 * @return The first option, or <code>null</code> if no options exist. 087 */ 088 public final Option getFirst() { 089 return head; 090 } 091 092 /** 093 * Log an option change 094 * @param o The option that changed 095 */ 096 public void logChange(Option o) { 097 if (loggingChanges) { 098 logString("Option Update: "); 099 log(o); 100 } 101 } 102 103 /** 104 * Log the option value in plain text. 105 * 106 * @param o The option to log. 107 */ 108 public void log(Option o) { 109 logString("Option '"); 110 logString(o.getKey()); 111 logString("' = "); 112 logValue(o, false); 113 logNewLine(); 114 } 115 116 /** 117 * Log the option value in XML. 118 * 119 * @param o The option to log. 120 */ 121 public void logXml(Option o) { 122 logString("<option name=\""); 123 logString(o.getKey()); 124 logString("\" value=\""); 125 logValue(o, true); 126 logString("\"/>"); 127 logNewLine(); 128 } 129 130 /** 131 * Log the option values in XML. 132 */ 133 public void logXml() { 134 logString("<options>"); 135 logNewLine(); 136 137 for(Option o = getFirst(); o != null; o = o.getNext()) { 138 logXml(o); 139 } 140 141 logString("</options>"); 142 logNewLine(); 143 } 144 145 /** 146 * Format and log an option value. 147 * 148 * @param o The option. 149 * @param forXml Is this part of XML output? 150 */ 151 protected abstract void logValue(Option o, boolean forXml); 152 153 /** 154 * Log a string. 155 */ 156 protected abstract void logString(String s); 157 158 /** 159 * Print a new line. 160 */ 161 protected abstract void logNewLine(); 162 163 /** 164 * Determine the VM specific key for a given option name. Option names are 165 * space delimited with capitalised words (e.g. "GC Verbosity Level"). 166 * 167 * @param name The option name. 168 * @return The VM specific key. 169 */ 170 protected abstract String computeKey(String name); 171 172 /** 173 * A non-fatal error occurred during the setting of an option. This method 174 * calls into the VM and shall not cause the system to stop. 175 * 176 * @param o The responsible option. 177 * @param message The message associated with the warning. 178 */ 179 protected abstract void warn(Option o, String message); 180 181 /** 182 * A fatal error occurred during the setting of an option. This method 183 * calls into the VM and is required to cause the system to stop. 184 * 185 * @param o The responsible option. 186 * @param message The error message associated with the failure. 187 */ 188 protected abstract void fail(Option o, String message); 189 190 /** 191 * Convert bytes into pages, rounding up if necessary. 192 * 193 * @param bytes The number of bytes. 194 * @return The corresponding number of pages. 195 */ 196 @Uninterruptible 197 protected abstract int bytesToPages(Extent bytes); 198 199 /** 200 * Convert from pages into bytes. 201 * @param pages the number of pages. 202 * @return The corresponding number of bytes. 203 */ 204 @Uninterruptible 205 protected abstract Extent pagesToBytes(int pages); 206 } 207