001    /*
002     * RootdMinMaxSingleCopySelector.java
003     *
004     * Created on April 28, 2003, 1:13 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.policy.copyselector;
025    
026    import gov.bnl.star.offline.scheduler.CatalogQuery;
027    import gov.bnl.star.offline.scheduler.catalog.QueryResult;
028    import gov.bnl.star.offline.scheduler.policy.FileAssignment;
029    import gov.bnl.star.offline.scheduler.policy.Location;
030    import java.util.*;
031    import org.apache.log4j.Logger;
032    
033    /**
034     *
035     * @author  Gabriele Carcassi
036     */
037    public class RootdMinMaxSingleCopySelector extends MinMaxSingleCopySelector {
038        static private Logger log = Logger.getLogger(RootdMinMaxSingleCopySelector.class.getName());
039        
040        public int selectCopy(QueryResult list, CatalogQuery query,
041            FileAssignment assignment) {
042                this.assignment = assignment;
043                int nFiles = super.selectCopy(list, query, assignment);
044                if (!assignment.isValid()) {
045                    log.debug("Using rootd local file distribution. Intital summary " + assignment.getSummary());
046                    moveLocalInvalid();
047                    log.debug("Using rootd local file distribution. End summary " + assignment.getSummary());
048                }
049                return nFiles;
050        }
051        
052        private List invalidLocations;
053        private FileAssignment assignment;
054        
055        private void moveLocalInvalid() {
056            // Get the list of invalid locations
057            invalidLocations = new ArrayList(assignment.getInvalidLocations());
058            log.debug("Invalid locations: " + invalidLocations);
059            
060            // Order them by number of surplus files
061            Collections.sort(invalidLocations, new Comparator() {
062                public int compare(Object obj1, Object obj2) {
063                    return Double.compare(assignment.needsLessFiles((Location)obj1), 
064                    assignment.needsLessFiles((Location)obj2));
065                }
066            });
067            log.debug("Invalid locations by dimension: " + invalidLocations);
068            
069            // Keeps moving files from the location with the least surplus to the
070            // the one with the most. This will end when there is 1 or 0 locations
071            // left
072            while(invalidLocations.size() > 1) {
073                Location mostFiles = (Location) invalidLocations.get(invalidLocations.size() - 1);
074                Location leastFiles = (Location) invalidLocations.get(0);
075                
076                moveNeededCopies(leastFiles, mostFiles);
077                log.debug("Invalid locations by dimension: " + invalidLocations);
078            }
079            
080            // Move the remaining files on the processes
081            // Making a copy of the locations because the set will be modified
082            // while iterating
083            Iterator iter = new ArrayList(assignment.getLocations()).iterator();
084            
085            if(invalidLocations.size() != 0){ //Bugfix: If all the files are removed from the last location, it will be destroyed and so no files need salvaging. (LBH)
086            
087                Location lastLocation = (Location) invalidLocations.get(0);
088                while ((assignment.getFiles(lastLocation) != null) && iter.hasNext()) {
089                    Location location = (Location) iter.next();
090                    if (location.equals(lastLocation)) continue;
091                    moveCopies(lastLocation, location);
092                    log.debug("Last invalid location: " + invalidLocations);
093                }
094            
095            }
096            
097        }
098    
099        /** Moves some or all the files from the source to fill the destination
100         * requirements.
101         */
102        private void moveNeededCopies(Location source, Location dest) {
103            log.debug("Moving needed files from " + source + " to " + dest);
104            int filesToMove = assignment.needsLessFiles(source);
105            int filesCanMove = assignment.needsMoreFiles(dest);
106            int nFiles = Math.min(filesToMove, filesCanMove);
107            
108            
109            moveCopies(source, dest, nFiles);
110        }
111    
112        /** Moves some or all the files from the source without changing the
113         * number of jobs on the destination.
114         */
115        private void moveCopies(Location source, Location dest) {
116            log.debug("Moving all files from " + source + " to " + dest);
117            int filesToMove = assignment.needsLessFiles(source);
118            int filesCanMove = assignment.canAdd(dest);
119            int nFiles = Math.min(filesToMove, filesCanMove);
120            
121            moveCopies(source, dest, nFiles);
122        }
123        
124        /** Copies some files from the source to the destination.
125         */
126        private void moveCopies(Location source, Location dest, int nFiles) {
127            log.debug("Moving " + nFiles + " files from " + source + " to " + dest);
128            List files = new ArrayList();
129            for (int n = 0; n < nFiles; n++) {
130                files.add(assignment.getFiles(source).get(n));
131            }
132            
133            assignment.removeAllPhysical(source, files);
134            assignment.addAllPhysical(dest, files);
135            if (assignment.getFiles(source) == null) invalidLocations.remove(source);
136            if (assignment.isValid(dest)) invalidLocations.remove(dest);
137        }
138        
139    }