/* This file is part of the db4o object database http://www.db4o.com Copyright (C) 2004 - 2011 Versant Corporation http://www.versant.com db4o is free software; you can redistribute it and/or modify it under the terms of version 3 of the GNU General Public License as published by the Free Software Foundation. db4o is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/. */ package com.db4o.cs.internal; import com.db4o.foundation.*; import com.db4o.internal.query.result.*; /** * @exclude */ class ClientQueryResultIterator implements Iterator4 { private static final PrefetchingStrategy _prefetchingStrategy = SingleMessagePrefetchingStrategy.INSTANCE; private Object[] _prefetchedObjects; private int _remainingObjects; private int _prefetchRight; private final AbstractQueryResult _client; private final IntIterator4 _ids; ClientQueryResultIterator(AbstractQueryResult client) { _client = client; _ids = client.iterateIDs(); } public Object current() { synchronized (streamLock()) { return _client.activate(prefetchedCurrent()); } } private Object streamLock() { return _client.lock(); } public void reset() { _remainingObjects = 0; _ids.reset(); } public boolean moveNext() { synchronized (streamLock()) { if (_remainingObjects > 0) { --_remainingObjects; return skipNulls(); } prefetch(); --_remainingObjects; if(_remainingObjects < 0){ return false; } return skipNulls(); } } private boolean skipNulls() { // skip nulls (deleted objects) if (prefetchedCurrent() == null){ return moveNext(); } return true; } private void prefetch() { _client.stream().withEnvironment(new Runnable() { public void run() { ensureObjectCacheAllocated(prefetchCount()); _remainingObjects = _prefetchingStrategy.prefetchObjects(stream(), _client.transaction(), _ids, _prefetchedObjects, prefetchCount()); _prefetchRight=_remainingObjects; }}); } private int prefetchCount() { return Math.max(stream().config().prefetchObjectCount(), 1); } private ClientObjectContainer stream() { return (ClientObjectContainer) _client.stream(); } private Object prefetchedCurrent() { return _prefetchedObjects[_prefetchRight-_remainingObjects-1]; } // TODO: open this as an external tuning interface in ExtObjectSet // public void prefetch(int count){ // if(count < 1){ // count = 1; // } // i_prefetchCount = count; // Object[] temp = new Object[i_prefetchCount]; // if(i_remainingObjects > 0){ // // Potential problem here: // // On reducing the prefetch size, this will crash. // System.arraycopy(i_prefetched, 0, temp, 0, i_remainingObjects); // } // i_prefetched = temp; // } private void ensureObjectCacheAllocated(int prefetchObjectCount) { if(_prefetchedObjects==null) { _prefetchedObjects = new Object[prefetchObjectCount]; return; } if(prefetchObjectCount>_prefetchedObjects.length) { Object[] newPrefetchedObjects=new Object[prefetchObjectCount]; System.arraycopy(_prefetchedObjects, 0, newPrefetchedObjects, 0, _prefetchedObjects.length); _prefetchedObjects=newPrefetchedObjects; } } }