001 /* 002 * $RCSfile: CatalogQuery.java,v $ 003 * 004 * Created on August 2, 2002, 2:47 PM 005 * 006 * This file is part of the STAR Scheduler. 007 * Copyright (c) 2002-2006 STAR Collaboration - Brookhaven National Laboratory 008 * 009 * STAR Scheduler is free software; you can redistribute it and/or modify 010 * it under the terms of the GNU General Public License as published by 011 * the Free Software Foundation; either version 2 of the License, or 012 * (at your option) any later version. 013 * 014 * STAR Scheduler is distributed in the hope that it will be useful, 015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 017 * GNU General Public License for more details. 018 * 019 * You should have received a copy of the GNU General Public License 020 * along with STAR Scheduler; if not, write to the Free Software 021 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 022 */ 023 package gov.bnl.star.offline.scheduler; 024 025 import java.net.URI; 026 import java.util.*; 027 028 import java.util.logging.Level; 029 import org.apache.log4j.Logger; 030 031 032 /** Encapsulate a query to the file catalog. This class is a wrapper around a 033 * URI that describes a file catalog query. The syntax of the URI is: 034 * <p> 035 * catalog:catalogName?query 036 * <p> 037 * catalogName is the name that identifies the catalog that should resolve the 038 * query. If can be directly a machine name, or a more abstract name that can 039 * be resolved to a specific machine at a later time. 040 * <p> 041 * query is the actual query to pass to the catalog. The syntax of the query 042 * is the one defined by the perl interface. 043 * <p> 044 * Different counting methods can be used. By counting methods, we mean the method 045 * used by the query resolver to decide how many and which records to return. Right 046 * now, two methods are supported: 047 * <p> 048 * START-LIMIT, which maps directly to the SQL START LIMIT definition. One can 049 * think the result returned as a view on the total result. Basically, only the 050 * records between start and start+limit are returned. By executing the same 051 * query with a different start, one can view all the result a chunk at a time. 052 * <p> 053 * NFILES, which returns a given number of files (that is of records) in no 054 * particular order. The query resolver is allowed to return whatever files 055 * it decides. This allows the query resolver to perform optimizations. 056 * 057 * @author Gabriele Carcassi 058 * @version $Revision: 1.28 $ $Date: 2006/11/21 00:41:32 $ 059 */ 060 public class CatalogQuery implements java.io.Serializable{ 061 static private Logger log = Logger.getLogger(CatalogQuery.class.getName()); 062 private static final int DEFAULT_N_FILES = 100; 063 private static final String COUNTING_ERROR_MESSAGE = "Can't mix start/limit with nFiles"; 064 065 /** No method for determine how long the result should be was specified. */ 066 public static final int NO_COUNTING = 0; 067 068 /** The method to specify how many records to return is the SQL START and 069 * LIMIT model. */ 070 public static final int START_LIMIT_COUNTING = 1; 071 072 /** The method to specify how many records to return is by returning 073 * the specified number of valid records. Any records in any order can be 074 * returned. */ 075 public static final int NFILES_COUNTING = 2; 076 private String uri; 077 private String host; 078 private String query; 079 private String preferStorage; 080 private Integer limit; 081 private Integer start; 082 private boolean singleCopy; 083 private Integer nFiles; 084 085 086 087 088 private int eventsReturned = 0; 089 public int getEventsReturned(){ return eventsReturned; } 090 public void setEventsReturned(int eventsReturned){ this.eventsReturned = eventsReturned; } 091 public void addToEventsReturned(int eventsReturned){ this.eventsReturned += eventsReturned; } 092 093 private int filesReturned = 0; 094 public int getFilesReturned(){ return filesReturned; } 095 public void setFilesReturned(int filesReturned){ this.filesReturned = filesReturned; } 096 public void filesReturned(){ this.filesReturned ++; } 097 098 099 100 101 /** Holds value of property attributes. */ 102 private List attributes; 103 104 /** Creates a query to the file catalog. The query is specified by a URI in this 105 * form: <CODE>catalog:catalogName?query</CODE> 106 * <p> 107 * <CODE>catalogName</CODE> defines which catalog to look. For example, 108 * star.bnl.gov specifies the STAR catalog. 109 * <p> 110 * <CODE>query</CODE> is the query that will be used to search for the entry. The 111 * exact syntax is specified by the catalog itself. For STAR, it 112 * is a series of comma separated assignments between keywords and values. 113 * @param uri specifies the full uri: ex. <CODE>catalog:star.bnl.gov:collision=AuAu200,storage=local</CODE> 114 */ 115 public CatalogQuery(String uri) { 116 try { 117 this.uri = uri; 118 parseUri(); 119 120 return; 121 } catch (Exception e) { 122 log.fatal("Couldn't parse catalog query", e); 123 } 124 125 throw new RuntimeException("The catalog query " + uri + 126 " is malformed"); 127 } 128 129 /** Creates a copy of a given query. The new query has the same URI and 130 * optional parameters, except the counting method, which is not set. 131 * @param query the query to be copied 132 */ 133 public CatalogQuery(CatalogQuery query) { 134 uri = query.uri; 135 parseUri(); 136 singleCopy = query.singleCopy; 137 } 138 139 /*Not used*/ 140 public CatalogQuery(){} 141 142 private void parseUri() { 143 String schemeDependant = uri.substring(uri.indexOf(':')+1); 144 host = schemeDependant.substring(0, schemeDependant.indexOf('?')); 145 query = schemeDependant.substring(schemeDependant.indexOf('?') + 1); 146 } 147 148 /** Returns the catalog to which the query should be sent. 149 * <p> 150 * This method is provided for 151 * forward compatibility and is not actually used 152 * @return the name of a machine 153 */ 154 public String getCatalogName() { 155 return host; 156 } 157 158 /** Returns the query to be passed to the file catalog. 159 * @return the query as specified by the file catalog. 160 */ 161 public String getQuery() { 162 return query; 163 } 164 165 166 /** Returns the number of records this query should return. 167 * @return number of files the query will return 168 */ 169 public Integer getLimit() { 170 return this.limit; 171 } 172 173 /** Sets the number of records this query should return. 174 * @param limit number of files returned by the query 175 */ 176 public void setLimit(Integer limit) { 177 178 if (limit == null) { 179 this.limit = null; 180 } 181 182 if ((getCountingType() != NO_COUNTING) && 183 (getCountingType() != START_LIMIT_COUNTING)) { 184 throw new RuntimeException(COUNTING_ERROR_MESSAGE); 185 } 186 187 this.limit = limit; 188 } 189 190 /** Returns the first element to be returned. In conjuction with limit you can 191 * scroll all the list. 192 * @return row of the first element to be returned 193 */ 194 public Integer getStart() { 195 return this.start; 196 } 197 198 /** Sets the first element to be returned. In conjuction with limit you can 199 * scroll all the list. 200 * @param start row of the first element to be returned 201 */ 202 public void setStart(Integer start) { 203 if (start == null) { 204 this.start = null; 205 } 206 207 if ((getCountingType() != NO_COUNTING) && 208 (getCountingType() != START_LIMIT_COUNTING)) { 209 throw new RuntimeException(COUNTING_ERROR_MESSAGE); 210 } 211 212 this.start = start; 213 } 214 215 /** Tells whether single copy or multiple copies for the same file should be 216 * returned. 217 * @return true if the query should return only one copy for each file in the catalog 218 */ 219 public boolean isSingleCopy() { 220 return this.singleCopy; 221 } 222 223 /** Tells which copy is preferred in case more than one copy for the same 224 * file is found. 225 * @return a String representing a storage (es. "local", "NFS", ... ) 226 */ 227 public String getPreferStorage() { 228 if (preferStorage == null) { 229 if (getNFiles().intValue() <= DEFAULT_N_FILES) return "NFS"; 230 else return "local"; 231 } 232 return this.preferStorage; 233 } 234 235 /** Sets which copy is preferred in case of more than one copy for the same 236 * file is found. 237 * @param preferStorage a String representing a storage (es. "local", "NFS", ... ) 238 */ 239 public void setPreferStorage(String preferStorage) { 240 this.preferStorage = preferStorage; 241 } 242 243 /** Sets whether single copy or multiple copies for the same file should be 244 * returned. 245 * @param singleCopy true if the query should return only one copy for each file in the catalog 246 */ 247 public void setSingleCopy(boolean singleCopy) { 248 this.singleCopy = singleCopy; 249 } 250 251 /** Returns the number of files the query should return. The files returned 252 * by the query if this counting method is used. 253 * @return the number of files returned by the query, or null if this 254 * counting method is not used 255 * 256 */ 257 public Integer getNFiles() { 258 259 if (getCountingType() == NO_COUNTING) { 260 return new Integer(DEFAULT_N_FILES); 261 } 262 263 return this.nFiles; 264 } 265 266 /** Sets the number of files the query should return. Files are returned in 267 * no particular order. 268 * @param nFiles the number of files to be returned by the query. 269 * 270 */ 271 public void setNFiles(Integer nFiles) { 272 273 if (nFiles == null) { 274 this.nFiles = null; 275 } 276 277 if ((getCountingType() != NO_COUNTING) && 278 (getCountingType() != NFILES_COUNTING)) { 279 throw new RuntimeException(COUNTING_ERROR_MESSAGE); 280 } 281 282 this.nFiles = nFiles; 283 } 284 285 /** Returns the counting method used to decide how many records the query 286 * should return. 287 * @return NO_COUNTING, START_LIMIT_COUNTING or NFILES_COUNTING depending on the counting 288 * method defined on the query 289 */ 290 public int getCountingType() { 291 if (nFiles != null) { 292 return NFILES_COUNTING; 293 } 294 295 if ((limit != null) || (start != null)) { 296 return START_LIMIT_COUNTING; 297 } 298 299 return NO_COUNTING; 300 } 301 302 /** Getter for property attributes. 303 * @return Value of property attributes. 304 * 305 */ 306 public List getAttributes() { 307 return this.attributes; 308 } 309 310 /** Setter for property attributes. 311 * @param attributes New value of property attributes. 312 * 313 */ 314 public void setAttributes(List attributes) { 315 this.attributes = attributes; 316 } 317 318 319 320 }