/** Choose a random key which can be fetched at the moment. Must not update any persistent data; * it's okay to update caches and other stuff that isn't stored to disk. If we fail etc we * should do it off-thread. * * FIXME make SplitFileFetcherGet per-segment, eliminate all this unnecessary complexity! * * @return The block number to be fetched, as an integer. */ public MyKey chooseRandomKey() { // FIXME this should probably use SimpleBlockChooser and hence use lowest-retry-count from each segment? synchronized(this) { if(finishedFetcher) return null; } // Generally segments are fairly well balanced, so we can usually pick a random segment // then a random key from it. // FIXME OPT SCALABILITY A simpler option might be just to have one SplitFileFetcherGet per // segment, like the old code. synchronized(randomSegmentIterator) { randomSegmentIterator.reset(random); while (randomSegmentIterator.hasNext()) { SplitFileFetcherSegmentStorage segment = randomSegmentIterator.next(); int ret = segment.chooseRandomKey(); if (ret != -1) { return new MyKey(ret, segment.segNo, this); } } } return null; }
keys.clear(); for(int i=0;i<dataBlocks+checkBlocks;i++) { int chosen = storage.chooseRandomKey(); assertTrue(chosen != -1); assertFalse(tried[chosen]); assertEquals(storage.chooseRandomKey(), -1);