@@ -190,4 +190,150 @@ public void testListLedgers()
190190 }
191191 }
192192
193+ /**
194+ * Unlike {@link #testListLedgers()} which only uses 10 ledgers within a single ZK range,
195+ * this test creates 10010 ledgers to verify cross-range iteration.
196+ *
197+ * <p>The HierarchicalLedgerManager stores ledgers in a ZK tree where each range (znode)
198+ * holds at most 10,000 leaf nodes. This limit is determined by the 4-digit last level of
199+ * the ledger ID path (0000-9999), as defined in:
200+ * <ul>
201+ * <li>{@code LegacyHierarchicalLedgerManager} — 2-4-4 split,
202+ * path: {root}/{level1}/{level2}/L{level3}</li>
203+ * <li>{@code LongHierarchicalLedgerManager} — 3-4-4-4-4 split,
204+ * path: {root}/{level0}/{level1}/{level2}/{level3}/L{level4}</li>
205+ * </ul>
206+ *
207+ * <p>By using numOfLedgers = 10010 (> 10000), ledgers will span across multiple ranges,
208+ * exercising the SyncLedgerIterator's ability to advance from one exhausted range to the
209+ * next via LedgerRangeIterator.
210+ */
211+ @ Test
212+ public void testListLedgersLargeScale ()
213+ throws Exception {
214+ // 10010 > 10000 (max ledgers per ZK range, determined by 4-digit last level 0000-9999),
215+ // ensuring cross-range iteration is covered
216+ int numOfLedgers = 10010 ;
217+
218+ ClientConfiguration conf = new ClientConfiguration ();
219+ conf .setMetadataServiceUri (zkUtil .getMetadataServiceUri ());
220+
221+ try (BookKeeper bkc = BookKeeper .newBuilder (conf ).build ();) {
222+ long [] ledgerIds = new long [numOfLedgers ];
223+ for (int i = 0 ; i < numOfLedgers ; i ++) {
224+
225+ try (WriteHandle l = bkc
226+ .newCreateLedgerOp ()
227+ .withDigestType (DigestType .CRC32 )
228+ .withPassword ("testPasswd" .getBytes ())
229+ .execute ()
230+ .get ();) {
231+ ledgerIds [i ] = l .getId ();
232+ }
233+ }
234+
235+ try (ListLedgersResult result = FutureUtils .result (bkc .newListLedgersOp ().execute ());) {
236+ int count = 0 ;
237+
238+ for (long ledgerId : result .toIterable ()) {
239+ assertEquals (ledgerIds [count ++], ledgerId );
240+ }
241+
242+ assertEquals (numOfLedgers , count , "Unexpected ledgers count" );
243+ try {
244+ result .iterator ();
245+ fail ("Should thrown error" );
246+ } catch (IllegalStateException e ) {
247+ // ok
248+ }
249+ try {
250+ result .toIterable ();
251+ fail ("Should thrown error" );
252+ } catch (IllegalStateException e ) {
253+ // ok
254+ }
255+ }
256+
257+ try (ListLedgersResult result = FutureUtils .result (bkc .newListLedgersOp ().execute ());) {
258+ int count = 0 ;
259+
260+ for (LedgersIterator iterator = result .iterator (); iterator .hasNext ();) {
261+ long ledgerId = iterator .next ();
262+ assertEquals (ledgerIds [count ++], ledgerId );
263+
264+ }
265+ assertEquals (numOfLedgers , count , "Unexpected ledgers count" );
266+ try {
267+ result .iterator ();
268+ fail ("Should thrown error" );
269+ } catch (IllegalStateException e ) {
270+ // ok
271+ }
272+ try {
273+ result .toIterable ();
274+ fail ("Should thrown error" );
275+ } catch (IllegalStateException e ) {
276+ // ok
277+ }
278+ }
279+ }
280+
281+ // check closed
282+ {
283+ ListLedgersResult result = FutureUtils .result (bkc .newListLedgersOp ().execute ());
284+ result .close ();
285+ try {
286+ result .toIterable ();
287+ fail ("Should thrown error" );
288+ } catch (IllegalStateException e ) {
289+ // ok
290+ }
291+
292+ try {
293+ result .iterator ();
294+ fail ("Should thrown error" );
295+ } catch (IllegalStateException e ) {
296+ // ok
297+ }
298+ }
299+
300+ { // iterator
301+ ListLedgersResult result = FutureUtils .result (bkc .newListLedgersOp ().execute ());
302+ LedgersIterator it = result .iterator ();
303+ result .close ();
304+ try {
305+ it .hasNext ();
306+ fail ("Should thrown error" );
307+ } catch (IllegalStateException e ) {
308+ // ok
309+ }
310+
311+ try {
312+ it .next ();
313+ fail ("Should thrown error" );
314+ } catch (IllegalStateException e ) {
315+ // ok
316+ }
317+ }
318+
319+ { // iterable
320+ ListLedgersResult result = FutureUtils .result (bkc .newListLedgersOp ().execute ());
321+ Iterator <Long > it = result .toIterable ().iterator ();
322+ result .close ();
323+ try {
324+ it .hasNext ();
325+ fail ("Should thrown error" );
326+ } catch (IllegalStateException e ) {
327+ // ok
328+ }
329+
330+ try {
331+ it .next ();
332+ fail ("Should thrown error" );
333+ } catch (IllegalStateException e ) {
334+ // ok
335+ }
336+ }
337+ }
338+
193339}
0 commit comments