[ https://issues.apache.org/jira/browse/ASTERIXDB-2204?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16312268#comment-16312268 ]
ASF subversion and git services commented on ASTERIXDB-2204: ------------------------------------------------------------ Commit 08dc8597e2c9bcbf133250487c71b82d53fd1224 in asterixdb's branch refs/heads/master from [~alamoudi] [ https://git-wip-us.apache.org/repos/asf?p=asterixdb.git;h=08dc859 ] [ASTERIXDB-2204][STO] Fix the IIndexCursor interface - user model changes: no - storage format changes: no - interface changes: yes - replace IIndexCursor.reset with close - replace IIndexCursor.close with destroy Details: - This change is the first step towards fixing the behavior of implementors/callers of the IIndexCursor interface - In this change, we simply rename the reset -> close and close -> destroy and we write down the javadocs explaining the semantics of the interface. - LSM Index Cursors don't implements ITreeIndexCursor anymore. Change-Id: I64cf8c0a5473268bdfd71fd560ee6b3bff219ce9 Reviewed-on: https://asterix-gerrit.ics.uci.edu/2238 Tested-by: Jenkins <jenk...@fulliautomatix.ics.uci.edu> Integration-Tests: Jenkins <jenk...@fulliautomatix.ics.uci.edu> Contrib: Jenkins <jenk...@fulliautomatix.ics.uci.edu> Reviewed-by: abdullah alamoudi <bamou...@gmail.com> > Define IIndexCursor interface > ----------------------------- > > Key: ASTERIXDB-2204 > URL: https://issues.apache.org/jira/browse/ASTERIXDB-2204 > Project: Apache AsterixDB > Issue Type: Bug > Components: STO - Storage > Reporter: Abdullah Alamoudi > Assignee: Abdullah Alamoudi > > The IIndexCursor interface is one of the critical interfaces inside > asteridxb. It is used to access tuples inside indexes, we have many > implementations for it and it is used differently in a different places. We > are trying to specify a contract for the interface that all > implementors/users of the a cursor have to follow to ensure consistent state > and no leaked resources under any circumstances. The scope of this email > focuses on the lifecycle of cursors and on the following existing methods: > -- void open(ICursorInitialState initialState, ISearchPredicate searchPred) > throws HyracksDataException; > -- boolean hasNext() throws HyracksDataException; > -- void next() throws HyracksDataException; > -- void close() throws HyracksDataException; > -- void reset() throws HyracksDataException; > Currently, these calls are "mostly" used as follows in our code: > - If there are multiple search predicates: > cursor = new cursor(); > while (more predicates){ > cursor.reset() > cursor.open(predicate); > while (cursor.hasNext()){ > cursor.next() > } > } > cursor.close(); > - If there is a single search predicate: > cursor = new cursor(); > cursor.open(predicate); > while (cursor.hasNext()){ > cursor.next() > } > cursor.close(); > There are two problems with this: > 1. There is no enforcement of any type of contract. For example, one can open > a cursor and reset it and then continue to read tuples from the cursor as > follows: > cursor.open(predicate); > cursor.hasNext() > cursor.next() > cursor.reset() > cursor.hasNext() > cursor.next() > and continue to read tuples. This is bug prone and can cause hidden bugs to > linger for a long time. > 2. Naming and symmetry: open calls don't have corresponding close calls > "unless we know the cursor will be used with exactly one search predicate" > With this, the implementation of the cursor lead to either duplicate code or > having close() call reset() or the other way around and handling of special > cases. > Moreover, when there are slight differences, often it is easy to make a > change in one and forget about the other. > ========================================== > To deal with these issues, we are proposing the following: > 1. change the methods to: > -- void open(ICursorInitialState initialState, ISearchPredicate searchPred) > throws HyracksDataException; > -- boolean hasNext() throws HyracksDataException; > -- void next() throws HyracksDataException; > -- void close(); // used to be reset() > -- void destroy(); // used to be close() > The call cycle becomes: > - If there are multiple search predicates: > cursor = new cursor(); > while (more predicates){ > cursor.open(predicate); > while (cursor.hasNext()){ > cursor.next() > } > cursor.close(); // used to be reset() > } > cursor.destroy(); // used to be close() > - If there is a single search predicate: > cursor = new cursor(); > cursor.open(predicate); > while (cursor.hasNext()){ > cursor.next() > } > cursor.close(); // used to be reset() > cursor.destroy(); // used to be close() > This way, we have a symmetry and we know that: > -- A created cursor will always have cursor.destroy() called. > -- An open cursor will always have cursor.close() called. > 2. Enforce the cursor state machine as follows: > The states are: > CLOSED > OPEN > DESTROYED > When a cursor object is created, it is in the CLOSED state. > - CLOSED: The only legal calls are open() --> OPEN, or destroy() --> DESTROYED > - OPEN: The only legal calls are hasNext(), next(), or close() --> CLOSED. > - DESTROYED: All calls are illegal. > We can then add tests to ensure that each of the cursors is enforcing the > contract. -- This message was sent by Atlassian JIRA (v6.4.14#64029)