[104] | 1 | package schedframe.scheduling; |
---|
| 2 | |
---|
| 3 | |
---|
| 4 | import java.util.ArrayList; |
---|
| 5 | import java.util.Collection; |
---|
| 6 | import java.util.Comparator; |
---|
| 7 | import java.util.Iterator; |
---|
| 8 | |
---|
| 9 | import org.apache.commons.logging.Log; |
---|
| 10 | import org.apache.commons.logging.LogFactory; |
---|
| 11 | |
---|
| 12 | import schedframe.scheduling.Reservation.Status; |
---|
| 13 | |
---|
| 14 | |
---|
| 15 | /** |
---|
| 16 | * A wrapper class used to store reservations. |
---|
| 17 | * Reservations on this list are ordered based on their start time |
---|
| 18 | * |
---|
| 19 | * @author Marcin Krystek |
---|
| 20 | * |
---|
| 21 | */ |
---|
| 22 | public class ReservationList extends ArrayList<Reservation> { |
---|
| 23 | |
---|
| 24 | protected static Log log = LogFactory.getLog(ReservationList.class); |
---|
| 25 | |
---|
| 26 | private static final long serialVersionUID = -7805575807997748584L; |
---|
| 27 | |
---|
| 28 | protected Comparator<Reservation> comparator; |
---|
| 29 | |
---|
| 30 | /** |
---|
| 31 | * Default constructor |
---|
| 32 | * |
---|
| 33 | */ |
---|
| 34 | public ReservationList() { |
---|
| 35 | super(); |
---|
| 36 | this.comparator = new ReservationComparator(); |
---|
| 37 | } |
---|
| 38 | |
---|
| 39 | public boolean add(Reservation r){ |
---|
| 40 | int i = findPositionFor(r); |
---|
| 41 | super.add(i, r); |
---|
| 42 | return true; |
---|
| 43 | } |
---|
| 44 | |
---|
| 45 | public Reservation get(Reservation r){ |
---|
| 46 | int size = size(); |
---|
| 47 | |
---|
| 48 | // find location estimation of the reservation r |
---|
| 49 | int idx = bisection(r.getStartMillis(), 0, size - 1); |
---|
| 50 | int i = idx; |
---|
| 51 | |
---|
| 52 | // go left and check if desired reservation is there |
---|
| 53 | Reservation res = get(i); |
---|
| 54 | // check only these reservations which start time is later |
---|
| 55 | // or equal to r start time |
---|
| 56 | while(i >= 0 && comparator.compare(res, r) >= 0){ |
---|
| 57 | if(res.equals(r)) |
---|
| 58 | return res; |
---|
| 59 | i--; |
---|
| 60 | res = get(i); |
---|
| 61 | } |
---|
| 62 | |
---|
| 63 | // if it is not there, then go to the right |
---|
| 64 | i = idx + 1; |
---|
| 65 | res = get(i); |
---|
| 66 | // check only these reservations which start time is earlier |
---|
| 67 | // or equal to r start time |
---|
| 68 | while(i < size && comparator.compare(res, r) <= 0){ |
---|
| 69 | if(res.equals(r)) |
---|
| 70 | return res; |
---|
| 71 | i++; |
---|
| 72 | res = get(i); |
---|
| 73 | } |
---|
| 74 | |
---|
| 75 | throw new IllegalArgumentException("There is no reservation " + r + " on the list"); |
---|
| 76 | } |
---|
| 77 | |
---|
| 78 | private int bisection(long startTime, int leftIdx, int rightIdx){ |
---|
| 79 | |
---|
| 80 | // 4 elements can be iterated by for loop |
---|
| 81 | if((rightIdx - leftIdx) < 4) |
---|
| 82 | return leftIdx; |
---|
| 83 | |
---|
| 84 | long first_startTime = get(leftIdx).getStartMillis(); |
---|
| 85 | long last_startTime = get(rightIdx).getStartMillis(); |
---|
| 86 | |
---|
| 87 | if(startTime < first_startTime){ |
---|
| 88 | int idx = leftIdx; |
---|
| 89 | while(idx > 0 && startTime < get(idx).getStartMillis()) |
---|
| 90 | idx--; |
---|
| 91 | return idx; |
---|
| 92 | } |
---|
| 93 | |
---|
| 94 | /* measure distance between new reservation start time and |
---|
| 95 | * both ends of the reservations list |
---|
| 96 | */ |
---|
| 97 | long delta_f = startTime - first_startTime; |
---|
| 98 | long delta_l = last_startTime - startTime; |
---|
| 99 | |
---|
| 100 | int middleIdx = leftIdx + ((rightIdx - leftIdx)/2); |
---|
| 101 | |
---|
| 102 | /* choose the correct half of the reservation list, |
---|
| 103 | * where "correct" means this one, which end is closer |
---|
| 104 | * to the new reservation start time |
---|
| 105 | */ |
---|
| 106 | if(delta_f < delta_l){ |
---|
| 107 | return bisection(startTime, leftIdx, middleIdx + 1); |
---|
| 108 | } else { |
---|
| 109 | return bisection(startTime, middleIdx - 1, rightIdx); |
---|
| 110 | } |
---|
| 111 | |
---|
| 112 | } |
---|
| 113 | |
---|
| 114 | protected int findPositionFor(Reservation r){ |
---|
| 115 | long startTime = r.getStartMillis(); |
---|
| 116 | boolean trace = false; |
---|
| 117 | |
---|
| 118 | int size = size(); |
---|
| 119 | int i = bisection(startTime, 0, size - 1); |
---|
| 120 | if(trace) |
---|
| 121 | log.debug("asdfgh: " + r.getStart() + " " + r.getId() + " " + i); |
---|
| 122 | while(i < size && comparator.compare(get(i), r) < 1){ |
---|
| 123 | i++; |
---|
| 124 | } |
---|
| 125 | |
---|
| 126 | if(trace) { |
---|
| 127 | log.debug("asdfgh: " + r.getId() + " " + i); |
---|
| 128 | for(int j = 0; j < size(); j++){ |
---|
| 129 | Reservation lr = get(j); |
---|
| 130 | log.debug("asdfgh: "+ j +".\t" + lr.getStart() + " id=" + lr.getId() + " jobId="+ lr.getJobId()); |
---|
| 131 | } |
---|
| 132 | } |
---|
| 133 | |
---|
| 134 | return i; |
---|
| 135 | } |
---|
| 136 | |
---|
| 137 | /** |
---|
| 138 | * Creates reservation for requested time resource allocation |
---|
| 139 | * @param key |
---|
| 140 | * @param resourceUsage |
---|
| 141 | * @return reservation |
---|
| 142 | */ |
---|
| 143 | public Reservation add(TimeResourceAllocation resourceUsage, Status status){ |
---|
| 144 | throw new RuntimeException("This method is not implemented"); |
---|
| 145 | } |
---|
| 146 | |
---|
| 147 | public void add(int i, Reservation r){ |
---|
| 148 | super.add(i, r); |
---|
| 149 | log.warn("Using this method may violate order of the reservations."); |
---|
| 150 | } |
---|
| 151 | |
---|
| 152 | public boolean addAll(Collection<? extends Reservation> c){ |
---|
| 153 | Iterator<? extends Reservation> itr = c.iterator(); |
---|
| 154 | while(itr.hasNext()){ |
---|
| 155 | this.add(itr.next()); |
---|
| 156 | } |
---|
| 157 | return true; |
---|
| 158 | } |
---|
| 159 | |
---|
| 160 | public boolean addAll(int i, Collection<? extends Reservation> c){ |
---|
| 161 | boolean ret = super.addAll(c); |
---|
| 162 | log.warn("Using this method may violate order of the reservations."); |
---|
| 163 | return ret; |
---|
| 164 | } |
---|
| 165 | |
---|
| 166 | |
---|
| 167 | public TimeResourceAllocation findInterval(TimeResourceAllocation timeSlot, long interval, int size) { |
---|
| 168 | throw new RuntimeException("Not implemented"); |
---|
| 169 | /*if (timeSlot.getEndTimeInMillis() <= timeSlot.getStartTimeInMillis() |
---|
| 170 | || interval == 0 || timeSlot.getDurationInMillis() < interval) |
---|
| 171 | return null; |
---|
| 172 | LinkedHashSet<Long> timestampsSet = createTimestampsSet(); |
---|
| 173 | TreeMap<Long, Integer> calendar = createCalendar(timestampsSet); |
---|
| 174 | if(calendar.size()==0){ |
---|
| 175 | return new TimeSlot(timeSlot.getStartTimeInMillis(), timeSlot.getStartTimeInMillis() + interval); |
---|
| 176 | } |
---|
| 177 | Date availableStartDate = getAvailableStartDate(calendar, timeSlot |
---|
| 178 | .getStartTime().getTime(), timeSlot.getEndTime().getTime(), |
---|
| 179 | interval, size); |
---|
| 180 | if (availableStartDate == null) |
---|
| 181 | return null; |
---|
| 182 | TimeSlot availableTimeSlot = new TimeSlot(availableStartDate.getTime(), |
---|
| 183 | availableStartDate.getTime() + interval); |
---|
| 184 | return availableTimeSlot; |
---|
| 185 | */ |
---|
| 186 | } |
---|
| 187 | |
---|
| 188 | protected class ReservationComparator implements Comparator<Reservation>{ |
---|
| 189 | |
---|
| 190 | public int compare(Reservation o1, Reservation o2) { |
---|
| 191 | long start1 = o1.getStart().getMillis(); |
---|
| 192 | long start2 = o2.getStart().getMillis(); |
---|
| 193 | |
---|
| 194 | if(start1 < start2) |
---|
| 195 | return -1; |
---|
| 196 | |
---|
| 197 | if(start1 > start2) |
---|
| 198 | return 1; |
---|
| 199 | |
---|
| 200 | return 0; |
---|
| 201 | } |
---|
| 202 | |
---|
| 203 | } |
---|
| 204 | } |
---|