if( keyCount == 0 ) {
return;
}
final int collectionId = this.doc.getCollection().getId();
final Lock lock = dbValues.getLock();
for( byte section = 0; section <= IDX_QNAME; section++ ) {
for( final Map.Entry<Object, List<NodeId>> entry : pending[section].entrySet() ) {
final Object key = entry.getKey();
final List<NodeId> storedGIDList = entry.getValue();
final List<NodeId> newGIDList = new ArrayList<NodeId>();
os.clear();
try {
lock.acquire( Lock.WRITE_LOCK );
//Compute a key for the value
Value searchKey;
if( section == IDX_GENERIC ) {
searchKey = new SimpleValue( collectionId, ( Indexable )key );
} else {
final QNameKey qnk = ( QNameKey )key;
searchKey = new QNameValue( collectionId, qnk.qname, qnk.value, broker.getBrokerPool().getSymbols() );
}
final Value value = dbValues.get( searchKey );
//Does the value already has data in the index ?
if( value != null ) {
//Add its data to the new list
final VariableByteArrayInput is = new VariableByteArrayInput( value.getData() );
while( is.available() > 0 ) {
final int storedDocId = is.readInt();
final int gidsCount = is.readInt();
final int size = is.readFixedInt();
if( storedDocId != this.doc.getDocId() ) {
// data are related to another document:
// append them to any existing data
os.writeInt( storedDocId );
os.writeInt( gidsCount );
os.writeFixedInt( size );
is.copyRaw( os, size );
} else {
// data are related to our document:
// feed the new list with the GIDs
NodeId previous = null;
for( int j = 0; j < gidsCount; j++ ) {
NodeId nodeId = broker.getBrokerPool().getNodeFactory().createFromStream( previous, is );
previous = nodeId;
// add the node to the new list if it is not
// in the list of removed nodes
if( !containsNode( storedGIDList, nodeId ) ) {
newGIDList.add( nodeId );
}
}
}
}
//append the data from the new list
if( newGIDList.size() > 0 ) {
final int gidsCount = newGIDList.size();
//Don't forget this one
FastQSort.sort( newGIDList, 0, gidsCount - 1 );
os.writeInt( this.doc.getDocId() );
os.writeInt( gidsCount );
//Mark position
final int nodeIDsLength = os.position();
//Dummy value : actual one will be written below
os.writeFixedInt( 0 );
NodeId previous = null;
for( final NodeId nodeId : newGIDList ) {
try {
previous = nodeId.write( previous, os );
}
catch( final IOException e ) {
LOG.warn( "IO error while writing range index: " + e.getMessage(), e );
//TODO : throw exception ?
}
}
//Write (variable) length of node IDs
os.writeFixedInt( nodeIDsLength, os.position() - nodeIDsLength - LENGTH_NODE_IDS );
}
// if(os.data().size() == 0)
// dbValues.remove(value);
if( dbValues.update( value.getAddress(), searchKey, os.data() ) == BFile.UNKNOWN_ADDRESS ) {
LOG.error( "Could not update index data for value '" + searchKey + "'" );
//TODO: throw exception ?
}
} else {
if( dbValues.put( searchKey, os.data() ) == BFile.UNKNOWN_ADDRESS ) {
LOG.error( "Could not put index data for value '" + searchKey + "'" );
//TODO : throw exception ?
}
}
}
catch( final EXistException e ) {
LOG.error( e.getMessage(), e );
}
catch( final LockException e ) {
LOG.warn( "Failed to acquire lock for '" + dbValues.getFile().getName() + "'", e );
//TODO : return ?
}
catch( final ReadOnlyException e ) {
LOG.warn( "Read-only error on '" + dbValues.getFile().getName() + "'", e );
}
catch( final IOException e ) {
LOG.error( e.getMessage(), e );
}
finally {
lock.release( Lock.WRITE_LOCK );
os.clear();
}
}
pending[section].clear();
}