001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 package org.apache.hadoop.fs;
019
020 import java.io.IOException;
021 import java.util.List;
022 import java.util.NoSuchElementException;
023
024 /**
025 * A RemoteIterator that fetches elements in batches.
026 */
027 public abstract class BatchedRemoteIterator<K, E> implements RemoteIterator<E> {
028 public interface BatchedEntries<E> {
029 public E get(int i);
030 public int size();
031 public boolean hasMore();
032 }
033
034 public static class BatchedListEntries<E> implements BatchedEntries<E> {
035 private final List<E> entries;
036 private final boolean hasMore;
037
038 public BatchedListEntries(List<E> entries, boolean hasMore) {
039 this.entries = entries;
040 this.hasMore = hasMore;
041 }
042
043 public E get(int i) {
044 return entries.get(i);
045 }
046
047 public int size() {
048 return entries.size();
049 }
050
051 public boolean hasMore() {
052 return hasMore;
053 }
054 }
055
056 private K prevKey;
057 private BatchedEntries<E> entries;
058 private int idx;
059
060 public BatchedRemoteIterator(K prevKey) {
061 this.prevKey = prevKey;
062 this.entries = null;
063 this.idx = -1;
064 }
065
066 /**
067 * Perform the actual remote request.
068 *
069 * @param prevKey The key to send.
070 * @return A list of replies.
071 */
072 public abstract BatchedEntries<E> makeRequest(K prevKey) throws IOException;
073
074 private void makeRequest() throws IOException {
075 idx = 0;
076 entries = null;
077 entries = makeRequest(prevKey);
078 if (entries.size() == 0) {
079 entries = null;
080 }
081 }
082
083 private void makeRequestIfNeeded() throws IOException {
084 if (idx == -1) {
085 makeRequest();
086 } else if ((entries != null) && (idx >= entries.size())) {
087 if (!entries.hasMore()) {
088 // Last time, we got fewer entries than requested.
089 // So we should be at the end.
090 entries = null;
091 } else {
092 makeRequest();
093 }
094 }
095 }
096
097 @Override
098 public boolean hasNext() throws IOException {
099 makeRequestIfNeeded();
100 return (entries != null);
101 }
102
103 /**
104 * Return the next list key associated with an element.
105 */
106 public abstract K elementToPrevKey(E element);
107
108 @Override
109 public E next() throws IOException {
110 makeRequestIfNeeded();
111 if (entries == null) {
112 throw new NoSuchElementException();
113 }
114 E entry = entries.get(idx++);
115 prevKey = elementToPrevKey(entry);
116 return entry;
117 }
118 }