Package org.apache.sandesha2.storage

Examples of org.apache.sandesha2.storage.Transaction


    super(POLLING_MANAGER_WAIT_TIME);
  }
 
  protected boolean internalRun() {
    if(log.isDebugEnabled()) log.debug("Enter: PollingManager::internalRun");
    Transaction t = null;
    try {
      // If we have request scheduled, handle them first, and then pick
      // pick a sequence using a round-robin approach. Scheduled polls
      // bypass the normal polling checks, to make sure that they happen
      boolean forcePoll = false;
      SequenceEntry entry = null;
      synchronized (this) {
        if(!scheduledPollingRequests.isEmpty()) {
          entry = (SequenceEntry) scheduledPollingRequests.removeFirst();
          forcePoll = true;
        }
      }
      if(entry == null) {
        ArrayList allSequencesList = getSequences();
        int size = allSequencesList.size();
        if(log.isDebugEnabled()) log.debug("Choosing one from " + size + " sequences");
        if(nextIndex >= size) {
          nextIndex = 0;
          // We just looped over the set of sequences, so sleep before we try
          // polling them again.
          if (log.isDebugEnabled()) log.debug("Exit: PollingManager::internalRun, looped over all sequences, sleeping");
          return true;
        }
 
        entry = (SequenceEntry) allSequencesList.get(nextIndex++);
      }
      if(log.isDebugEnabled()) log.debug("Chose sequence " + entry.getSequenceId());

      t = storageManager.getTransaction();
      if(entry.isRmSource()) {
        pollRMSSide(entry, forcePoll);
      } else {
        pollRMDSide(entry, forcePoll);
      }
      if(t != null) t.commit();
      t = null;

    } catch (Exception e) {
      if(log.isDebugEnabled()) log.debug("Exception", e);
    } finally {
      if(t != null && t.isActive()) {
        try {
          t.rollback();
        } catch(Exception e2) {
          if(log.isDebugEnabled()) log.debug("Exception during rollback", e2);
        }
      }
    }
View Full Code Here


    StorageManager storageManager =
      SandeshaUtil.getSandeshaStorageManager(rmMsgCtx.getConfigurationContext(),
          rmMsgCtx.getConfigurationContext().getAxisConfiguration());
   
    Transaction transaction = null;
   
    try {
      transaction = storageManager.getTransaction();
   
      // Check that both the Sequence header and message body have been secured properly
      RMDBeanMgr mgr = storageManager.getRMDBeanMgr();
      RMDBean bean = mgr.retrieve(sequenceId);
     
      if(bean != null && bean.getSecurityTokenData() != null) {
        SecurityManager secManager = SandeshaUtil.getSecurityManager(rmMsgCtx.getConfigurationContext());
       
        QName seqName = new QName(rmMsgCtx.getRMNamespaceValue(), Sandesha2Constants.WSRM_COMMON.SEQUENCE);
       
        SOAPEnvelope envelope = rmMsgCtx.getSOAPEnvelope();
        OMElement body = envelope.getBody();
        OMElement seqHeader = envelope.getHeader().getFirstChildWithName(seqName);
       
        SecurityToken token = secManager.recoverSecurityToken(bean.getSecurityTokenData());
       
        secManager.checkProofOfPossession(token, seqHeader, rmMsgCtx.getMessageContext());
        secManager.checkProofOfPossession(token, body, rmMsgCtx.getMessageContext());
      }
   
      if (bean != null) {
       
        if (msgNo == 0) {
          String message = SandeshaMessageHelper.getMessage(SandeshaMessageKeys.invalidMsgNumber, Long
              .toString(msgNo));
          log.debug(message);
          throw new SandeshaException(message);
        }
   
        // Get the server completed message ranges list
        RangeString serverCompletedMessageRanges = bean.getServerCompletedMessages();
   
        // See if the message is in the list of completed ranges
        boolean msgNoPresentInList =
          serverCompletedMessageRanges.isMessageNumberInRanges(msgNo);
         
        if (!msgNoPresentInList) {
          serverCompletedMessageRanges.addRange(new Range(msgNo));
         
          storageManager.getRMDBeanMgr().update(bean);
        }
        else {
          if (log.isDebugEnabled())
            log.debug("Detected duplicate message " + msgNo);
          rmMsgCtx.getMessageContext().setRelationships(null);
          // Add the duplicate RM AxisOperation to the message
          AxisOperation duplicateMessageOperation = SpecSpecificConstants.getWSRMOperation(
              Sandesha2Constants.MessageTypes.DUPLICATE_MESSAGE,
              Sandesha2Constants.SPEC_VERSIONS.v1_0,
              rmMsgCtx.getMessageContext().getAxisService());
          rmMsgCtx.getMessageContext().setAxisOperation(duplicateMessageOperation);
        }
             
      } else {
        if (log.isDebugEnabled())
          log.debug("Detected message for no sequence " + msgNo);
        rmMsgCtx.getMessageContext().setRelationships(null);
        // Add the duplicate RM AxisOperation to the message
        AxisOperation duplicateMessageOperation = SpecSpecificConstants.getWSRMOperation(
            Sandesha2Constants.MessageTypes.DUPLICATE_MESSAGE,
            Sandesha2Constants.SPEC_VERSIONS.v1_0,
            rmMsgCtx.getMessageContext().getAxisService());
        rmMsgCtx.getMessageContext().setAxisOperation(duplicateMessageOperation);
      }
     
      if(transaction != null && transaction.isActive()) transaction.commit();
      transaction = null;
    }
    finally {
      if (transaction != null && transaction.isActive())
        transaction.rollback();
    }
    if (log.isDebugEnabled())
      log.debug("Exit: SandeshaGlobalInHandler::processApplicationMessage");
  }
View Full Code Here

  }

  protected boolean internalRun() {
    if (log.isDebugEnabled()) log.debug("Enter: Sender::internalRun");

    Transaction transaction = null;
    boolean sleep = false;

    try {
      // Pick a sequence using a round-robin approach
      ArrayList allSequencesList = getSequences();
      int size = allSequencesList.size();
      if (log.isDebugEnabled())
        log.debug("Choosing one from " + size + " sequences");
      if(nextIndex >= size) {
        nextIndex = 0;

        // We just looped over the set of sequences. If we didn't process any
        // messages on this loop then we sleep before the next one
        if(size == 0 || !processedMessage) {
          sleep = true;
        }
        processedMessage = false;
       
        // At this point - delete any sequences that have timed out, or been terminated.
        deleteTerminatedSequences(storageManager);

        // Also clean up and sender beans that are not yet eligible for sending, but
        // are blocking the transport threads.
        unblockTransportThreads(storageManager);
       
        // Finally, check for messages that can only be serviced by polling, and warn
        // the user if they are too old
        checkForOrphanMessages(storageManager);

        if (log.isDebugEnabled()) log.debug("Exit: Sender::internalRun, looped over all sequences, sleep " + sleep);
        return sleep;
      }

      SequenceEntry entry = (SequenceEntry) allSequencesList.get(nextIndex++);
      String sequenceId = entry.getSequenceId();
      if (log.isDebugEnabled())
        log.debug("Chose sequence " + sequenceId);

      transaction = storageManager.getTransaction();

      String rmVersion = null;
      // Check that the sequence is still valid
      boolean found = false;
      if(entry.isRmSource()) {
        RMSBean matcher = new RMSBean();
        matcher.setInternalSequenceID(sequenceId);
        matcher.setTerminated(false);
        RMSBean rms = storageManager.getRMSBeanMgr().findUnique(matcher);
        if(rms != null && !rms.isTerminated() && !rms.isTimedOut()) {
          sequenceId = rms.getSequenceID();         
          if (SequenceManager.hasSequenceTimedOut(rms, sequenceId, storageManager))         
            SequenceManager.finalizeTimedOutSequence(rms.getInternalSequenceID(), null, storageManager);
          else
            found = true;
          rmVersion = rms.getRMVersion();
        }
       
      } else {
        RMDBean matcher = new RMDBean();
        matcher.setSequenceID(sequenceId);
        matcher.setTerminated(false);
        RMDBean rmd = storageManager.getRMDBeanMgr().findUnique(matcher);
        if(rmd != null) {
          found = true;
          rmVersion = rmd.getRMVersion();
        }
      }
      if (!found) {
        stopThreadForSequence(sequenceId, entry.isRmSource());
        if (log.isDebugEnabled()) log.debug("Exit: Sender::internalRun, sequence has ended");
        return false;
      }
     
      SenderBeanMgr mgr = storageManager.getSenderBeanMgr();
      SenderBean senderBean = mgr.getNextMsgToSend(sequenceId);
     
      if (senderBean == null) {
        if (log.isDebugEnabled()) log.debug("Exit: Sender::internalRun, no message for this sequence");
        return false; // Move on to the next sequence in the list
      }

      // work Id is used to define the piece of work that will be
      // assigned to the Worker thread,
      // to handle this Sender bean.
     
      //workId contains a timeTiSend part to cater for retransmissions.
      //This will cause retransmissions to be treated as new work.
      String workId = senderBean.getMessageID() + senderBean.getTimeToSend();

      // check weather the bean is already assigned to a worker.
      if (getWorkerLock().isWorkPresent(workId)) {
        // As there is already a worker running we are probably looping
        // too fast, so sleep on the next loop.
        if (log.isDebugEnabled()) {
          String message = SandeshaMessageHelper.getMessage(
                  SandeshaMessageKeys.workAlreadyAssigned,
                  workId);
          log.debug("Exit: Sender::internalRun, " + message + ", sleeping");
        }
        return true;
      }

      if(transaction != null) {
        transaction.commit();
        transaction = null;
      }

      // start a worker which will work on this messages.
      SenderWorker worker = new SenderWorker(context, senderBean, rmVersion);
      worker.setLock(getWorkerLock());
      worker.setWorkId(workId);
      threadPool.execute(worker);

      // adding the workId to the lock after assigning it to a thread
      // makes sure
      // that all the workIds in the Lock are handled by threads.
      getWorkerLock().addWork(workId);

      // If we got to here then we found work to do on the sequence, so we should
      // remember not to sleep at the end of the list of sequences.
      processedMessage = true;
     
      if(transaction != null && transaction.isActive()) transaction.commit();
      transaction = null;

    } catch (Exception e) {

      // TODO : when this is the client side throw the exception to
      // the client when necessary.

     
      //TODO rollback only if a SandeshaStorageException.
      //This allows the other Exceptions to be used within the Normal flow.
     
      String message = SandeshaMessageHelper.getMessage(SandeshaMessageKeys.sendMsgError, e.toString());
      log.debug(message, e);
    } finally {
      if (transaction != null && transaction.isActive()) {
        try {
          transaction.rollback();
          transaction = null;
        } catch (Exception e) {
          String message = SandeshaMessageHelper
              .getMessage(SandeshaMessageKeys.rollbackError, e.toString());
          log.debug(message, e);
View Full Code Here

      log.debug("Enter: Sender::deleteTerminatedSequences");

    RMSBean finderBean = new RMSBean();
    finderBean.setTerminated(true);
   
    Transaction transaction = null;
   
    try {
      transaction = storageManager.getTransaction();
     
      SandeshaPolicyBean propertyBean =
        SandeshaUtil.getPropertyBean(storageManager.getContext().getAxisConfiguration());     

      long deleteTime = propertyBean.getSequenceRemovalTimeoutInterval();
      if (deleteTime < 0)
        deleteTime = 0;

      if (deleteTime > 0) {
        // Find terminated sequences.
        List rmsBeans = storageManager.getRMSBeanMgr().find(finderBean);
       
        deleteRMSBeans(rmsBeans, propertyBean, deleteTime);
       
        finderBean.setTerminated(false);
        finderBean.setTimedOut(true);
       
        // Find timed out sequences
        rmsBeans = storageManager.getRMSBeanMgr().find(finderBean);
             
        deleteRMSBeans(rmsBeans, propertyBean, deleteTime);
       
        // Remove any terminated RMDBeans.
        RMDBean finderRMDBean = new RMDBean();
        finderRMDBean.setTerminated(true);
       
        List rmdBeans = storageManager.getRMDBeanMgr().find(finderRMDBean);
 
        Iterator beans = rmdBeans.iterator();
        while (beans.hasNext()) {
          RMDBean rmdBean = (RMDBean)beans.next();
         
          long timeNow = System.currentTimeMillis();
          long lastActivated = rmdBean.getLastActivatedTime();
 
          // delete sequences that have been timedout or deleted for more than
          // the SequenceRemovalTimeoutInterval
          if ((lastActivated + deleteTime) < timeNow) {
            if (log.isDebugEnabled())
              log.debug("Deleting RMDBean " + deleteTime + " : " + rmdBean);
            storageManager.getRMDBeanMgr().delete(rmdBean.getSequenceID());
          }               
        }
      }

      // Terminate RMD Sequences that have been inactive.     
      if (propertyBean.getInactivityTimeoutInterval() > 0) {
        RMDBean finderRMDBean = new RMDBean();
        finderRMDBean.setTerminated(false);
       
        List rmdBeans = storageManager.getRMDBeanMgr().find(finderRMDBean);
     
        Iterator beans = rmdBeans.iterator();
        while (beans.hasNext()) {
          RMDBean rmdBean = (RMDBean)beans.next();
         
          long timeNow = System.currentTimeMillis();
          long lastActivated = rmdBean.getLastActivatedTime();
         
          if ((lastActivated + propertyBean.getInactivityTimeoutInterval()) < timeNow) {
            // Terminate
            rmdBean.setTerminated(true);
            rmdBean.setLastActivatedTime(timeNow);
            if (log.isDebugEnabled())
              log.debug(System.currentTimeMillis() + "Marking RMDBean as terminated " + rmdBean);
            storageManager.getRMDBeanMgr().update(rmdBean);
          }               
        }
      }      
     
      if(transaction != null && transaction.isActive()) transaction.commit();
      transaction = null;
     
    } catch (SandeshaException e) {
      if (log.isErrorEnabled())
        log.error(e);
    } finally {
      if(transaction != null && transaction.isActive()) {
        try {
          transaction.rollback();
        } catch (SandeshaStorageException e) {
          if (log.isDebugEnabled())
            log.debug("Caught exception rolling back transaction", e);
        }
      }
View Full Code Here

  private void unblockTransportThreads(StorageManager manager)
  throws SandeshaStorageException
  {
    if (log.isDebugEnabled()) log.debug("Enter: Sender::unblockTransportThreads");

    Transaction transaction = null;
    try {
      transaction = manager.getTransaction();
     
      // This finder will look for beans that have been locking the transport for longer than
      // the TRANSPORT_WAIT_TIME. The match method for SenderBeans does the time comparison
      // for us.
      SenderBean finder = new SenderBean();
      finder.setSend(false);
      finder.setTransportAvailable(true);
      finder.setTimeToSend(System.currentTimeMillis() - Sandesha2Constants.TRANSPORT_WAIT_TIME);
     
      List beans = manager.getSenderBeanMgr().find(finder);
      Iterator beanIter = beans.iterator();
      while(beanIter.hasNext()) {
        // The beans we have found are assigned to an internal sequence id, but the create
        // sequence has not completed yet (and perhaps never will). Server-side, most of the
        // info that we can usefully print is associated with the inbound sequence that generated
        // this message.
        SenderBean bean = (SenderBean) beanIter.next();
       
        // Load the message, so that we can free the transport (if there is one there). The
        // case we are trying to free up is when there is a request-response transport, and
        // it's still there waiting.
        MessageContext msgCtx = manager.retrieveMessageContext(bean.getMessageContextRefKey(), context);

        RequestResponseTransport t = null;
        MessageContext inMsg = null;
        OperationContext op = msgCtx.getOperationContext();
        if (op != null)
          inMsg = op.getMessageContext(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
        if (inMsg != null)
          t = (RequestResponseTransport) inMsg.getProperty(RequestResponseTransport.TRANSPORT_CONTROL);
 
        if((t != null || !t.getStatus().equals(RequestResponseTransportStatus.WAITING))) {
          if(log.isWarnEnabled()) {
            String message = SandeshaMessageHelper.getMessage(SandeshaMessageKeys.freeingTransport);
            log.warn(message);
          }
          // If the message is a reply, then the request may need to be acked. Rather
          // than just return a HTTP 202, we should try to send an ack.
          boolean sendAck = false;
          RMDBean inbound = null;
          String inboundSeq = bean.getInboundSequenceId();
          if(inboundSeq != null)
            inbound = SandeshaUtil.getRMDBeanFromSequenceId(manager, inboundSeq);
         
          if(inbound != null) {
            String acksTo = inbound.getAcksToEPR();
            EndpointReference acksToEPR = new EndpointReference(acksTo);
            if(acksTo == null || acksToEPR.hasAnonymousAddress())
              sendAck = true;
          }
         
          if(sendAck) {
            RMMsgContext rmMsgCtx = MsgInitializer.initializeMessage(msgCtx);
            RMMsgContext ackRMMsgCtx = AcknowledgementManager.generateAckMessage(
                rmMsgCtx, inbound, inbound.getSequenceID(), storageManager, true);
            AcknowledgementManager.sendAckNow(ackRMMsgCtx);
            msgCtx.getOperationContext().setProperty(org.apache.axis2.Constants.RESPONSE_WRITTEN, "true");
            t.signalResponseReady();
          } else {
            msgCtx.getOperationContext().setProperty(org.apache.axis2.Constants.RESPONSE_WRITTEN, "false");
            t.acknowledgeMessage(msgCtx);
          }
 
          // Mark the bean so that we know the transport is missing, and reset the send time
          bean.setTransportAvailable(false);
          bean.setTimeToSend(System.currentTimeMillis());
         
          // Update the bean
          manager.getSenderBeanMgr().update(bean);
        }
      }
 
      if(transaction != null && transaction.isActive()) transaction.commit();
      transaction = null;
     
    } catch(Exception e) {
      // There isn't much we can do here, so log the exception and continue.
      if(log.isDebugEnabled()) log.debug("Exception", e);
    } finally {
      if(transaction != null && transaction.isActive()) transaction.rollback();
    }
   
    if (log.isDebugEnabled()) log.debug("Exit: Sender::unblockTransportThreads");
  }
View Full Code Here

   
    ConfigurationContext configurationContext = msgContext.getConfigurationContext();
    RMMsgContext rmmsgContext = MsgInitializer.initializeMessage(msgContext);
    StorageManager storageManager = SandeshaUtil.getSandeshaStorageManager(configurationContext, configurationContext.getAxisConfiguration());
   
    Transaction transaction = storageManager.getTransaction();
   
    AxisService service;
    try {
      String sequenceID = (String) rmmsgContext
          .getProperty(Sandesha2Constants.MessageContextProperties.SEQUENCE_ID);
      service = null;
      if (sequenceID != null) {

        //If this is the RMD of the sequence
        RMDBeanMgr rmdBeanMgr = storageManager.getRMDBeanMgr();
        RMDBean rmdFindBean = new RMDBean();
        rmdFindBean.setSequenceID(sequenceID);

        RMDBean rmdBean = rmdBeanMgr.findUnique(rmdFindBean);
        if (rmdBean != null) {

          String serviceName = rmdBean.getServiceName();
          if (serviceName != null) {
            service = configurationContext.getAxisConfiguration()
                .getService(serviceName);
          }
        }

        if (service == null && rmdBean == null) {
          //If this is the RMD of the sequence
          RMSBeanMgr rmsBeanMgr = storageManager.getRMSBeanMgr();
          RMSBean rmsfindBean = new RMSBean();
          rmsfindBean.setSequenceID(sequenceID);

          RMSBean rmsBean = rmsBeanMgr.findUnique(rmsfindBean);

          if (rmsBean != null) {
            String serviceName = rmsBean.getServiceName();
            if (serviceName != null) {
              service = configurationContext
                  .getAxisConfiguration().getService(
                      serviceName);
            }
          }
        }

      }
    } finally  {
      transaction.commit();
    }   
   
    return service;
  }
View Full Code Here

  private void checkForOrphanMessages(StorageManager manager)
  throws SandeshaStorageException
  {
    if(log.isDebugEnabled()) log.debug("Enter: Sender::checkForOrphanMessages");
   
    Transaction tran = null;
    try {
      tran = manager.getTransaction();
 
      // This finder will look for beans that should have been sent, but could not be sent
      // because they need a MakeConnection message to come in to pick it up. We also factor
      // in TRANSPORT_WAIT_TIME to give the MakeConnection a chance to arrive.
      SenderBean finder = new SenderBean();
      finder.setSend(true);
      finder.setTransportAvailable(false);
      finder.setTimeToSend(System.currentTimeMillis() - Sandesha2Constants.TRANSPORT_WAIT_TIME);
     
      List beans = manager.getSenderBeanMgr().find(finder);
      Iterator beanIter = beans.iterator();
      while(beanIter.hasNext()) {
        SenderBean bean = (SenderBean) beanIter.next();
       
        // Emit a message to warn the user that MakeConnections are not arriving to pick
        // messages up
        if(log.isWarnEnabled()) {
          String messageType = Integer.toString(bean.getMessageType());
          String message = SandeshaMessageHelper.getMessage(SandeshaMessageKeys.noPolling, messageType);
          log.warn(message);
        }
       
        // Update the bean so that we won't emit another message for another TRANSPORT_WAIT_TIME
        bean.setTimeToSend(System.currentTimeMillis());
        manager.getSenderBeanMgr().update(bean);
      }
 
      if(tran != null && tran.isActive()) tran.commit();
      tran = null;
 
    } catch(Exception e) {
      // There isn't much we can do here, so log the exception and continue.
      if(log.isDebugEnabled()) log.debug("Exception", e);
    } finally {
      if(tran != null && tran.isActive()) tran.rollback();
    }
   
    if(log.isDebugEnabled()) log.debug("Exit: Sender::checkForOrphanMessages");
  }
View Full Code Here

        InvokerBean selector = new InvokerBean();
        selector.setSequenceID(sequenceID);
        Iterator stMapIt = storageMapMgr.find(selector).iterator();
       
        long highestMsgNumberInvoked = 0;
        Transaction transaction = null;
       
        //invoke each bean in turn.
        //NOTE: here we are breaking ordering
        while(stMapIt.hasNext()){
          //invoke the app
          try{
            transaction = storageManager.getTransaction();
            InvokerBean invoker = (InvokerBean)stMapIt.next();
           
            // start a new worker thread and let it do the invocation.
            String workId = sequenceID + "::" + invoker.getMsgNo(); //creating a workId to uniquely identify the
             //piece of work that will be assigned to the Worker.
           
            String messageContextKey = invoker.getMessageContextRefKey();
            InvokerWorker worker = new InvokerWorker(context,
                messageContextKey,
                true); //want to ignore the enxt msg number
           
            worker.setLock(getWorkerLock());
            worker.setWorkId(workId);
           
            //before we execute we need to set the
           
            threadPool.execute(worker);
         
            //adding the workId to the lock after assigning it to a thread makes sure
            //that all the workIds in the Lock are handled by threads.
            getWorkerLock().addWork(workId);

            long msgNumber = invoker.getMsgNo();
            //if necessary, update the "next message number" bean under this transaction
            if(msgNumber>highestMsgNumberInvoked){
              highestMsgNumberInvoked = invoker.getMsgNo();
              rMDBean.setNextMsgNoToProcess(highestMsgNumberInvoked+1);
             
              if(allowLaterDeliveryOfMissingMessages){
                //we also need to update the sequence OUT_OF_ORDER_RANGES property
                //so as to include our latest view of this outOfOrder range.
                //We do that here (rather than once at the end) so that we reamin
                //transactionally consistent
                Range r = new Range(firstMessageInOutOfOrderWindow,highestMsgNumberInvoked);
                   
                RangeString rangeString = null;
                if(rMDBean.getOutOfOrderRanges()==null){
                  //insert a new blank one one
                  rangeString = new RangeString();
                }
                else{
                  rangeString = rMDBean.getOutOfOrderRanges();
                }
                //update the range String with the new value
                rangeString.addRange(r);
                rMDBean.setOutOfOrderRanges(rangeString);
              }
             
              rmdBeanMgr.update(rMDBean);
            }
           
            if(transaction != null && transaction.isActive()) transaction.commit();
            transaction = null;
          }
          catch(Exception e){
            // Just log the error
            if(log.isDebugEnabled()) log.debug("Exception", e);
          } finally {
            if(transaction != null && transaction.isActive()) {
              transaction.rollback();
              transaction = null;
            }
          }
   
        }//end while
View Full Code Here

  public Transaction getTransaction() {
    // Calling getTransaction is the only way to set up a new transaction. If you
    // do some work that requires a tran without there being a transaction in scope
    // then the enlist method will throw an exception.
    Transaction result = null;
    synchronized (transactions) {
      Thread key = Thread.currentThread();
      String name = key.getName();
      int    id = System.identityHashCode(key);
      result = (Transaction) transactions.get(key);
View Full Code Here

 
  protected boolean internalRun() {
    if (log.isDebugEnabled()) log.debug("Enter: Invoker::internalRun");
   
    boolean sleep = false;
    Transaction transaction = null;

    try {
      RMDBeanMgr nextMsgMgr = storageManager.getRMDBeanMgr();

      InvokerBeanMgr storageMapMgr = storageManager
          .getInvokerBeanMgr();

      transaction = storageManager.getTransaction();
     
      // Pick a sequence using a round-robin approach
      ArrayList allSequencesList = getSequences();
      int size = allSequencesList.size();
      log.debug("Choosing one from " + size + " sequences");
      if(nextIndex >= size) {
        nextIndex = 0;

        // We just looped over the set of sequences. If we didn't process any
        // messages on this loop then we sleep before the next one
        if(size == 0 || !processedMessage) {
          sleep = true;
        }
        processedMessage = false;
       
        if (log.isDebugEnabled()) log.debug("Exit: Invoker::internalRun, looped over all sequences, sleep " + sleep);
        return sleep;
      }

      SequenceEntry entry = (SequenceEntry) allSequencesList.get(nextIndex++);
      String sequenceId = entry.getSequenceId();
      log.debug("Chose sequence " + sequenceId);

      RMDBean nextMsgBean = nextMsgMgr.retrieve(sequenceId);
      if (nextMsgBean == null) {
        log.debug("Next message not set correctly. Removing invalid entry.");

        stopThreadForSequence(sequenceId, entry.isRmSource());
        allSequencesList = getSequences();
        if (allSequencesList.size() == 0)
          sleep = true;

        if (log.isDebugEnabled()) log.debug("Exit: Invoker::internalRun, sleep " + sleep);
        return sleep;
      }

      long nextMsgno = nextMsgBean.getNextMsgNoToProcess();
      if (nextMsgno <= 0) {
        // Make sure we sleep on the next loop, so that we don't spin in a tight loop
        sleep = true;
        if (log.isDebugEnabled())
          log.debug("Invalid Next Message Number " + nextMsgno);
        String message = SandeshaMessageHelper.getMessage(
            SandeshaMessageKeys.invalidMsgNumber, Long
                .toString(nextMsgno));
        throw new SandeshaException(message);
      }

      InvokerBean selector = new InvokerBean();
      selector.setSequenceID(sequenceId);
      selector.setMsgNo(nextMsgno);
      List invokerBeans = storageMapMgr.find(selector);
     
      //add any msgs that belong to out of order windows
      addOutOfOrderInvokerBeansToList(sequenceId,
          storageManager, invokerBeans);
     
      // If there aren't any beans to process then move on to the next sequence
      if (invokerBeans.size() == 0) {
        if (log.isDebugEnabled()) log.debug("Exit: Invoker::internalRun, no beans to invoke on sequence " + sequenceId + ", sleep " + sleep);
        return sleep;
      }
     
      Iterator stMapIt = invokerBeans.iterator();

      //TODO correct the locking mechanism to have one lock per sequence.
      //TODO should this be a while, not an if?
      if (stMapIt.hasNext()) { //some invokation work is present
       
        InvokerBean bean = (InvokerBean) stMapIt.next();
        //see if this is an out of order msg
        boolean beanIsOutOfOrderMsg = bean.getMsgNo()!=nextMsgno;
       
        String workId = sequenceId + "::" + bean.getMsgNo();
                                  //creating a workId to uniquely identify the
                                 //piece of work that will be assigned to the Worker.
                 
        //check whether the bean is already assigned to a worker.
        if (getWorkerLock().isWorkPresent(workId)) {
          // As there is already a worker assigned we are probably dispatching
          // messages too quickly, so we sleep before trying the next sequence.
          sleep = true;
          String message = SandeshaMessageHelper.getMessage(SandeshaMessageKeys.workAlreadyAssigned, workId);
          if (log.isDebugEnabled()) log.debug("Exit: Invoker::internalRun, " + message + ", sleep " + sleep);
          return sleep;
        }

        String messageContextKey = bean.getMessageContextRefKey();
       
        if(transaction != null) {
          transaction.commit();
          transaction = null;
        }

        // start a new worker thread and let it do the invocation.
        InvokerWorker worker = new InvokerWorker(context,
            messageContextKey,
            beanIsOutOfOrderMsg); //only ignore nextMsgNumber if the bean is an
                                  //out of order message
       
        worker.setLock(getWorkerLock());
        worker.setWorkId(workId);
       
        threadPool.execute(worker);
       
        //adding the workId to the lock after assigning it to a thread makes sure
        //that all the workIds in the Lock are handled by threads.
        getWorkerLock().addWork(workId);
       
        processedMessage = true;
      }
     
      if(transaction != null && transaction.isActive()) transaction.commit();
      transaction = null;
    } catch (Exception e) {
      String message = SandeshaMessageHelper
          .getMessage(SandeshaMessageKeys.invokeMsgError);
      if(log.isDebugEnabled()) log.debug(message, e);
    } finally {
      if (transaction != null && transaction.isActive()) {
        try {
          transaction.rollback();
        } catch (Exception e) {
          String message = SandeshaMessageHelper.getMessage(
              SandeshaMessageKeys.rollbackError, e.toString());
          if(log.isDebugEnabled()) log.debug(message, e);
        }
View Full Code Here

TOP

Related Classes of org.apache.sandesha2.storage.Transaction

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.