@Override
  public synchronized void close() throws SQLException {
    try {
      closeLock.writeLock().lock();
      if (closed) {
        return;
      }
      closed = true;
    } finally {
      closeLock.writeLock().unlock();
    }

    try {
      Collection<ConnectionQueryServices> connectionQueryServices =
          connectionQueryServicesMap.values();
      try {
        SQLCloseables.closeAll(connectionQueryServices);
      } finally {
        connectionQueryServices.clear();
      }
    } finally {
      if (services != null) {
        try {
          services.close();
        } finally {
          ExecutorService executor = services.getExecutor();
          // Even if something wrong happened while closing services above, we still
          // want to set it to null. Otherwise, we will end up having a possibly non-working
          // services instance.
          services = null;
          executor.shutdown();
        }
      }
    }
  }
 @Override
 protected ConnectionQueryServices getConnectionQueryServices(String url, Properties info)
     throws SQLException {
   try {
     closeLock.readLock().lock();
     checkClosed();
     ConnectionInfo connInfo = ConnectionInfo.create(url);
     QueryServices services = getQueryServices();
     ConnectionInfo normalizedConnInfo = connInfo.normalize(services.getProps());
     ConnectionQueryServices connectionQueryServices =
         connectionQueryServicesMap.get(normalizedConnInfo);
     if (connectionQueryServices == null) {
       if (normalizedConnInfo.isConnectionless()) {
         connectionQueryServices =
             new ConnectionlessQueryServicesImpl(services, normalizedConnInfo);
       } else {
         connectionQueryServices =
             new ConnectionQueryServicesImpl(services, normalizedConnInfo, info);
       }
       ConnectionQueryServices prevValue =
           connectionQueryServicesMap.putIfAbsent(normalizedConnInfo, connectionQueryServices);
       if (prevValue != null) {
         connectionQueryServices = prevValue;
       }
     }
     boolean success = false;
     SQLException sqlE = null;
     try {
       connectionQueryServices.init(url, info);
       success = true;
     } catch (SQLException e) {
       sqlE = e;
     } finally {
       if (!success) {
         try {
           connectionQueryServices.close();
         } catch (SQLException e) {
           if (sqlE == null) {
             sqlE = e;
           } else {
             sqlE.setNextException(e);
           }
         } finally {
           // Remove from map, as initialization failed
           connectionQueryServicesMap.remove(normalizedConnInfo);
           if (sqlE != null) {
             throw sqlE;
           }
         }
       }
     }
     return connectionQueryServices;
   } finally {
     closeLock.readLock().unlock();
   }
 }