| /* |
| * Copyright 2009-2013 by The Regents of the University of California |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * you may obtain a copy of the License from |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package edu.uci.ics.pregelix.dataflow.context; |
| |
| import java.io.IOException; |
| import java.io.OutputStream; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import edu.uci.ics.hyracks.api.exceptions.HyracksDataException; |
| import edu.uci.ics.hyracks.api.lifecycle.ILifeCycleComponent; |
| import edu.uci.ics.hyracks.storage.am.common.api.IIndex; |
| import edu.uci.ics.hyracks.storage.am.common.api.IIndexLifecycleManager; |
| |
| public class NoBudgetIndexLifecycleManager implements IIndexLifecycleManager, ILifeCycleComponent { |
| |
| private final Map<Long, IndexInfo> indexInfos; |
| |
| public NoBudgetIndexLifecycleManager() { |
| this.indexInfos = new HashMap<Long, IndexInfo>(); |
| } |
| |
| @Override |
| public IIndex getIndex(long resourceID) { |
| IndexInfo info = indexInfos.get(resourceID); |
| return info == null ? null : info.index; |
| } |
| |
| @Override |
| public void register(long resourceID, IIndex index) throws HyracksDataException { |
| if (indexInfos.containsKey(resourceID)) { |
| throw new HyracksDataException("Index with resource ID " + resourceID + " already exists."); |
| } |
| |
| indexInfos.put(resourceID, new IndexInfo(index)); |
| } |
| |
| @Override |
| public void unregister(long resourceID) throws HyracksDataException { |
| IndexInfo info = indexInfos.remove(resourceID); |
| if (info == null) { |
| throw new HyracksDataException("Index with resource ID " + resourceID + " does not exist."); |
| } |
| |
| if (info.referenceCount != 0) { |
| indexInfos.put(resourceID, info); |
| throw new HyracksDataException("Cannot remove index while it is open."); |
| } |
| |
| if (info.isOpen) { |
| info.index.deactivate(); |
| } |
| } |
| |
| @Override |
| public void open(long resourceID) throws HyracksDataException { |
| IndexInfo info = indexInfos.get(resourceID); |
| if (info == null) { |
| throw new HyracksDataException("Failed to open index with resource ID " + resourceID |
| + " since it does not exist."); |
| } |
| |
| if (!info.isOpen) { |
| info.index.activate(); |
| info.isOpen = true; |
| } |
| info.touch(); |
| } |
| |
| @Override |
| public void close(long resourceID) { |
| indexInfos.get(resourceID).untouch(); |
| } |
| |
| private class IndexInfo implements Comparable<IndexInfo> { |
| private final IIndex index; |
| private int referenceCount; |
| private long lastAccess; |
| private boolean isOpen; |
| |
| public IndexInfo(IIndex index) { |
| this.index = index; |
| this.lastAccess = -1; |
| this.referenceCount = 0; |
| this.isOpen = false; |
| } |
| |
| public void touch() { |
| lastAccess = System.currentTimeMillis(); |
| referenceCount++; |
| } |
| |
| public void untouch() { |
| lastAccess = System.currentTimeMillis(); |
| referenceCount--; |
| } |
| |
| @Override |
| public int compareTo(IndexInfo i) { |
| // sort by (isOpen, referenceCount, lastAccess) ascending, where |
| // true < false |
| // |
| // Example sort order: |
| // ------------------- |
| // (F, 0, 70) <-- largest |
| // (F, 0, 60) |
| // (T, 10, 80) |
| // (T, 10, 70) |
| // (T, 9, 90) |
| // (T, 0, 100) <-- smallest |
| if (isOpen && !i.isOpen) { |
| return -1; |
| } else if (!isOpen && i.isOpen) { |
| return 1; |
| } else { |
| if (referenceCount < i.referenceCount) { |
| return -1; |
| } else if (referenceCount > i.referenceCount) { |
| return 1; |
| } else { |
| if (lastAccess < i.lastAccess) { |
| return -1; |
| } else if (lastAccess > i.lastAccess) { |
| return 1; |
| } else { |
| return 0; |
| } |
| } |
| } |
| |
| } |
| |
| public String toString() { |
| return "{index: " + index + ", isOpen: " + isOpen + ", refCount: " + referenceCount + ", lastAccess: " |
| + lastAccess + "}"; |
| } |
| } |
| |
| @Override |
| public List<IIndex> getOpenIndexes() { |
| List<IIndex> openIndexes = new ArrayList<IIndex>(); |
| for (IndexInfo i : indexInfos.values()) { |
| if (i.isOpen) { |
| openIndexes.add(i.index); |
| } |
| } |
| return openIndexes; |
| } |
| |
| @Override |
| public void start() { |
| } |
| |
| @Override |
| public void stop(boolean dumpState, OutputStream outputStream) throws IOException { |
| if (dumpState) { |
| dumpState(outputStream); |
| } |
| |
| for (IndexInfo i : indexInfos.values()) { |
| if (i.isOpen) { |
| i.index.deactivate(); |
| } |
| } |
| } |
| |
| public void dumpState(OutputStream os) throws IOException { |
| StringBuilder sb = new StringBuilder(); |
| |
| String headerFormat = "%-20s %-10s %-20s %-20s %-20s\n"; |
| String rowFormat = "%-20d %-10b %-20d %-20s %-20s\n"; |
| sb.append(String.format(headerFormat, "ResourceID", "Open", "Reference Count", "Last Access", "Index Name")); |
| IndexInfo ii; |
| for (Map.Entry<Long, IndexInfo> entry : indexInfos.entrySet()) { |
| ii = entry.getValue(); |
| sb.append(String.format(rowFormat, entry.getKey(), ii.isOpen, ii.referenceCount, ii.lastAccess, ii.index)); |
| } |
| os.write(sb.toString().getBytes()); |
| } |
| } |