From: Wolfgang M. M. <wol...@us...> - 2004-08-03 15:26:13
|
Update of /cvsroot/exist/eXist-1.0/src/org/exist/storage In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8244/src/org/exist/storage Modified Files: DBBroker.java BrokerPool.java NativeBroker.java Log Message: Revised collection locking to fix various concurrency errors. It is now the responsibility of the caller to lock/unlock a collection. A collection can be retrieved and locked via the new openCollection() method provided by DBBroker. After reading/modifying the collection, it should be unlocked by calling Collection.release. The local XML:DB implementation and the XMLRPC interface have been changed to reflect the new collection locking rules. Index: NativeBroker.java =================================================================== RCS file: /cvsroot/exist/eXist-1.0/src/org/exist/storage/NativeBroker.java,v retrieving revision 1.91 retrieving revision 1.92 diff -C2 -d -r1.91 -r1.92 *** NativeBroker.java 28 Jul 2004 18:54:55 -0000 1.91 --- NativeBroker.java 3 Aug 2004 15:25:58 -0000 1.92 *************** *** 336,360 **** public DocumentSet getAllDocuments(DocumentSet docs) { long start = System.currentTimeMillis(); ! Collection root = getCollection(ROOT_COLLECTION); ! root.allDocs(this, docs, true, false); ! if (LOG.isDebugEnabled()) { ! LOG.debug("getAllDocuments(DocumentSet) - end - " ! + "loading " ! + docs.getLength() ! + " documents from " ! + docs.getCollectionCount() ! + "collections took " ! + (System.currentTimeMillis() - start) ! + "ms."); ! } ! return docs; } public Collection getCollection(String name) { ! return getCollection(name, -1); } /** ! * get collection object. If the collection does not exist, null is * returned. * --- 336,373 ---- public DocumentSet getAllDocuments(DocumentSet docs) { long start = System.currentTimeMillis(); ! Collection root = null; ! try { ! root = openCollection(ROOT_COLLECTION, Lock.READ_LOCK); ! root.allDocs(this, docs, true, false); ! if (LOG.isDebugEnabled()) { ! LOG.debug("getAllDocuments(DocumentSet) - end - " ! + "loading " ! + docs.getLength() ! + " documents from " ! + docs.getCollectionCount() ! + "collections took " ! + (System.currentTimeMillis() - start) ! + "ms."); ! } ! return docs; ! } finally { ! root.release(); ! } } public Collection getCollection(String name) { ! return openCollection(name, -1, Lock.NO_LOCK); ! } ! ! public Collection getCollection(String name, long addr) { ! return openCollection(name, addr, Lock.NO_LOCK); ! } ! ! public Collection openCollection(String name, int lockMode) { ! return openCollection(name, -1, lockMode); } /** ! * Get collection object. If the collection does not exist, null is * returned. * *************** *** 362,366 **** *@return The collection value */ ! public Collection getCollection(String name, long addr) { // final long start = System.currentTimeMillis(); name = normalizeCollectionName(name); --- 375,379 ---- *@return The collection value */ ! public Collection openCollection(String name, long addr, int lockMode) { // final long start = System.currentTimeMillis(); name = normalizeCollectionName(name); *************** *** 373,425 **** if (name.endsWith("/") && name.length() > 1) name = name.substring(0, name.length() - 1); ! Value key = null; ! if (addr == -1) ! try { ! key = new Value(name.getBytes("UTF-8")); ! } catch (UnsupportedEncodingException uee) { ! key = new Value(name.getBytes()); ! } ! Collection collection = null; ! VariableByteInput is = null; ! Lock lock = collectionsDb.getLock(); ! try { ! lock.acquire(Lock.READ_LOCK); ! collection = collectionsDb.getCollectionCache().get(name); ! if (collection != null) { ! return collection; ! } ! collection = new Collection(collectionsDb, name); ! try { ! if (addr < 0) { ! is = collectionsDb.getAsStream(key); ! } else { ! is = collectionsDb.getAsStream(addr); } - } catch (IOException ioe) { - LOG.warn(ioe.getMessage(), ioe); } ! if (is == null) ! return null; ! ! try { ! collection.read(this, is); ! } catch (IOException ioe) { ! LOG.warn(ioe); ! return null; } ! collectionsDb.getCollectionCache().add(collection); ! } catch (LockException e) { ! LOG.warn("failed to acquire lock on collections.dbx"); ! return null; ! } finally { ! lock.release(); } - // LOG.debug( - // "loading collection " - // + name - // + " took " - // + (System.currentTimeMillis() - start) - // + "ms."); - return collection; } --- 386,445 ---- if (name.endsWith("/") && name.length() > 1) name = name.substring(0, name.length() - 1); ! ! synchronized(collectionsCache) { ! Collection collection = collectionsCache.get(name); ! if(collection == null) { ! // LOG.debug("loading collection " + name); ! VariableByteInput is = null; ! Lock lock = collectionsDb.getLock(); ! try { ! lock.acquire(Lock.READ_LOCK); ! ! collection = new Collection(collectionsDb, name); ! Value key = null; ! if (addr == -1) { ! try { ! key = new Value(name.getBytes("UTF-8")); ! } catch (UnsupportedEncodingException uee) { ! key = new Value(name.getBytes()); ! } ! } ! try { ! if (addr < 0) { ! is = collectionsDb.getAsStream(key); ! } else { ! is = collectionsDb.getAsStream(addr); ! } ! if (is == null) ! return null; ! collection.read(this, is); ! } catch (IOException ioe) { ! LOG.warn(ioe.getMessage(), ioe); ! } ! } catch (LockException e) { ! LOG.warn("failed to acquire lock on collections.dbx"); ! return null; ! } finally { ! lock.release(); } } ! if(lockMode != Lock.NO_LOCK) { ! try { ! // LOG.debug("acquiring lock on " + collection.getName()); ! collection.getLock().acquire(lockMode); ! // Thread.dumpStack(); ! } catch (LockException e1) { ! LOG.warn("Could not acquire lock on collection " + name); ! } } ! collectionsCache.add(collection); ! // LOG.debug( ! // "loading collection " ! // + name ! // + " took " ! // + (System.currentTimeMillis() - start) ! // + "ms."); ! return collection; } } *************** *** 521,524 **** --- 541,580 ---- } + public Document openDocument(String docPath, int lockMode) throws PermissionDeniedException { + if (!docPath.startsWith("/")) + docPath = '/' + docPath; + if (!docPath.startsWith("/db")) + docPath = "/db" + docPath; + + int pos = docPath.lastIndexOf('/'); + String collName = docPath.substring(0, pos); + String docName = docPath.substring(pos + 1); + + Collection collection = null; + try { + collection = openCollection(collName, lockMode); + if (collection == null) { + LOG.debug("collection " + collName + " not found!"); + return null; + } + if (!collection.getPermissions().validate(user, Permission.READ)) { + throw new PermissionDeniedException("permission denied to read collection"); + } + DocumentImpl doc = collection.getDocumentWithLock(this, docName, lockMode); + if (doc == null) { + LOG.debug("document " + docPath + " not found!"); + return null; + } + // if (!doc.getPermissions().validate(user, Permission.READ)) + // throw new PermissionDeniedException("not allowed to read document"); + return doc; + } catch (LockException e) { + LOG.warn("Could not acquire lock on document " + docPath, e); + } finally { + collection.release(); + } + return null; + } + public DocumentSet getDocumentsByCollection(String collection, DocumentSet docs) throws PermissionDeniedException { *************** *** 1483,1537 **** name = name.substring(0, name.length() - 1); ! Collection current = null; ! Lock lock = collectionsDb.getLock(); ! try { ! lock.acquire(); ! StringTokenizer tok = new StringTokenizer(name, "/"); ! String temp = tok.nextToken(); ! String path = ROOT_COLLECTION; ! Collection sub; ! current = getCollection(ROOT_COLLECTION); ! if (current == null) { ! LOG.debug("creating root collection /db"); ! current = new Collection(collectionsDb, ROOT_COLLECTION); ! current.getPermissions().setPermissions(0777); ! current.getPermissions().setOwner(user); ! current.getPermissions().setGroup(user.getPrimaryGroup()); ! current.setId(getNextCollectionId()); ! current.setCreationTime(System.currentTimeMillis()); ! saveCollection(current); ! } ! while (tok.hasMoreTokens()) { ! temp = tok.nextToken(); ! path = path + "/" + temp; ! if (current.hasSubcollection(temp)) { ! current = getCollection(path); ! } else { ! if (!current.getPermissions().validate(user, Permission.WRITE)) { ! LOG.debug("permission denied to create collection " + path); ! throw new PermissionDeniedException("not allowed to write to collection"); ! } ! LOG.debug("creating collection " + path); ! sub = new Collection(collectionsDb, path); ! sub.getPermissions().setOwner(user); ! sub.getPermissions().setGroup(user.getPrimaryGroup()); ! sub.setId(getNextCollectionId()); ! sub.setCreationTime(System.currentTimeMillis()); ! current.addCollection(sub); saveCollection(current); - current = sub; } } - } catch (ReadOnlyException e) { - LOG.debug("database read-only"); - return null; - } catch (LockException e) { - LOG.warn("failed to acquire lock on collections store"); - } finally { - lock.release(); } - // LOG.debug("getOrCreateCollection took " + - // (System.currentTimeMillis() - start) + "ms."); - return current; } --- 1539,1587 ---- name = name.substring(0, name.length() - 1); ! synchronized(collectionsCache) { ! try { ! StringTokenizer tok = new StringTokenizer(name, "/"); ! String temp = tok.nextToken(); ! String path = ROOT_COLLECTION; ! Collection sub; ! Collection current = getCollection(ROOT_COLLECTION); ! if (current == null) { ! LOG.debug("creating root collection /db"); ! current = new Collection(collectionsDb, ROOT_COLLECTION); ! current.getPermissions().setPermissions(0777); ! current.getPermissions().setOwner(user); ! current.getPermissions().setGroup(user.getPrimaryGroup()); ! current.setId(getNextCollectionId()); ! current.setCreationTime(System.currentTimeMillis()); saveCollection(current); } + while (tok.hasMoreTokens()) { + temp = tok.nextToken(); + path = path + "/" + temp; + if (current.hasSubcollection(temp)) { + current = getCollection(path); + } else { + if (!current.getPermissions().validate(user, Permission.WRITE)) { + LOG.debug("permission denied to create collection " + path); + throw new PermissionDeniedException("not allowed to write to collection"); + } + LOG.debug("creating collection " + path); + sub = new Collection(collectionsDb, path); + sub.getPermissions().setOwner(user); + sub.getPermissions().setGroup(user.getPrimaryGroup()); + sub.setId(getNextCollectionId()); + sub.setCreationTime(System.currentTimeMillis()); + current.addCollection(sub); + saveCollection(current); + current = sub; + } + } + // LOG.debug("getOrCreateCollection took " + + // (System.currentTimeMillis() - start) + "ms."); + return current; + } catch(ReadOnlyException e) { + throw new PermissionDeniedException(DATABASE_IS_READ_ONLY); } } } *************** *** 1691,1819 **** } ! public boolean removeCollection(String name) throws PermissionDeniedException { if (readOnly) throw new PermissionDeniedException(DATABASE_IS_READ_ONLY); - if (!name.startsWith(ROOT_COLLECTION)) - name = ROOT_COLLECTION + name; - Collection collection = getCollection(name); - if (collection == null) { - LOG.debug("collection " + name + " not found!"); - return false; - } if (!collection.getPermissions().validate(user, Permission.WRITE)) ! throw new PermissionDeniedException("not allowed to remove collection"); ! String childCollection; ! LOG.debug("removing sub-collections"); ! for (Iterator i = collection.collectionIterator(); i.hasNext();) { ! childCollection = (String) i.next(); ! removeCollection( ! (name.equals("/") ! ? "/" + childCollection ! : name + "/" + childCollection)); ! } ! Lock lock = collectionsDb.getLock(); ! try { ! lock.acquire(Lock.WRITE_LOCK); ! ! // if this is not the root collection remove it completely ! if (name.equals(ROOT_COLLECTION)) ! saveCollection(collection); ! else { ! Value key; ! try { ! key = new Value(name.getBytes("UTF-8")); ! } catch (UnsupportedEncodingException uee) { ! key = new Value(name.getBytes()); ! } ! collectionsDb.remove(key); ! } ! if (!name.equals(ROOT_COLLECTION)) ! collectionsDb.getCollectionCache().remove(collection); ! Collection parent = collection.getParent(this); ! if (parent != null) { ! parent.removeCollection(name.substring(name.lastIndexOf("/") + 1)); ! saveCollection(parent); ! } ! } catch (LockException e) { ! LOG.warn("Failed to acquire lock on collections.dbx"); ! } catch (ReadOnlyException e) { ! throw new PermissionDeniedException(DATABASE_IS_READ_ONLY); ! } finally { ! lock.release(); ! } ! freeCollection(collection.getId()); ! textEngine.dropIndex(collection); ! elementIndex.dropIndex(collection); ! LOG.debug("removing dom nodes ..."); ! for (Iterator i = collection.iterator(this); i.hasNext();) { ! final DocumentImpl doc = (DocumentImpl) i.next(); ! LOG.debug("removing document " + doc.getFileName()); ! new DOMTransaction(this, domDb, Lock.WRITE_LOCK) { ! public Object start() { ! if(doc.getResourceType() == DocumentImpl.BINARY_FILE) { ! domDb.remove(doc.getAddress()); ! domDb.removeOverflowValue(((BinaryDocument)doc).getPage()); ! } else { ! NodeImpl node = (NodeImpl)doc.getFirstChild(); ! domDb.removeAll(node.getInternalAddress()); ! } ! return null; ! } ! } ! .run(); ! new DOMTransaction(this, domDb, Lock.WRITE_LOCK) { ! public Object start() { ! try { ! Value ref = new NodeRef(doc.getDocId()); ! IndexQuery query = ! new IndexQuery(IndexQuery.TRUNC_RIGHT, ref); ! domDb.remove(query, null); ! domDb.flush(); ! } catch (BTreeException e) { ! LOG.warn("btree error while removing document", e); ! } catch (DBException e) { ! LOG.warn("db error while removing document", e); ! } catch (IOException e) { ! LOG.warn("io error while removing document", e); ! } catch (TerminatedException e) { ! LOG.warn("method terminated", e); ! } ! return null; ! } ! } ! .run(); ! freeDocument(doc.getDocId()); } - return true; } ! public void removeDocument(String docName, boolean freeDocId) throws PermissionDeniedException { if (readOnly) throw new PermissionDeniedException(DATABASE_IS_READ_ONLY); try { - if (!docName.startsWith("/")) - docName = '/' + docName; - final DocumentImpl doc = (DocumentImpl) getDocument(docName); - if (doc == null) { - if (LOG.isDebugEnabled()) { - LOG.debug("removeDocument(String) - end - document " - + docName - + " not found"); - } - return; - } if (LOG.isInfoEnabled()) { LOG.info("removeDocument() - " + "removing document " ! + doc.getDocId() + " ..."); } ! elementIndex.dropIndex(doc); ! textEngine.dropIndex(doc); if (LOG.isDebugEnabled()) { LOG.debug("removeDocument() - removing dom"); --- 1741,1868 ---- } ! public boolean removeCollection(Collection collection) throws PermissionDeniedException { if (readOnly) throw new PermissionDeniedException(DATABASE_IS_READ_ONLY); if (!collection.getPermissions().validate(user, Permission.WRITE)) ! throw new PermissionDeniedException("not allowed to remove collection"); ! synchronized(collectionsCache) { ! String name = collection.getName(); ! // remove from parent collection ! Collection parent = openCollection(collection.getParentPath(), Lock.WRITE_LOCK); ! if (parent != null) { ! try { ! parent.removeCollection(name.substring(name.lastIndexOf("/") + 1)); ! saveCollection(parent); ! } catch (LockException e) { ! LOG.warn("LockException while removing collection " + name); ! } finally { ! parent.getLock().release(); ! } ! } ! ! // remove child collections ! String childName; ! Collection childCollection; ! LOG.debug("removing sub-collections"); ! for (Iterator i = collection.collectionIterator(); i.hasNext();) { ! childName = (String) i.next(); ! childCollection = openCollection(name + '/' + childName, Lock.WRITE_LOCK); ! try { ! removeCollection(childCollection); ! } finally { ! childCollection.getLock().release(); ! } ! } ! ! Lock lock = collectionsDb.getLock(); ! try { ! lock.acquire(Lock.WRITE_LOCK); ! ! // if this is not the root collection remove it completely ! if (name.equals(ROOT_COLLECTION)) ! saveCollection(collection); ! else { ! Value key; ! try { ! key = new Value(name.getBytes("UTF-8")); ! } catch (UnsupportedEncodingException uee) { ! key = new Value(name.getBytes()); ! } ! collectionsDb.remove(key); ! } ! if (!name.equals(ROOT_COLLECTION)) ! collectionsCache.remove(collection); ! } catch (LockException e) { ! LOG.warn("Failed to acquire lock on collections.dbx"); ! } catch (ReadOnlyException e) { ! throw new PermissionDeniedException(DATABASE_IS_READ_ONLY); ! } finally { ! lock.release(); ! } ! freeCollection(collection.getId()); ! textEngine.dropIndex(collection); ! elementIndex.dropIndex(collection); ! ! LOG.debug("removing resources ..."); ! for (Iterator i = collection.iterator(this); i.hasNext();) { ! final DocumentImpl doc = (DocumentImpl) i.next(); ! LOG.debug("removing document " + doc.getFileName()); ! new DOMTransaction(this, domDb, Lock.WRITE_LOCK) { ! public Object start() { ! if(doc.getResourceType() == DocumentImpl.BINARY_FILE) { ! domDb.remove(doc.getAddress()); ! domDb.removeOverflowValue(((BinaryDocument)doc).getPage()); ! } else { ! NodeImpl node = (NodeImpl)doc.getFirstChild(); ! domDb.removeAll(node.getInternalAddress()); ! } ! return null; ! } ! } ! .run(); ! new DOMTransaction(this, domDb, Lock.WRITE_LOCK) { ! public Object start() { ! try { ! Value ref = new NodeRef(doc.getDocId()); ! IndexQuery query = ! new IndexQuery(IndexQuery.TRUNC_RIGHT, ref); ! domDb.remove(query, null); ! domDb.flush(); ! } catch (BTreeException e) { ! LOG.warn("btree error while removing document", e); ! } catch (DBException e) { ! LOG.warn("db error while removing document", e); ! } catch (IOException e) { ! LOG.warn("io error while removing document", e); ! } catch (TerminatedException e) { ! LOG.warn("method terminated", e); ! } ! return null; ! } ! } ! .run(); ! freeDocument(doc.getDocId()); ! } ! return true; } } ! public void removeDocument(final DocumentImpl document, boolean freeDocId) throws PermissionDeniedException { if (readOnly) throw new PermissionDeniedException(DATABASE_IS_READ_ONLY); try { if (LOG.isInfoEnabled()) { LOG.info("removeDocument() - " + "removing document " ! + document.getDocId() + " ..."); } ! elementIndex.dropIndex(document); ! textEngine.dropIndex(document); if (LOG.isDebugEnabled()) { LOG.debug("removeDocument() - removing dom"); *************** *** 1821,1825 **** new DOMTransaction(this, domDb) { public Object start() { ! NodeImpl node = (NodeImpl)doc.getFirstChild(); domDb.removeAll(node.getInternalAddress()); return null; --- 1870,1874 ---- new DOMTransaction(this, domDb) { public Object start() { ! NodeImpl node = (NodeImpl)document.getFirstChild(); domDb.removeAll(node.getInternalAddress()); return null; *************** *** 1828,1832 **** .run(); ! NodeRef ref = new NodeRef(doc.getDocId()); final IndexQuery idx = new IndexQuery(IndexQuery.TRUNC_RIGHT, ref); new DOMTransaction(this, domDb) { --- 1877,1881 ---- .run(); ! NodeRef ref = new NodeRef(document.getDocId()); final IndexQuery idx = new IndexQuery(IndexQuery.TRUNC_RIGHT, ref); new DOMTransaction(this, domDb) { *************** *** 1849,1853 **** .run(); if(freeDocId) ! freeDocument(doc.getDocId()); } catch (ReadOnlyException e) { LOG.warn("removeDocument(String) - " + DATABASE_IS_READ_ONLY); --- 1898,1902 ---- .run(); if(freeDocId) ! freeDocument(document.getDocId()); } catch (ReadOnlyException e) { LOG.warn("removeDocument(String) - " + DATABASE_IS_READ_ONLY); *************** *** 1960,1963 **** --- 2009,2013 ---- if (readOnly) throw new PermissionDeniedException(DATABASE_IS_READ_ONLY); + collectionsCache.add(collection); Lock lock = null; try { *************** *** 1985,1989 **** } collection.setAddress(addr); - collectionsDb.getCollectionCache().add(collection); ostream.close(); } catch (IOException ioe) { --- 2035,2038 ---- *************** *** 2080,2083 **** --- 2129,2141 ---- if(newName.indexOf('/') > -1) throw new PermissionDeniedException("New collection name is illegal (may not contain a '/')"); + // check if another collection with the same name exists at the destination + Collection old = openCollection(newName, Lock.WRITE_LOCK); + if(old != null) { + try { + removeCollection(old); + } finally { + old.release(); + } + } Lock lock = null; try { *************** *** 2085,2092 **** lock.acquire(Lock.WRITE_LOCK); newName = destination.getName() + '/' + newName; ! // check if another collection with the same name exists at the destination ! Collection old = getCollection(newName); ! if(old != null) ! removeCollection(old.getName()); Collection destCollection = getOrCreateCollection(newName); for(Iterator i = collection.iterator(this); i.hasNext(); ) { --- 2143,2147 ---- lock.acquire(Lock.WRITE_LOCK); newName = destination.getName() + '/' + newName; ! Collection destCollection = getOrCreateCollection(newName); for(Iterator i = collection.iterator(this); i.hasNext(); ) { *************** *** 2126,2176 **** if(newName.indexOf('/') > -1) throw new PermissionDeniedException("New collection name is illegal (may not contain a '/')"); - Lock lock = null; - try { - lock = collectionsDb.getLock(); - lock.acquire(Lock.WRITE_LOCK); // check if another collection with the same name exists at the destination ! Collection old = getCollection(destination.getName() + '/' + newName); ! if(old != null) ! removeCollection(old.getName()); ! ! String name = collection.getName(); ! Collection parent = collection.getParent(this); ! if(parent != null) ! parent.removeCollection(name.substring(name.lastIndexOf("/") + 1)); ! ! collectionsDb.getCollectionCache().remove(collection); ! Value key; ! try { ! key = new Value(name.getBytes("UTF-8")); ! } catch (UnsupportedEncodingException uee) { ! key = new Value(name.getBytes()); ! } ! collectionsDb.remove(key); ! ! collection.setName(destination.getName() + '/' + newName); ! collection.setCreationTime(System.currentTimeMillis()); ! ! destination.addCollection(collection); ! if(parent != null) ! saveCollection(parent); ! if(parent != destination) ! saveCollection(destination); ! saveCollection(collection); ! ! String childName; Collection child; for(Iterator i = collection.collectionIterator(); i.hasNext(); ) { childName = (String)i.next(); ! child = getCollection(name + '/' + childName); if(child == null) LOG.warn("Child collection " + childName + " not found"); ! else ! moveCollection(child, collection, childName); } - } catch (ReadOnlyException e) { - throw new PermissionDeniedException(DATABASE_IS_READ_ONLY); - } finally { - lock.release(); } } --- 2181,2246 ---- if(newName.indexOf('/') > -1) throw new PermissionDeniedException("New collection name is illegal (may not contain a '/')"); // check if another collection with the same name exists at the destination ! Collection old = openCollection(destination.getName() + '/' + newName, Lock.WRITE_LOCK); ! if(old != null) { ! try { ! removeCollection(old); ! } finally { ! old.release(); ! } ! } ! String name = collection.getName(); ! synchronized(collectionsCache) { ! Collection parent = openCollection(collection.getParentPath(), Lock.WRITE_LOCK); ! if(parent != null) { ! try { ! parent.removeCollection(name.substring(name.lastIndexOf("/") + 1)); ! } finally { ! parent.release(); ! } ! } ! Lock lock = null; ! try { ! lock = collectionsDb.getLock(); ! lock.acquire(Lock.WRITE_LOCK); ! ! collectionsCache.remove(collection); ! Value key; ! try { ! key = new Value(name.getBytes("UTF-8")); ! } catch (UnsupportedEncodingException uee) { ! key = new Value(name.getBytes()); ! } ! collectionsDb.remove(key); ! ! collection.setName(destination.getName() + '/' + newName); ! collection.setCreationTime(System.currentTimeMillis()); ! ! destination.addCollection(collection); ! if(parent != null) ! saveCollection(parent); ! if(parent != destination) ! saveCollection(destination); ! saveCollection(collection); ! } catch (ReadOnlyException e) { ! throw new PermissionDeniedException(DATABASE_IS_READ_ONLY); ! } finally { ! lock.release(); ! } ! String childName; Collection child; for(Iterator i = collection.collectionIterator(); i.hasNext(); ) { childName = (String)i.next(); ! child = openCollection(name + '/' + childName, Lock.WRITE_LOCK); if(child == null) LOG.warn("Child collection " + childName + " not found"); ! else { ! try { ! moveCollection(child, collection, childName); ! } finally { ! child.release(); ! } ! } } } } *************** *** 2385,2389 **** } doc.setAddress(domDb.add(data)); ! // LOG.debug("Document metadata stored to " + StorageAddress.toString(doc.getAddress())); return null; } --- 2455,2459 ---- } doc.setAddress(domDb.add(data)); ! LOG.debug("Document metadata stored to " + StorageAddress.toString(doc.getAddress())); return null; } *************** *** 2393,2404 **** public void updateDocument(DocumentImpl doc) throws LockException, PermissionDeniedException { ! Lock lock = collectionsDb.getLock(); ! try { ! lock.acquire(Lock.WRITE_LOCK); ! storeDocument(doc); ! saveCollection(doc.getCollection()); ! } finally { ! lock.release(); ! } } --- 2463,2468 ---- public void updateDocument(DocumentImpl doc) throws LockException, PermissionDeniedException { ! storeDocument(doc); ! saveCollection(doc.getCollection()); } Index: DBBroker.java =================================================================== RCS file: /cvsroot/exist/eXist-1.0/src/org/exist/storage/DBBroker.java,v retrieving revision 1.39 retrieving revision 1.40 diff -C2 -d -r1.39 -r1.40 *** DBBroker.java 28 Jul 2004 18:54:54 -0000 1.39 --- DBBroker.java 3 Aug 2004 15:25:58 -0000 1.40 *************** *** 34,37 **** --- 34,38 ---- import org.exist.EXistException; import org.exist.collections.Collection; + import org.exist.collections.CollectionCache; import org.exist.dom.BinaryDocument; import org.exist.dom.DocumentImpl; *************** *** 73,76 **** --- 74,83 ---- public final static int DBM = 3; + // size of the internal buffer for collection objects + public static final int COLLECTION_BUFFER_SIZE = 128; + + protected static CollectionCache collectionsCache = + new CollectionCache(COLLECTION_BUFFER_SIZE); + protected final static Logger LOG = Logger.getLogger(DBBroker.class); *************** *** 149,152 **** --- 156,163 ---- } + public CollectionCache getCollectionsCache() { + return collectionsCache; + } + public DBBroker(BrokerPool pool, Configuration config) throws EXistException { *************** *** 235,238 **** --- 246,271 ---- /** + * Returns the database collection identified by the specified path. + * The storage address is used to locate the collection without + * looking up the path in the btree. + * + * @return + */ + public abstract Collection getCollection(String name, long address); + + /** + * Open a collection for reading or writing. The collection is identified by its + * absolute path, e.g. /db/system. It will be loaded and locked according to the + * lockMode argument. + * + * The caller should take care to release the collection lock properly. + * + * @param name the collection path + * @param lockMode one of the modes specified in class {@link org.exist.util.Lock} + * @return collection or null if no collection matches the path + */ + public abstract Collection openCollection(String name, int lockMode); + + /** * Returns the database collection identified by the specified path. * If the collection does not yet exist, it is created - including all *************** *** 245,257 **** return null; } - - /** - * Returns the database collection identified by the specified path. - * The storage address is used to locate the collection without - * looking up the path in the btree. - * - * @return - */ - public abstract Collection getCollection(String name, long address); public abstract void reloadCollection(Collection collection); --- 278,281 ---- *************** *** 305,308 **** --- 329,335 ---- throws PermissionDeniedException; + public abstract Document openDocument(String docPath, int lockMode) + throws PermissionDeniedException; + /** * Returns a DocumentSet containing all the documents found in the *************** *** 396,400 **** * */ ! public abstract boolean removeCollection(String name) throws PermissionDeniedException; --- 423,427 ---- * */ ! public abstract boolean removeCollection(Collection collection) throws PermissionDeniedException; *************** *** 403,412 **** * */ ! public void removeDocument(String docName) throws PermissionDeniedException { ! removeDocument(docName, true); } ! public abstract void removeDocument(String docName, boolean freeDocId) throws PermissionDeniedException; --- 430,439 ---- * */ ! public void removeDocument(DocumentImpl document) throws PermissionDeniedException { ! removeDocument(document, true); } ! public abstract void removeDocument(DocumentImpl document, boolean freeDocId) throws PermissionDeniedException; Index: BrokerPool.java =================================================================== RCS file: /cvsroot/exist/eXist-1.0/src/org/exist/storage/BrokerPool.java,v retrieving revision 1.25 retrieving revision 1.26 diff -C2 -d -r1.25 -r1.26 *** BrokerPool.java 28 Jul 2004 18:54:54 -0000 1.25 --- BrokerPool.java 3 Aug 2004 15:25:58 -0000 1.26 *************** *** 250,260 **** } synchronized(this) { - // force the thread to wait until a pending sync has finished - while(syncRequired && threads.size() > 0) { - try { - this.wait(); - } catch(InterruptedException e) { - } - } if (pool.isEmpty()) { if (brokers < max) --- 250,253 ---- *************** *** 272,276 **** threads.put(Thread.currentThread(), broker); broker.incReferenceCount(); ! // this.notifyAll(); return broker; } --- 265,269 ---- threads.put(Thread.currentThread(), broker); broker.incReferenceCount(); ! this.notifyAll(); return broker; } |