001 /* 002 * MinMaxSingleCopySelector.java 003 * 004 * Created on April 4, 2003, 12:10 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.policy.copyselector; 024 025 import gov.bnl.star.offline.scheduler.CatalogQuery; 026 import gov.bnl.star.offline.scheduler.catalog.PhysicalFile; 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 031 import java.util.Iterator; 032 import java.util.List; 033 import java.util.Set; 034 import java.util.Collection; 035 import java.util.logging.Logger; 036 037 038 /** 039 * Select the copies trying to comply with the minFilesPerProcess parameter. 040 * The selection is split in five staged. 041 * <p/> 042 * 1) Assigns all the files that are on one machine only. There is no chioce to 043 * be made there. 044 * <p/> 045 * 2) Checks if, due to the min limit, some groups can't be split into valid jobs. 046 * In that case, looks for files that have one copy on that machines, and assigns 047 * them 048 * <p/> 049 * 3) Assigns all the files that have multiple copies. If preferStorage is used, 050 * it chooses a file on the given storage. Local copies as chosen randomly. 051 * <p/> 052 * 4) Checks if, due to the min limits, some groups can't be split correctly. 053 * In that cases, uses files on NFS to fill the minimum requirements. 054 * <p/> 055 * 5) Assigns the rest of the files on NFS. First, it fills to the max all the 056 * processes already created. Then it assigns the rest to processes that run on 057 * NFS 058 * 059 * @author Gabreile Carcassi & Pavel Jakl 060 */ 061 public class MinMaxSingleCopySelector implements CopySelector { 062 static private Logger log = Logger.getLogger(MinMaxSingleCopySelector.class.getName()); 063 064 public int selectCopy(QueryResult list, CatalogQuery query, 065 FileAssignment assignment) { 066 // Files that have only one copy on local disk are forced 067 int nFiles = assignFilesWithSingleCopy(list, assignment); 068 069 // Make the jobs valid by distributing part of the files with multiple copies 070 // It can distribute also the one with a copy on NFS 071 nFiles += fillMinMultipleCopyFiles(list, assignment); 072 073 // Distribute the remaining local files 074 // It distributes the files with a copy on NFS depending on the preferStorage 075 nFiles += assignFilesWithMultipleCopy(list, query, assignment); 076 077 // Make the jobs valid by distributing the files on NFS 078 nFiles += fillMinNFSFiles(list, assignment); 079 080 // Distribute the remaining NFS files 081 nFiles += assignNFSFiles(list, assignment); 082 083 return nFiles; 084 } 085 086 private int assignFilesWithSingleCopy(QueryResult list, 087 FileAssignment assignment) { 088 //PJ: add all files which are not located in NFS or HPSS 089 List singleCopy = list.getSinglePhysicalNoNFSorHPSS(); 090 // make sure that we can add something 091 if (singleCopy != null) { 092 assignment.addAllPhysical(singleCopy); 093 list.removeAllLogicalOfPhysical(singleCopy); 094 } 095 return singleCopy.size(); 096 } 097 098 private int fillMinMultipleCopyFiles(QueryResult list, 099 FileAssignment assignment) { 100 int nFiles = 0; 101 List badLocations = assignment.getInvalidLocations(); 102 if (badLocations != null) { 103 Iterator iter = badLocations.iterator(); 104 while (iter.hasNext()) { 105 Location location = (Location) iter.next(); 106 List files = list.getPhysicalOnLocation(location); 107 int nFilesToAssign = Math.min(assignment.needsMoreFiles(location), 108 files.size()); 109 List filesToAssign = files.subList(0, nFilesToAssign); 110 // dont add null files 111 if (filesToAssign != null) { 112 assignment.addAllPhysical(filesToAssign); 113 list.removeAllLogicalOfPhysical(filesToAssign); 114 nFiles += nFilesToAssign; 115 } 116 } 117 } 118 return nFiles; 119 } 120 121 private int assignFilesWithMultipleCopy(QueryResult list, CatalogQuery query, FileAssignment assignment) { 122 123 int nFiles = 0; 124 List physicalFilesToAssign; 125 126 // getPreferStorage and call current method 127 if ("NFS".equals(query.getPreferStorage())) { 128 // get all copies on NFS or local (instance of one file is choosen randomly) 129 physicalFilesToAssign = list.getRandomPhysicalOnNFSOrLocal(); 130 } else { 131 // get only files on local 132 physicalFilesToAssign = list.getRandomPhysicalLocal(); 133 } 134 135 if (physicalFilesToAssign != null) { 136 Iterator iter = physicalFilesToAssign.iterator(); 137 assignment.addAllPhysical(physicalFilesToAssign); 138 list.removeAllLogicalOfPhysical(physicalFilesToAssign); 139 nFiles+=physicalFilesToAssign.size(); 140 } 141 return nFiles; 142 } 143 144 private int fillMinNFSFiles(QueryResult list, FileAssignment assignment) { 145 int nFiles = 0; 146 List badLocations = assignment.getInvalidLocations(); 147 148 if (badLocations != null) { 149 Iterator iter = badLocations.iterator(); 150 List files = list.getPhysicalOnLocation(Location.getNFS()); 151 while (iter.hasNext()) { 152 Location location = (Location) iter.next(); 153 int nFilesToAssign = Math.min(assignment.needsMoreFiles(location), 154 files.size()); 155 List filesToAssign = files.subList(0, nFilesToAssign); 156 files = files.subList(nFilesToAssign, files.size()); 157 if (filesToAssign != null) { 158 assignment.addAllPhysical(location, filesToAssign); 159 list.removeAllLogicalOfPhysical(filesToAssign); 160 nFiles += nFilesToAssign; 161 } 162 } 163 } 164 return nFiles; 165 } 166 167 private int assignNFSFiles(QueryResult list, FileAssignment assignment) { 168 int nFiles = 0; 169 Set locations = assignment.getLocations(); 170 Iterator iter = locations.iterator(); 171 List files = list.getPhysicalOnLocation(Location.getNFS()); 172 if (locations != null) { 173 while (iter.hasNext()) { 174 Location location = (Location) iter.next(); 175 int nFilesToAssign = Math.min(assignment.canAdd(location), 176 files.size()); 177 List filesToAssign = files.subList(0, nFilesToAssign); 178 files = files.subList(nFilesToAssign, files.size()); 179 if (filesToAssign != null) { 180 assignment.addAllPhysical(location, filesToAssign); 181 list.removeAllLogicalOfPhysical(filesToAssign); 182 nFiles += nFilesToAssign; 183 } 184 } 185 if (files != null) { 186 assignment.addAllPhysical(files); 187 list.removeAllLogicalOfPhysical(files); 188 } 189 } 190 return files.size(); 191 } 192 193 }