/** This method is synchronized because we want it to be atomic with the cursors being used */
  private long checkMinPage(List<PageSubscription> cursorList) {
    long minPage = Long.MAX_VALUE;

    for (PageSubscription cursor : cursorList) {
      long firstPage = cursor.getFirstPage();
      if (log.isDebugEnabled()) {
        log.debug(
            this.pagingStore.getAddress()
                + " has a cursor "
                + cursor
                + " with first page="
                + firstPage);
      }
      if (firstPage < minPage) {
        minPage = firstPage;
      }
    }

    if (log.isDebugEnabled()) {
      log.debug(this.pagingStore.getAddress() + " has minPage=" + minPage);
    }

    return minPage;
  }
  public synchronized PageSubscription createSubscription(
      long cursorID, Filter filter, boolean persistent) {
    if (log.isDebugEnabled()) {
      log.debug(
          this.pagingStore.getAddress()
              + " creating subscription "
              + cursorID
              + " with filter "
              + filter,
          new Exception("trace"));
    }
    PageSubscription activeCursor = activeCursors.get(cursorID);
    if (activeCursor != null) {
      throw new IllegalStateException("Cursor " + cursorID + " had already been created");
    }

    activeCursor =
        new PageSubscriptionImpl(
            this, pagingStore, storageManager, executor, filter, cursorID, persistent);
    activeCursors.put(cursorID, activeCursor);
    return activeCursor;
  }
Example #3
0
  private void deployClusterConnection(final ClusterConnectionConfiguration config)
      throws Exception {
    if (config.getName() == null) {
      ClusterManagerImpl.log.warn(
          "Must specify a unique name for each cluster connection. This one will not be deployed.");

      return;
    }

    if (config.getAddress() == null) {
      ClusterManagerImpl.log.warn(
          "Must specify an address for each cluster connection. This one will not be deployed.");

      return;
    }

    TransportConfiguration connector =
        configuration.getConnectorConfigurations().get(config.getConnectorName());

    if (connector == null) {
      log.warn(
          "No connector with name '"
              + config.getConnectorName()
              + "'. The cluster connection will not be deployed.");
      return;
    }

    if (clusterConnections.containsKey(config.getName())) {
      log.warn(
          "Cluster Configuration  '"
              + config.getConnectorName()
              + "' already exists. The cluster connection will not be deployed.",
          new Exception("trace"));
      return;
    }

    ClusterConnectionImpl clusterConnection;

    if (config.getDiscoveryGroupName() != null) {
      DiscoveryGroupConfiguration dg =
          configuration.getDiscoveryGroupConfigurations().get(config.getDiscoveryGroupName());

      if (dg == null) {
        ClusterManagerImpl.log.warn(
            "No discovery group with name '"
                + config.getDiscoveryGroupName()
                + "'. The cluster connection will not be deployed.");
        return;
      }

      if (log.isDebugEnabled()) {
        log.debug(
            this
                + " Starting a Discovery Group Cluster Connection, name="
                + config.getDiscoveryGroupName()
                + ", dg="
                + dg);
      }

      clusterConnection =
          new ClusterConnectionImpl(
              this,
              dg,
              connector,
              new SimpleString(config.getName()),
              new SimpleString(config.getAddress()),
              config.getMinLargeMessageSize(),
              config.getClientFailureCheckPeriod(),
              config.getConnectionTTL(),
              config.getRetryInterval(),
              config.getRetryIntervalMultiplier(),
              config.getMaxRetryInterval(),
              config.getReconnectAttempts(),
              config.getCallTimeout(),
              config.getCallFailoverTimeout(),
              config.isDuplicateDetection(),
              config.isForwardWhenNoConsumers(),
              config.getConfirmationWindowSize(),
              executorFactory,
              server,
              postOffice,
              managementService,
              scheduledExecutor,
              config.getMaxHops(),
              nodeUUID,
              backup,
              server.getConfiguration().getClusterUser(),
              server.getConfiguration().getClusterPassword(),
              config.isAllowDirectConnectionsOnly());
    } else {
      TransportConfiguration[] tcConfigs =
          config.getStaticConnectors() != null
              ? connectorNameListToArray(config.getStaticConnectors())
              : null;

      if (log.isDebugEnabled()) {
        log.debug(this + " defining cluster connection towards " + Arrays.toString(tcConfigs));
      }

      clusterConnection =
          new ClusterConnectionImpl(
              this,
              tcConfigs,
              connector,
              new SimpleString(config.getName()),
              new SimpleString(config.getAddress()),
              config.getMinLargeMessageSize(),
              config.getClientFailureCheckPeriod(),
              config.getConnectionTTL(),
              config.getRetryInterval(),
              config.getRetryIntervalMultiplier(),
              config.getMaxRetryInterval(),
              config.getReconnectAttempts(),
              config.getCallTimeout(),
              config.getCallFailoverTimeout(),
              config.isDuplicateDetection(),
              config.isForwardWhenNoConsumers(),
              config.getConfirmationWindowSize(),
              executorFactory,
              server,
              postOffice,
              managementService,
              scheduledExecutor,
              config.getMaxHops(),
              nodeUUID,
              backup,
              server.getConfiguration().getClusterUser(),
              server.getConfiguration().getClusterPassword(),
              config.isAllowDirectConnectionsOnly());
    }

    if (defaultClusterConnection == null) {
      defaultClusterConnection = clusterConnection;
    }

    managementService.registerCluster(clusterConnection, config);

    clusterConnections.put(config.getName(), clusterConnection);

    if (log.isDebugEnabled()) {
      log.debug("ClusterConnection.start at " + clusterConnection, new Exception("trace"));
    }
  }
  public void cleanup() {
    ArrayList<Page> depagedPages = new ArrayList<Page>();

    while (true) {
      if (pagingStore.lock(100)) {
        break;
      }
      if (!pagingStore.isStarted()) return;
    }

    synchronized (this) {
      try {
        if (!pagingStore.isStarted()) {
          return;
        }

        if (pagingStore.getNumberOfPages() == 0) {
          return;
        }

        if (log.isDebugEnabled()) {
          log.debug("Asserting cleanup for address " + this.pagingStore.getAddress());
        }

        ArrayList<PageSubscription> cursorList = new ArrayList<PageSubscription>();
        cursorList.addAll(activeCursors.values());

        long minPage = checkMinPage(cursorList);

        if (minPage == pagingStore.getCurrentWritingPage()
            && pagingStore.getCurrentPage().getNumberOfMessages() > 0) {
          boolean complete = true;

          for (PageSubscription cursor : cursorList) {
            if (!cursor.isComplete(minPage)) {
              if (log.isDebugEnabled()) {
                log.debug("Cursor " + cursor + " was considered incomplete at page " + minPage);
              }

              complete = false;
              break;
            } else {
              if (log.isDebugEnabled()) {
                log.debug("Cursor " + cursor + "was considered **complete** at page " + minPage);
              }
            }
          }

          if (!pagingStore.isStarted()) {
            return;
          }

          if (complete) {

            if (log.isDebugEnabled()) {
              log.debug(
                  "Address "
                      + pagingStore.getAddress()
                      + " is leaving page mode as all messages are consumed and acknowledged from the page store");
            }

            pagingStore.forceAnotherPage();

            Page currentPage = pagingStore.getCurrentPage();

            storePositions(cursorList, currentPage);

            pagingStore.stopPaging();

            // This has to be called after we stopped paging
            for (PageSubscription cursor : cursorList) {
              cursor.scheduleCleanupCheck();
            }
          }
        }

        for (long i = pagingStore.getFirstPage(); i < minPage; i++) {
          Page page = pagingStore.depage();
          if (page == null) {
            break;
          }
          depagedPages.add(page);
        }

        if (pagingStore.getNumberOfPages() == 0
            || pagingStore.getNumberOfPages() == 1
                && pagingStore.getCurrentPage().getNumberOfMessages() == 0) {
          pagingStore.stopPaging();
        } else {
          if (log.isTraceEnabled()) {
            log.trace(
                "Couldn't cleanup page on address "
                    + this.pagingStore.getAddress()
                    + " as numberOfPages == "
                    + pagingStore.getNumberOfPages()
                    + " and currentPage.numberOfMessages = "
                    + pagingStore.getCurrentPage().getNumberOfMessages());
          }
        }
      } catch (Exception ex) {
        log.warn("Couldn't complete cleanup on paging", ex);
        return;
      } finally {
        pagingStore.unlock();
      }
    }

    try {
      for (Page depagedPage : depagedPages) {
        PageCache cache;
        PagedMessage[] pgdMessages;
        synchronized (softCache) {
          cache = softCache.get((long) depagedPage.getPageId());
        }

        if (isTrace) {
          log.trace("Removing page " + depagedPage.getPageId() + " from page-cache");
        }

        if (cache == null) {
          // The page is not on cache any more
          // We need to read the page-file before deleting it
          // to make sure we remove any large-messages pending
          storageManager.beforePageRead();

          List<PagedMessage> pgdMessagesList = null;
          try {
            depagedPage.open();
            pgdMessagesList = depagedPage.read(storageManager);
          } finally {
            try {
              depagedPage.close();
            } catch (Exception e) {
            }

            storageManager.afterPageRead();
          }
          depagedPage.close();
          pgdMessages = pgdMessagesList.toArray(new PagedMessage[pgdMessagesList.size()]);
        } else {
          pgdMessages = cache.getMessages();
        }

        depagedPage.delete(pgdMessages);

        synchronized (softCache) {
          softCache.remove((long) depagedPage.getPageId());
        }
      }
    } catch (Exception ex) {
      log.warn("Couldn't complete cleanup on paging", ex);
      return;
    }
  }