001    /*
002     * STARCatalog.java
003     *
004     * Created on June 27, 2006, 7:33 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    
024    package gov.bnl.star.offline.scheduler.dataset.catalog;
025    
026    import gov.bnl.star.offline.scheduler.request.Request;
027    import java.io.BufferedReader;
028    import java.io.File;
029    import java.io.FileNotFoundException;
030    import java.io.FileOutputStream;
031    import java.io.InputStreamReader;
032    import java.io.PrintStream;
033    import java.io.Reader;
034    
035    import java.net.URL;
036    import java.util.*;
037    import java.util.logging.Level;
038    import org.apache.log4j.Logger;
039    
040    import gov.bnl.star.offline.scheduler.util.CSHCommandLineTask; //for testing 
041    import gov.bnl.star.offline.scheduler.CatalogQuery;
042    import gov.bnl.star.offline.scheduler.dataset.Dataset;
043    import gov.bnl.star.offline.scheduler.dataset.catalog.PrintDots;
044    
045    import java.io.IOException;
046    
047    /** The hard implementation of the SUMS catalog interface for the S.T.A.R. experiment.
048     *
049     * @author lbhajdu
050     */
051    public class STARCatalog {
052        
053        static private Logger log = Logger.getLogger(STARCatalog.class.getName());
054        private static Dataset dataset = null;
055        private static Request  request;
056        private static PrintStream datasetFileStream;
057        
058        PrintDots printDots;
059        
060        /** Creates a new instance of STARCatalog */
061        public STARCatalog() {
062    
063            
064        }
065        
066        
067        
068        public void fillDataset(Dataset dataset, Request request){
069            
070            this.dataset = dataset;
071            this.request = request;
072            
073            try {//Open the file we will be writting to
074                datasetFileStream = new PrintStream(new FileOutputStream(new File(dataset.getDatasetName()),true)); 
075            } catch (FileNotFoundException ex) {
076                ex.printStackTrace();
077            }  
078            
079            int nQueries = 0;
080    
081            for (int n = 0; n < request.getInputList().size(); n++) {
082                if (request.getInputList().get(n) instanceof CatalogQuery) {
083                    nQueries++;
084                }
085                else if (request.getInputList().get(n) instanceof URL){
086                    URLToEntryWriter((URL) request.getInputList().get(n));
087                } 
088            }
089    
090            CatalogQuery[] queries = new CatalogQuery[nQueries];
091    
092            for (int n = 0; n < queries.length; n++) {
093                //queries[n] = (CatalogQuery) request.getInputList().get(n);
094                getDataSet((CatalogQuery) request.getInputList().get(n));
095            }
096            
097            // Close to stream now that we have filled the dataset file
098            datasetFileStream.flush();
099            datasetFileStream.close();
100        
101        }
102        
103        
104        
105        
106    /*
107        public Dataset getDataSet(CatalogQuery[] querys, String name){
108            
109            
110            this.dataset = new Dataset(name);
111           
112            for(int i = 0; i < querys.length ; i++){
113                getDataSet(querys[i], name);
114            }
115            
116            return dataset;
117            
118        } 
119     */
120        
121        CatalogQuery currentQuery;
122        
123        private void getDataSet(CatalogQuery query){
124            
125            currentQuery = query;
126    
127            if(query.getNFiles() == null){
128                throw new RuntimeException("The query query.getNFiles() file limit was null");
129            } 
130            else if(query.getNFiles().intValue() == -1){ //If the user asks for alll the files
131                 executeQuery(query.getQuery(), null, null); 
132            }
133            else if(query.getNFiles().intValue() > 0){ //If the user set nfiles to a real value
134                executeQuery(query.getQuery(), null, query.getNFiles());
135            }
136            else{
137               throw new RuntimeException("Couldn't execute query the query.getNFiles() = " + query.getNFiles() + " is not valid value."); 
138            }
139            
140            /*
141            }
142            else{
143                 System.out.println("The limit was null");
144                 executeQuery(query.getQuery(), null, null);
145            }
146            */   
147               
148        } 
149        
150        
151    
152        
153            
154        private void executeQuery(String query, Integer start, Integer limit) {
155     
156            String inputOrder = "";
157            List inputOrderList = request.getInputOrder();
158            if(inputOrderList != null){
159                for(int i = 0; i != inputOrderList.size(); i++){
160                   String item = (String) inputOrderList.get(i); 
161                   boolean isAlreadyOnList = item.equals("fdid")||item.equals("storage")||item.equals("site")||item.equals("node")||item.equals("path")||item.equals("filename")||item.equals("events");
162                   if(!isAlreadyOnList) inputOrder = inputOrder + "," + item; 
163                }
164            }
165            
166           
167    
168            String commandLine = "get_file_list.pl -keys fdid,storage,site,node,path,filename,events" + inputOrder + " -cond " + query + "";
169            
170    
171            if (start != null) {
172                commandLine += (" -start " + start);
173            }
174    
175            if (limit != null) {
176                
177                commandLine += (" -limit " + limit);
178            } else {
179                commandLine += (" -limit 0");
180            }
181    
182            executeCommand(commandLine);
183    
184        }
185        
186        
187    
188        private void executeCommand(String commandLine) {
189            
190            log.info("Executing : " + commandLine);
191            System.out.print("Executing : " + commandLine);
192            int linesRecovered = 0; // Entries Recored 
193            
194            PrintDots printDots = new PrintDots();
195            printDots.start();
196            printDots.resumeDots();
197            
198            try {
199                 
200                String line;
201                Process p = Runtime.getRuntime().exec(commandLine);
202    
203                BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
204                while ((line = input.readLine()) != null) {
205                    
206                    if(line.matches("[0-9]*::[a-zA-Z]*::[a-zA-Z]*::[a-zA-Z0-9:.]*::[^:]*::[^:/]*::[0-9]*.*")){
207                        //Write everyting out to the data set
208                        datasetFileStream.println(line);
209                        linesRecovered ++;
210                        dataset.incrementSize();
211                    }else{
212                        printDots.pauseDots();
213                        System.out.println("Line does not match expected format, dropping line >>>> " + line);
214                        printDots.resumeDots();
215                    }
216                    
217                    
218                }
219                input.close();
220                printDots.pauseDots();
221    
222                if( p.waitFor() != 0){
223                    log.fatal("There was an error recovering the dataset (catalog error) :\n" + commandLine);
224                    throw new RuntimeException("There was an error recovering the dataset (catalog error) :\n" + commandLine); 
225                }
226                   
227            } catch (Exception err) {
228                err.printStackTrace();
229            }
230            
231            printDots.exitPrinting();
232            printDots.stop();
233            System.out.println("...." + linesRecovered +" Entries Recovered ");
234            
235            
236            currentQuery.setFilesReturned(linesRecovered);
237            
238         }   
239        
240        
241        
242        
243        
244        /**
245         *Convert a file url to an entry in the database 
246         *
247         *basic format example:
248         *
249         *    {FLN}::{STORAGE_SERVISE}::{SITE}::{HOST}::{PATH}::{FILE_NAME}::{NUMBER_OF_EVENTS}{other}
250         *    9404397::NFS::BNL::localhost::/star/data41/reco/productionMinBias/ReversedFullField/P05ic/2004/023::st_physics_adc_5023001_raw_1050014.MuDst.root::155
251         *    
252        */    
253        private void URLToEntryWriter(URL url){
254            
255            
256            //String baseEntry = "{FLN}::{STORAGE_SERVISE}::{SITE}::{HOST}::{PATH}::{FILE_NAME}::{NUMBER_OF_EVENTS}{OTHER}";
257            String baseEntry = "::{STORAGE_SERVISE}::::{HOST}::{PATH}::{FILE_NAME}::{NUMBER_OF_EVENTS}{OTHER}";
258    
259    
260            String host = url.getHost(); //if this is an ip address to format may come out funny
261            int port = url.getPort();
262            if(host != null){   //fill in the host block
263                host = host.trim();
264                if(! host.equals("")){ //if there is some kind of string for the host fill it in 
265                    if(port != -1) host = host + ":" + String.valueOf(port);
266                    baseEntry = baseEntry.replaceFirst("\\{HOST\\}",host);
267                    baseEntry = baseEntry.replaceFirst("\\{STORAGE_SERVISE\\}","local");
268                } else{
269                    baseEntry = baseEntry.replaceFirst("\\{HOST\\}","");    //if the host is "" leave it blank
270                    baseEntry = baseEntry.replaceFirst("\\{STORAGE_SERVISE\\}","NFS");
271                } 
272            } else{
273                baseEntry = baseEntry.replaceFirst("\\{HOST\\}","");        //if the host is null leave it blank
274                baseEntry = baseEntry.replaceFirst("\\{STORAGE_SERVISE\\}","NFS");
275            }
276            
277            
278            String path_filename = url.getFile();
279            String path = "";
280            String filename = "";
281            String events = "";
282            if(path_filename.matches(".*/[^/]*") ){ //if it is not just a file name, but also a path then it needs to be split 
283                path = path_filename.replaceAll("(.*)/[^/]*","$1");
284                filename = path_filename.replaceAll(".*/([^/]*)","$1");    
285            }
286            else{ //if it has no '/' in it hen it is just a file file name without a path
287               filename =  path_filename;
288            }
289            
290            if(filename.matches("^.* [0-9]*$")){ //if it end with the number of events
291                events = filename.replaceAll(".* ([0-9]*) *$","$1");
292                filename = filename.replaceAll("(.*) [0-9]* *$","$1");  
293                //System.out.println("name has events -->" + filename + "------->" + events); //checks the split in case there is ever a problem
294                
295            }
296            
297            
298            baseEntry = baseEntry.replaceAll("\\{PATH\\}", path);
299            baseEntry = baseEntry.replaceAll("\\{FILE_NAME\\}", filename);
300            baseEntry = baseEntry.replaceAll("\\{NUMBER_OF_EVENTS\\}", events);
301            
302            
303            if(request.getOutputList() != null){
304                if(request.getOutputList().size() != 0  ) baseEntry = baseEntry.replaceFirst("\\{OTHER\\}", "::");
305                else baseEntry = baseEntry.replaceFirst("\\{OTHER\\}", "");
306            } else baseEntry = baseEntry.replaceFirst("\\{OTHER\\}", "");
307            
308            
309            datasetFileStream.println(baseEntry);
310            
311            
312        }
313            
314            
315            
316            
317            
318            
319            /*
320            
321            System.out.println("bebug step 4");
322            
323            
324    
325            try {
326                
327                
328                //This code caused more problems then it has solved. The ,<,>,|| don"t work when it is used.
329                //This code replaces the code commented out below. The changes where needed because the code below does not allow the user to use " " in there code.  
330                //CSHCommandLineTask task = new CSHCommandLineTask(commandLine, true, 0);       
331                //task.execute(); //run the get_file_list.pl command 
332                //List result = parseOutput(task.getOutputReader(), attributeNames); //get the output back
333                
334                
335               System.out.println("Execute query: " + commandLine );
336              
337               Process proc = Runtime.getRuntime().exec("touch blax.tmp");
338               proc.waitFor();
339               proc = Runtime.getRuntime().exec(commandLine);
340               
341               // List result = parseOutput(new InputStreamReader(proc.getInputStream()), attributeNames);
342               proc.waitFor();
343                
344            } catch (Exception e) {
345                throw new RuntimeException("Couldn't execute query: " + commandLine + "\n" + e.getMessage());
346            }
347             
348            */
349        
350        
351        
352        
353        
354            
355        /*
356        public void resolveQuires(){
357            try {
358                
359                //how to get  catalog Q
360                Process proc = Runtime.getRuntime().exec("bla >> file");
361                
362            } catch (IOException ex) {
363                ex.printStackTrace();
364            }
365      
366            
367        }
368        */
369        
370        
371    
372        
373        
374    
375        
376         //public static List bla = new ArrayList();
377        
378        /** Parses the output of a get_file_list.pl command.
379         * @param in the input reader with the command output
380         * @return a list of PhysicalFiles
381         */
382     /*   
383        protected static List parseOutput(Reader in, List attributeNames) {
384            try {
385                List files = new ArrayList();
386                BufferedReader reader = new BufferedReader(in);
387                String line;
388    
389                while ((line = reader.readLine()) != null) {
390                    
391                    
392                    List tokens = parseOutputLine(line);
393                    PhysicalFile newFile = new PhysicalFile((String) tokens.get(0), (String) tokens.get(1),(String) tokens.get(2), (String) tokens.get(3), (String) tokens.get(4), null);
394                    for (int nAtt = 5; nAtt < tokens.size(); nAtt++) {
395                        int nName = nAtt - 5;
396                        String name = (String) attributeNames.get(nName);
397                        String token = (String) tokens.get(nAtt);
398                        // Hack to prevent garbage values: 0 for nEvents really means that
399                        // the value is not set
400                        if ("events".equals(name)) {
401                            if (!"0".equals(token)) {
402                                newFile.setAttribute(name, new Integer(token));
403                            }
404                        } else {
405                            newFile.setAttribute(name, new Integer(token));
406                        }
407                    }
408                    files.add(newFile);
409                }
410    
411                return files;
412            } catch (Exception e) {
413                log.error("Couldn't parse output of STAR catalog query", e);
414    
415                return new ArrayList();
416            }
417        }
418    
419        private static List parseOutputLine(String line) {
420            log.debug("Parsing : " + line);
421    
422            List tokens = new ArrayList();
423            StringTokenizer tokenizer = new StringTokenizer(line, ":");
424            int nToken = 0;
425            int parsedLength = 0;
426    
427            while (tokenizer.hasMoreTokens()) {
428                String token = tokenizer.nextToken();
429    
430                // If more spaces is detected, than a token was empty, and a position
431                // should be skipped.
432                if (nToken != 0) {
433                    int nWhiteSpaces = line.indexOf(token, parsedLength) -
434                        parsedLength;
435                    nToken += ((nWhiteSpaces / 2) - 1);
436                    parsedLength += nWhiteSpaces;
437                }
438    
439                // Saves the value of the token in the correct position
440                tokens.add(token);
441                parsedLength += token.length();
442                nToken++;
443            }
444    
445            return tokens;
446        }
447       */  
448        /*
449        private List executeQuery(String query, Integer start, Integer limit) {
450            if (CatalogManager.getAttrList() != null) {
451                return executeQuery(query, start, limit, CatalogManager.getAttrList());
452            } else {
453                return executeQuery(query, start, limit, new ArrayList());
454            }
455        }*/
456    
457    
458    /*
459        public void executeQuery(String query) {
460            executeQuery(query, null, null);
461        }
462    
463        public Iterator executeQuery(String query, int nExpectedResults) {
464            return new CatalogIterator(query, nExpectedResults);
465        }
466    
467        public Iterator executeQuery(String query, int start, int limit) {
468            return executeQuery(query, new Integer(start), new Integer(limit))
469                       .iterator();
470        }
471    
472        private class CatalogIterator implements Iterator {
473            private String query;
474            private List buffer;
475            private int nCurrentInBuffer;
476            private int nCurrentStart;
477            private int bufferSize;
478    
479            public CatalogIterator(String query, int bufferSize) {
480                this.query = query;
481                this.bufferSize = bufferSize;
482            }
483    
484            private void fetchData() {
485                buffer = executeQuery(query, new Integer(nCurrentStart),
486                        new Integer(bufferSize));
487                nCurrentInBuffer = 0;
488                nCurrentStart += bufferSize;
489            }
490    
491            public boolean hasNext() {
492                if (buffer == null) {
493                    fetchData();
494    
495                    boolean test = hasNext();
496    
497                    return test;
498                }
499    
500                if (buffer.size() == 0) {
501                    return false;
502                }
503    
504                if (nCurrentInBuffer < buffer.size()) {
505                    return true;
506                }
507    
508                fetchData();
509    
510                return hasNext();
511            }
512    
513            public Object next() {
514                if (hasNext()) {
515                    Object temp = buffer.get(nCurrentInBuffer);
516                    nCurrentInBuffer++;
517    
518                    return temp;
519                }
520    
521                throw new NoSuchElementException(
522                    "Catalog query has no more results.");
523            }
524    
525            public void remove() {
526                throw new UnsupportedOperationException(
527                    "Catalog query result don't support remove");
528            }
529        }
530        
531      */  
532    
533    
534        
535        
536        
537        
538    }