billoley opened a new issue, #2789:
URL: https://github.com/apache/accumulo/issues/2789

   Running version 1.9.3, observed an exception in the tserver logs from Tablet 
(now in TabletBase) --> "Underlying iterator yielded to a position that does 
not follow the last key returned: "  The exception didn't make sense because 
the last key returned (results.get(results.size() - 1)) was not in the seek 
range.  While writing a unit test to reproduce the issue, three separate issues 
in LookupTask were discovered.
   
   1) 
   
   In LookupTask.run(), session.queries is a HashMap (therefore not sorted), so 
when List<KVEntry> results = new ArrayList<>(); which contains the accumulated 
results for all subsequent KeyExtents gets passed to successive tablets, a 
yield could easily happen at a key that is before the last entry in results. 
("Underlying iterator yielded to a position that does not follow the last key 
returned: ")  LookupTask.run() should pass an empty List of results and add the 
returned value to the accumulated results.
   
   2) 
   
   LookupTask.run() uses an iterator (Iterator<Entry<KeyExtent,List<Range>>> 
iter = session.queries.entrySet().iterator()). If there are unfinished ranges 
on a tablet that is not closed, it calls session.queries.put(entry.getKey(), 
lookupResult.unfinishedRanges) which is modifying the container that is being 
iterated over inside iteration loop.  This results in a 
ConcurrentModificationException the next time iter.next() is called.
   
   3) 
   
   After #1 and #2 are corrected and the unfinished ranges are re-added to 
session.queries for a subsequent call, there are issues with 
partScan/partNextKey/partNextKeyInclusive
   
   a) These variables are not used until after the loop exits, so they will be 
overwritten any time there is a lookupResult with unfinishedRanges on a tablet 
that is not closed.
   
   b) Once we complete scanning the extent/ranges that were previously 
unfinished, the last one encoutered (is this desired) will then be in 
partScan/partNextKey/partNextKeyInclusive and fullscans.  Both are returned in 
the thrift response..... and this causes a NullPointerException in 
TabletServerBatchReaderIterator at line 554 in trackScanning()
   ListIterator<Range> iterator = unscanned.get(ke).listIterator()
   
   sequence of events:
   
   Map<KeyExtent,List<Range>> unscanned starts with all requested values
   remove all failures from unscanned
   remove all fullScans from unscanned
   then....
     if (scanResult.partScan != null) {
         KeyExtent ke = new KeyExtent(scanResult.partScan);
         Key nextKey = new Key(scanResult.partNextKey);
   
         ListIterator<Range> iterator = unscanned.get(ke).listIterator();
   
   NullPointerException because the scan on ke was completed and it is in 
fullScans, thus removed from the unscanned container
   
   
   Encountered in version 1.9.3, but these issues exist in much older versions 
up to the current.
   
   Reproduced by adding another test to YieldScannersIt that added splits to 
the table prior to adding data, ensuring that LookupTask received a request 
that included more than one KeyExtent -> List<Range> entries.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to