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 */ 018package org.apache.hadoop.fs; 019 020import java.io.IOException; 021import java.util.List; 022import java.util.NoSuchElementException; 023 024/** 025 * A RemoteIterator that fetches elements in batches. 026 */ 027public 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}