2

We are using Xodus on a Servlet container, and from time to time the application throws this error (which we don't know what is the cause)

jetbrains.exodus.ExodusException: Can't acquire environment lock after 0 ms.

 Lock owner info: 
null
    at jetbrains.exodus.log.Log.tryLock(Log.java:935)
    at jetbrains.exodus.log.Log.<init>(Log.java:91)
    at jetbrains.exodus.env.Environments.newLogInstance(Environments.java:137)
    at jetbrains.exodus.env.Environments.newLogInstance(Environments.java:115)
    at jetbrains.exodus.env.Environments.newLogInstance(Environments.java:104)
    at jetbrains.exodus.env.Environments.newInstance(Environments.java:49)
    at jetbrains.exodus.env.Environments.newInstance(Environments.java:39)

What could be causing this to happen?

Example Usage:

public void put(String instance, final String storeName, final String key, final String value) {
    final Environment env = Environments.newInstance(xodusRoot + instance);
    env.executeInTransaction(new TransactionalExecutable() {
        @Override
        public void execute(@NotNull final Transaction txn) {
            final Store store = env.openStore(storeName, StoreConfig.WITHOUT_DUPLICATES, txn);
            store.put(txn, StringBinding.stringToEntry(key), StringBinding.stringToEntry(value));
        }
    });
    env.close();
}

Where this put method is called from a Servlet endpoint, thus multiple concurrent clients of the server call this method.

quarks
  • 33,478
  • 73
  • 290
  • 513

2 Answers2

4

BTW, it's very inefficient to open/close Environment on each request. It makes sense to keep environments open while they are updated. To limit the number of open environments, probably it's good to have a cache of open environments and to close those pushed out of the cache.

Vyacheslav Lukianov
  • 1,913
  • 8
  • 12
  • What is the recommended way to open an environment in a not exclusive way, because the way we will deploy Xodus is that is will reside on a single server (for now) and be accessed by other servers that means the database folder will be accessed by multiple Xodus API concurrently... – quarks Aug 14 '18 at 15:36
  • @xybreak Currently, Environments can only be opened exclusively. Do you mean other servers will access the same Environment on a network filesystem? This would not work. We are working on a feature that would allow to put a database on Amason S3 and use it by different servers. – Vyacheslav Lukianov Aug 14 '18 at 15:54
  • This is very interesting to know that you guys is planning to do this, that would mean that Xodus would be instantly scalable. Google Cloud Storage GCS is already something worth looking. – quarks Aug 14 '18 at 16:03
  • Anyway so that means the only option we have is to put a Single Servlet on top of the Xodus database and handle all Environment instances, like put in a Singleton map or list and new clients accessing the same Store or Key will just resource the Environment object that had already an exclusive access, maybe we are not doing this that is why we can randomly the ` Can't acquire environment lock after 0 ms.` during our unit tests. RIght? – quarks Aug 14 '18 at 16:05
  • @xybrek That's right. You're getting "Can't acquire lock" trying to create two or more Environment instances simultaneously for a single database folder which in your case is identified by a single `String instance`. – Vyacheslav Lukianov Aug 14 '18 at 16:11
3

This happens in case of an attempt to access the database concurrently, regardless of whether from several processes or from a single one. The file xd.lck contains human readable information about the owner of the database lock.

Vyacheslav Lukianov
  • 1,913
  • 8
  • 12
  • What part of the API would lock the database? I mean all our code start with ` final Environment env = Environments.newInstance` and does `env.close();` right after, I have updated my post to show how we use the API. – quarks Aug 13 '18 at 20:36
  • You have a race: concurrent updates of a single instance would result in the exception. – Vyacheslav Lukianov Aug 14 '18 at 14:10
  • Each call to `Environments.newInstance()` as well as to `PersistentEntityStores.newInstance()` tries to get an exclusive database lock. – Vyacheslav Lukianov Aug 14 '18 at 14:16
  • So that means my code is bad, because all of the CRUD operation in our service layer have that, what is the recommended way? – quarks Aug 14 '18 at 15:34
  • @VyacheslavLukianov I am facing similar exception with same logs.. I have xodus directory I wan to share between two applications.. But one with read /write access and other with read-only access.. Is the any other way to create Environment apart from Environments.newInstance("xodusDir"); for read-only access to xodus database.. I need only read only access to xodus from other application.. – Viraj Nalawade Aug 22 '18 at 12:45
  • @VirajNalawade This would be possible with upcoming version 1.3.0. – Vyacheslav Lukianov Aug 22 '18 at 13:48
  • @VyacheslavLukianov I just saw this comment; does it mean for version 1.3.0 and up the same environment / persistent store can be used concurrently? Meaning we can create new instance of PersistentEntityStore pointing to an existing one with already opened store? If yes, then that would be great. – quarks Jul 11 '19 at 15:35
  • 1
    @xybrek yes, versions 1.3.0 and up allow using Environment/PersistentEntityStore concurrently. I gonna post a detailed answer here: https://stackoverflow.com/questions/56995773/multiple-xodus-app-to-access-share-single-directory. – Vyacheslav Lukianov Jul 11 '19 at 19:40
  • @VirajNalawade take a look at https://stackoverflow.com/questions/56995773/multiple-xodus-app-to-access-share-single-directory/57003792#57003792 – Vyacheslav Lukianov Jul 12 '19 at 09:15