Uploaded image for project: 'Java Driver'
  1. Java Driver
  2. JAVA-2091

Exception: Interrupted acquiring a permit to retrieve an item from the pool

    • Type: Icon: Bug Bug
    • Resolution: Done
    • Priority: Icon: Major - P3 Major - P3
    • None
    • Affects Version/s: 3.2.0
    • Component/s: Connection Management
    • Labels:
      None
    • Environment:
      Ubuntu, connecting to single instance of Mongo DB 3.0.6 on localhost

      We recently upgraded from a older version of the MongoDB driver to 3.2 and are see multiple exceptions being thrown.

      Our application runs OK for a day or so but then we're seeing this exception being thrown frequently...

      Error message
      com.mongodb.MongoInterruptedException: Interrupted acquiring a permit to retrieve an item from the pool
      
      Sample stack trace
      …ngodb.internal.connection.ConcurrentPool.acquirePermit (ConcurrentPool.java:186)
      
           com.mongodb.internal.connection.ConcurrentPool.get (ConcurrentPool.java:126)
      
      …b.connection.DefaultConnectionPool.getPooledConnection (DefaultConnectionPool.java:250)
      
             com.mongodb.connection.DefaultConnectionPool.get (DefaultConnectionPool.java:91)
      
             com.mongodb.connection.DefaultConnectionPool.get (DefaultConnectionPool.java:80)
      com.mongodb.connection.DefaultConnectionPool.get
      
           com.mongodb.connection.DefaultServer.getConnection (DefaultServer.java:72)
      
      …erBinding$ClusterBindingConnectionSource.getConnection (ClusterBinding.java:86)
      
      …mongodb.operation.OperationHelper.withConnectionSource (OperationHelper.java:228)
      
         com.mongodb.operation.OperationHelper.withConnection (OperationHelper.java:221)
      
        com.mongodb.operation.MixedBulkWriteOperation.execute (MixedBulkWriteOperation.java:168)
      
        com.mongodb.operation.MixedBulkWriteOperation.execute (MixedBulkWriteOperation.java:74)
      
                                    com.mongodb.Mongo.execute (Mongo.java:782)
      
                                  com.mongodb.Mongo$2.execute (Mongo.java:765)
      
      ….mongodb.MongoCollectionImpl.executeSingleWriteRequest (MongoCollectionImpl.java:515)
      
                   com.mongodb.MongoCollectionImpl.replaceOne (MongoCollectionImpl.java:344)
      
       com.mapov.availability.AvailabilityCache.cacheResponse (AvailabilityCache.java:62)
      
       com.mapov.availability.AvailabilityCache.cacheResponse (AvailabilityCache.java:45)
      
      ….availability.AvailabilityRequestHandler.cacheResponse (AvailabilityRequestHandler.java:146)
      
      …apov.availability.AvailabilityRequestHandler.sendError (AvailabilityRequestHandler.java:204)
      
           com.mapov.availability.agoda.AgodaAvailability.run (AgodaAvailability.java:93)
      
            java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1142)
      
           java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:617)
      
                                         java.lang.Thread.run (Thread.java:745)
      
      
      caused by java.lang.InterruptedException
      …locks.AbstractQueuedSynchronizer.tryAcquireSharedNanos (AbstractQueuedSynchronizer.java:1326)
      
                    java.util.concurrent.Semaphore.tryAcquire (Semaphore.java:409)
      
      …ngodb.internal.connection.ConcurrentPool.acquirePermit (ConcurrentPool.java:180)
      
           com.mongodb.internal.connection.ConcurrentPool.get (ConcurrentPool.java:126)
      
      …b.connection.DefaultConnectionPool.getPooledConnection (DefaultConnectionPool.java:250)
      
             com.mongodb.connection.DefaultConnectionPool.get (DefaultConnectionPool.java:91)
      
             com.mongodb.connection.DefaultConnectionPool.get (DefaultConnectionPool.java:80)
      
           com.mongodb.connection.DefaultServer.getConnection (DefaultServer.java:72)
      
      …erBinding$ClusterBindingConnectionSource.getConnection (ClusterBinding.java:86)
      
      …mongodb.operation.OperationHelper.withConnectionSource (OperationHelper.java:228)
      
         com.mongodb.operation.OperationHelper.withConnection (OperationHelper.java:221)
      
        com.mongodb.operation.MixedBulkWriteOperation.execute (MixedBulkWriteOperation.java:168)
      
        com.mongodb.operation.MixedBulkWriteOperation.execute (MixedBulkWriteOperation.java:74)
      
                                    com.mongodb.Mongo.execute (Mongo.java:782)
      
                                  com.mongodb.Mongo$2.execute (Mongo.java:765)
      
      ….mongodb.MongoCollectionImpl.executeSingleWriteRequest (MongoCollectionImpl.java:515)
      
                   com.mongodb.MongoCollectionImpl.replaceOne (MongoCollectionImpl.java:344)
      
       com.mapov.availability.AvailabilityCache.cacheResponse (AvailabilityCache.java:62)
      
       com.mapov.availability.AvailabilityCache.cacheResponse (AvailabilityCache.java:45)
      
      ….availability.AvailabilityRequestHandler.cacheResponse (AvailabilityRequestHandler.java:146)
      
      …apov.availability.AvailabilityRequestHandler.sendError (AvailabilityRequestHandler.java:204)
      
           com.mapov.availability.agoda.AgodaAvailability.run (AgodaAvailability.java:93)
      
            java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1142)
      
           java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:617)
      
                                         java.lang.Thread.run (Thread.java:745)
      

      We have a single MongoClient instance:

      package com.mapov.availability;
      
      import com.mongodb.MongoClient;
      import com.mongodb.client.MongoDatabase;
      
      /**
       *
       * @author Justin
       */
      public class MongoConnection {
        private static MongoClient mongoClient = null;
        
        private MongoConnection() {
          // Private constructor
        }
        
        public static MongoDatabase getMapovDB() {
          if( mongoClient == null) {
            mongoClient = new MongoClient();
          }
          return mongoClient.getDatabase("mapov");
        }
      }
      
      

      This is the cache code, called from multiple threads:

      package com.mapov.availability;
      
      import com.mapov.util.Util;
      import com.mongodb.BasicDBObject;
      import com.mongodb.client.MongoCollection;
      import com.mongodb.client.MongoDatabase;
      import com.mongodb.client.model.Filters;
      import com.mongodb.client.model.UpdateOptions;
      import java.util.logging.Logger;
      import org.bson.Document;
      import org.bson.conversions.Bson;
      import org.joda.time.DateTime;
      import static com.mongodb.client.model.Filters.*;
      import static com.mongodb.client.model.Sorts.*;
      
      /**
       *
       * @author Justin
       */
      public class AvailabilityCache {
      
        private static final Logger logger = Logger.getLogger(AvailabilityCache.class.getName());
        private static final int cacheExpirySeconds = 3600; // Default cache time is 1 hour
        private final MongoCollection<Document> cacheCollection;
      
        public AvailabilityCache() {
          MongoDatabase mapovDB = MongoConnection.getMapovDB();
          this.cacheCollection = mapovDB.getCollection("availability");
        }
      
        private BasicDBObject buildKey(AvailabilityRequest request, AvailabilityResponse response) {
          BasicDBObject key = new BasicDBObject("startDate", request.startDate);
          key.append("endDate", request.endDate);
          key.append("locale", request.locale);
          key.append("rooms", Util.implode(request.rooms, ","));
          key.append("children", Util.implode(request.children, ","));
          key.append("cpID", response.cpID);
          key.append("providerPropertyID", response.providerPropertyID);
          key.append("currency", request.currencyCode);
      
          return key;
        }
      
        public void cacheResponse(AvailabilityRequest request, AvailabilityResponse response) {
          cacheResponse(request, response, cacheExpirySeconds);
        }
      
        public void cacheResponse(AvailabilityRequest request, AvailabilityResponse response, int cacheExpirySeconds) {
          BasicDBObject key = buildKey(request, response);
      
          Document doc = new Document();
          doc.append("_id", key);
          doc.append("rate", (int)response.rate*100);
          doc.append("deepLink", response.deepLink);
          doc.append("availableRooms", response.availableRooms);
          doc.append("error", response.error);
          doc.append("errorMsg", response.errorMsg);
          DateTime expiry = DateTime.now().plusSeconds(cacheExpirySeconds);
          doc.append("expireAt", expiry.toDate());
          UpdateOptions uo = new UpdateOptions();
          uo.upsert(true);
          cacheCollection.replaceOne(Filters.eq("_id", key),doc, uo);//Upserts
        }
      
        public boolean checkCache(AvailabilityRequest request, AvailabilityResponse response) {
          boolean found = false;
          
          BasicDBObject key = buildKey(request, response);
          Bson query = eq("_id", key);
          Bson orderBy = descending("expireAt");
      
          Document result = (Document)cacheCollection.find(query).sort(orderBy).first();
          if( result!=null) {
            response.rate = (Integer)result.get("rate")/100;
            response.deepLink = (String)result.get("deepLink");
            response.error = (Integer)result.get("error");
            response.errorMsg = (String)result.get("errorMsg");
            if( result.containsKey("availableRooms")) {
              response.availableRooms = (Integer)result.get("availableRooms");
            }
            found = true;
            //logger.log(Level.INFO, "Cache match: {0}", response);
          }
      
          return found;
        }
      }
      

            Assignee:
            Unassigned Unassigned
            Reporter:
            justinknight Justin Knight
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: