Package org.apache.uima.aae.controller

Examples of org.apache.uima.aae.controller.Endpoint


    {
      key = aController.getServiceEndpointName();
    }
    else
    {
      Endpoint endpoint = (Endpoint) anErrorContext.get(AsynchAEMessage.Endpoint);
      key = endpoint.getEndpoint();
    }
   
    return key;

    }
View Full Code Here


    }
   
    UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, getClass().getName(), "handleError",
        UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE, "UIMAEE_exception__WARNING", t);

    Endpoint endpoint = (Endpoint) anErrorContext.get(AsynchAEMessage.Endpoint);

    if ( endpoint != null && aController instanceof AggregateAnalysisEngineController )
    {
      Threshold threshold = super.getThreshold(endpoint, delegateMap, aController);
        String key = ((AggregateAnalysisEngineController)aController).lookUpDelegateKey(endpoint.getEndpoint());
        //  If threshold is not defined, assume action=terminate
        if threshold == null || threshold.getMaxRetries() == 0 ||
              ( super.retryLastCommand(AsynchAEMessage.GetMeta, endpoint, aController, key, threshold, anErrorContext) == false
                )
        {
          if ( terminate(threshold ) )
          {
            System.out.println("!!!!!!!!!!!! Exceeded Threshold Terminating !!!!!!!!!!!!!!");
            UIMAFramework.getLogger(CLASS_NAME).logrb(Level.FINE, CLASS_NAME.getName(),
                        "handleError", UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE, "UIMAEE_terminate_service__INFO",
                        new Object[] {aController.getComponentName(), endpoint.getEndpoint()});
            aController.terminate();
            aController.notifyListenersWithInitializationStatus((Exception)t);
          }
          else
          {
            aController.takeAction(threshold.getAction(), endpoint.getEndpoint(), anErrorContext);
          }
        }
    }
    else
    {
View Full Code Here

  {
    delegateMap = aDelegateMap;
  }
  private Endpoint getDestination( AnalysisEngineController aController, ErrorContext anErrorContext)
  {
    Endpoint endpoint = null;
    String casReferenceId = (String)anErrorContext.get( AsynchAEMessage.CasReference);
    if ( aController instanceof AggregateAnalysisEngineController )
    {
      endpoint = ((AggregateAnalysisEngineController)aController).getMessageOrigin(casReferenceId);
View Full Code Here

  }

  private boolean isClient( Endpoint anEndpoint, AnalysisEngineController aController, String aCasReferenceId )
  {
    Endpoint clientEndpoint = null;
   
    if (aController.isTopLevelComponent())
    {
      clientEndpoint = aController.
        getInProcessCache().
          getEndpoint(null, aCasReferenceId);
    }
    else  if ( aController instanceof AggregateAnalysisEngineController )
    {
      clientEndpoint =
        ((AggregateAnalysisEngineController)aController).
          getMessageOrigin(aCasReferenceId);
    }
    if (anEndpoint != null && clientEndpoint != null )
    {
      return anEndpoint.getEndpoint().equalsIgnoreCase(clientEndpoint.getEndpoint());
    }
    return false;
  }
View Full Code Here

    boolean delegateDisabled = false;
    //                       R E T R Y
    //  Do retry first if this an Aggregate Controller
    if ( !isEndpointTheClient && aController instanceof AggregateAnalysisEngineController )
    {
      Endpoint endpoint = null;
     
      if ( anErrorContext.get(AsynchAEMessage.Endpoint) != null )
      {
        endpoint = (Endpoint) anErrorContext.get(AsynchAEMessage.Endpoint);
      }
      threshold = super.getThreshold(endpoint, delegateMap, aController);
      if ( endpoint != null )
      {
          key = ((AggregateAnalysisEngineController)aController).lookUpDelegateKey(endpoint.getEndpoint());
          delegateDisabled = ((AggregateAnalysisEngineController)aController).isDelegateDisabled(key);
          if ( threshold != null && threshold.getMaxRetries() > 0 && !delegateDisabled)
          {
            //  If max retry count is not reached, send the last command again and return true
            if ( super.retryLastCommand(AsynchAEMessage.Process, endpoint, aController, key, threshold, anErrorContext) )
            {
              UIMAFramework.getLogger(CLASS_NAME).logrb(Level.FINE, getClass().getName(), "handleError",
                  UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE, "UIMAEE_retry_cas__FINE", new Object[] { aController.getComponentName(), key, casReferenceId });
              return true;   // Command has been retried. Done here.
            }
          }
          else if ( threshold == null )
          {
          UIMAFramework.getLogger(CLASS_NAME).logrb(Level.CONFIG, getClass().getName(), "handleError", UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE, "UIMAEE_no_threshold_for_endpoint__CONFIG", new Object[] { aController.getComponentName(), "Process",  key });
          }
      }
      else
      {
        UIMAFramework.getLogger(CLASS_NAME).logrb(Level.INFO, getClass().getName(), "handleError", UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE, "UIMAEE_no_endpoint_provided__INFO", new Object[] { aController.getComponentName() });
      }
    }
    else
    {
        if ( delegateMap != null && delegateMap.containsKey(key))
        {
            threshold = (Threshold)delegateMap.get(key);
        }
    }

   
    if ( key != null && key.trim().length() > 0)
    {
      //  Retries either exceeded or not configured for retry
      UIMAFramework.getLogger(CLASS_NAME).logrb(Level.FINE, getClass().getName(), "handleError",
          UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE, "UIMAEE_cas_retries_exceeded__FINE", new Object[] { aController.getComponentName(), key, casReferenceId });
    }

    //  Dont increment errors for destinations that are clients of this service.
    if ( !aController.isStopped() && (isRequest || !isEndpointTheClient ) )
    {
      synchronized( monitor )
      {
        //  Dont increment errors for delegates that have been already disabled
        if ( !delegateDisabled )
        {
          //  Process Error Count is only incremented after retries are done.
          super.incrementStatistic(aController.getMonitor(), key, Monitor.ProcessErrorCount);
          super.incrementStatistic(aController.getMonitor(), key, Monitor.TotalProcessErrorCount);
          aController.getServiceErrors().incrementProcessErrors();
          if ( aController instanceof AggregateAnalysisEngineController && anErrorContext.get(AsynchAEMessage.Endpoint) != null )
          {
            Endpoint endpoint = (Endpoint) anErrorContext.get(AsynchAEMessage.Endpoint);
            if ( endpoint.isRemote())
            {
              ServiceErrors serviceErrs =
                ((AggregateAnalysisEngineController)aController).getDelegateServiceErrors(key);
//              ServiceErrors serviceErrs = ((AggregateAnalysisEngineController)aController).getServiceErrors(key);
              if (serviceErrs != null )
              {
                serviceErrs.incrementProcessErrors();
              }
            }
          }

          /***
          if (threshold != null && threshold.getThreshold() > 0 && super.exceedsThresholdWithinWindow(aController.getMonitor(), Monitor.ProcessErrorCount, key, threshold) )
          */

          long procCount = aController.getMonitor().getLongNumericStatistic(key, Monitor.ProcessCount).getValue();
          if (threshold != null && threshold.exceededWindow(procCount))
          {
            UIMAFramework.getLogger(CLASS_NAME).logrb(Level.INFO, getClass().getName(), "handleError",
                UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE, "UIMAEE_process_cas_exceeded_threshold__INFO", new Object[] { aController.getComponentName(), key, casReferenceId, threshold.getThreshold(), threshold.getAction() });
            aController.takeAction(threshold.getAction(), key, anErrorContext);
          }
        }
        else
        {
          UIMAFramework.getLogger(CLASS_NAME).logrb(Level.INFO, getClass().getName(), "handleError",
              UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE, "UIMAEE_delegate_already_disabled__INFO", new Object[] { aController.getComponentName(), key, casReferenceId });
        }
      }
     
    }
    else
    {
      Endpoint endpt = (Endpoint) anErrorContext.get(AsynchAEMessage.Endpoint);
      if ( endpt != null )
      {
        UIMAFramework.getLogger(CLASS_NAME).logrb(Level.FINE, getClass().getName(), "handleError",
            UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE, "UIMAEE_exception_while_sending_reply_to_client__FINE", new Object[] { aController.getComponentName(), endpt.getEndpoint(), casReferenceId });
      }
    }
   
    int totalNumberOfParallelDelegatesProcessingCas = 1; // default
    CacheEntry cacheEntry = null;
    try
    {
      cacheEntry = aController.getInProcessCache().getCacheEntryForCAS(casReferenceId);
      if ( cacheEntry != null )
      {
        totalNumberOfParallelDelegatesProcessingCas = cacheEntry.getNumberOfParallelDelegates();
      }

    }
    catch( Exception e) {}
    //  Determine where to send the message
    Endpoint endpoint = getDestination(aController, anErrorContext);
/*
    //  Notify the parent of the exception
    if ( endpoint != null && casReferenceId != null && !endpoint.isCasMultiplier())
    {
      try
      {
        aController.getOutputChannel().sendReply(t, casReferenceId, endpoint, AsynchAEMessage.Process);
        aController.dropStats(casReferenceId, endpoint.getEndpoint());
      }
      catch( Exception e)
      {
        UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, getClass().getName(), "handleError",
            UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE, "UIMAEE_exception__WARNING", e);
      }
    }
*/   
    //  If the error occured during parallel step, treat the exception as response from the delegate
    //  When all responses from delegates are accounted for we allow the CAS to move on to the next
    //  step in the flow
    if ( cacheEntry != null && totalNumberOfParallelDelegatesProcessingCas > 1 && ( cacheEntry.howManyDelegatesResponded() < totalNumberOfParallelDelegatesProcessingCas))
    {
      synchronized( cacheEntry )
      {
        cacheEntry.incrementHowManyDelegatesResponded();
      }
    }

    if (aController instanceof AggregateAnalysisEngineController && t instanceof Exception)
    {
      boolean flowControllerContinueFlag = false;
      // if the deployment descriptor says no retries, dont care what the Flow Controller says
      if ( threshold != null && threshold.getContinueOnRetryFailure() )
      {
        try
        {
          //  Consult Flow Controller to determine if it is ok to continue despite the error
          flowControllerContinueFlag =
            ((AggregateAnalysisEngineController) aController).continueOnError(casReferenceId, key, (Exception) t );
        }
        catch( Exception exc) {}
      }
 
      //  Check if the caller has already decremented number of subordinates. This property is only
      //  set in the Aggregate's finalStep() method before the CAS is sent back to the client. If
      //  there was a problem sending the CAS to the client, we dont want to update the counter
      //  again. If an exception is reported elsewhere ( not in finalStep()), the default action is
      //  to decrement the number of subordinates associated with the parent CAS.
      if ( !anErrorContext.containsKey(AsynchAEMessage.SkipSubordinateCountUpdate))
      {
        //  Check if the CAS is a subordinate (has parent CAS).
        if ( cacheEntry != null && cacheEntry.isSubordinate())
        {
          String parentCasReferenceId = cacheEntry.getInputCasReferenceId();
          if ( parentCasReferenceId != null )
          {
            try
            {
              CacheEntry parentCasCacheEntry = aController.getInProcessCache().
                                getCacheEntryForCAS(parentCasReferenceId);
              synchronized( parentCasCacheEntry )
              {
                ((AggregateAnalysisEngineController)aController).
                decrementCasSubordinateCount( parentCasCacheEntry);
                if ( parentCasCacheEntry.getSubordinateCasInPlayCount() == 0 &&
                   parentCasCacheEntry.isPendingReply())
                {
                  //  Complete processing of the Input CAS
                  if ( flowControllerContinueFlag ==  false )
                  {
                    aController.process(parentCasCacheEntry.getCas(), parentCasCacheEntry.getCasReferenceId());
                  }
                }
              }
            }
            catch( Exception ex)
            {
              //  Input CAS doesnt exist. Nothing to update, move on
            }
          }
        }
      }
     
     
     
      if ( threshold != null && flowControllerContinueFlag )
      {
        if (totalNumberOfParallelDelegatesProcessingCas == 1 || ( cacheEntry.howManyDelegatesResponded() == totalNumberOfParallelDelegatesProcessingCas) )
        {
          aController.process(aController.getInProcessCache().getCasByReference(casReferenceId), casReferenceId);
        }
        //  Dont send request to release the CAS to remote CM. This will happen in the final step. We are continuing
        //  despite the error here.
        return true;
      }
      else
      {
        try
        {
          sendExceptionToClient( t, casReferenceId, endpoint, aController );
          //System.out.println("---------------------------- CAS Produced By CM:"+cacheEntry.getCasProducerKey());
        }
        catch( Exception e)
        {
          e.printStackTrace();
          UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, getClass().getName(), "handleError",
              UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE, "UIMAEE_exception__WARNING", e);
        }
      }
     
      //  Now check if the CAS origin is a remote CAS Multiplier. If so, send a request to release the CAS. Remote
      //  CAS Multipliers must be "gated" to prevent flooding the Aggregate queue with too many CASes. There is
      //  an explicit protocol between an Aggregate AS and its CM. The Aggregate AS sends a request to free a CAS
      //  in the CM whenever the Aggregate has capacity to process more CASes. Here we are recovering from an
      //  an error but we still need to send a request to free the CAS in the remote CM to prevent a hang in the CM
      try
      {
        //  First check if the current controller is the one that first produced the CAS
        if ( cacheEntry != null && aController.getName().equalsIgnoreCase(cacheEntry.getCasProducerAggregateName() ) )
        {
          //  Fetch the key of the Cas Multiplier
          String casProducerKey = cacheEntry.getCasMultiplierKey();
          if ( casProducerKey != null )
          {
            //  Create an endpoint object from the key. This object will be cloned from the Endpoint object
            //  defined in the spring configuration file.
            Endpoint cmEndpoint = ((AggregateAnalysisEngineController)aController).lookUpEndpoint(casProducerKey, true);
           
            //  CAS reference id will be different if the CAS originated from a remote Cas Multiplier.
            //String cmCasReferenceId = cacheEntry.getRemoteCMCasReferenceId();
            //  If the Cas Multiplier is remote send a request to free a CAS with a given cas id
            if ( cmEndpoint != null && cmEndpoint.isCasMultiplier() && cmEndpoint.isRemote() )
            {
              cmEndpoint.setEndpoint(cmEndpoint.getEndpoint()+"__CasSync");
              aController.getOutputChannel().sendRequest(AsynchAEMessage.ReleaseCAS, cmEndpoint);
            }
          }
        }
      }
View Full Code Here

      UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, getClass().getName(), "handleError",
          UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE, "UIMAEE_exception__WARNING", new Object[] { t });

      if ( anErrorContext.containsKey(AsynchAEMessage.Endpoint) )
      {
        Endpoint endpoint = (Endpoint)anErrorContext.get(AsynchAEMessage.Endpoint);
        String casReferenceId = (String)anErrorContext.get(AsynchAEMessage.CasReference);

        try
        {
          aController.getOutputChannel().sendReply(t, casReferenceId, endpoint, AsynchAEMessage.Process );
View Full Code Here

    super(anEndpointThreasholdMap);
  }
   
  private Endpoint getDestination( AnalysisEngineController aController, ErrorContext anErrorContext)
  {
    Endpoint endpoint = null;
    String casReferenceId = (String)anErrorContext.get( AsynchAEMessage.CasReference);
    if ( aController instanceof AggregateAnalysisEngineController )
    {
      endpoint = ((AggregateAnalysisEngineController)aController).getMessageOrigin(casReferenceId);
View Full Code Here

    return endpoint;
  }
  public boolean handleError(Throwable t, ErrorContext anErrorContext, AnalysisEngineController aController)
  {
    String casReferenceId = null;
    Endpoint endpoint = null;
    String key = null;
    try
    {
      UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, getClass().getName(), "handleError",
          UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE, "UIMAEE_exception__WARNING", t);
     
      endpoint = getDestination(aController, anErrorContext);
      casReferenceId = (String)anErrorContext.get( AsynchAEMessage.CasReference);

      //  Notify the parent of the exception
      if ( endpoint != null && !endpoint.isCasMultiplier())
      {
        aController.getOutputChannel().sendReply(t, casReferenceId, endpoint, AsynchAEMessage.Process);

        //  Lookup Delegate's key
        key = super.getDelegateKey(endpoint, aController);
       
        if (super.exceedsThreshold(Monitor.ErrorCount, key, aController))
        {
          String action = getAction(Monitor.ErrorCount, key);
          aController.takeAction( action, key, anErrorContext);
        }
      }
      else if ( endpoint == null)
      {
        UIMAFramework.getLogger(CLASS_NAME).logrb(Level.INFO, getClass().getName(), "handleError",
            UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE, "UIMAEE_no_endpoint__INFO", new Object[] { aController.getName() });
      }
    }
    catch( Exception e)
    {
      e.printStackTrace();
      UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, getClass().getName(), "handleError",
          UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE, "UIMAEE_exception__WARNING", e);
    }
    finally
    {
      try
      {
        //  Only top level component can Drop the CAS.
        if ( aController.isTopLevelComponent() )
        {
          aController.takeAction( ErrorHandler.DROPCAS, key, anErrorContext);
        }     
        else if ( casReferenceId != null && aController instanceof AggregateAnalysisEngineController )
        {
          ((AggregateAnalysisEngineController)aController).dropFlow(casReferenceId, true);
          ((AggregateAnalysisEngineController)aController).removeMessageOrigin(casReferenceId);

        }

        aController.dropStats(casReferenceId, aController.getName());
       
        endpoint = (Endpoint) anErrorContext.get(AsynchAEMessage.Endpoint);
        if ( endpoint != null )
        {
          aController.dropStats(casReferenceId, endpoint.getEndpoint());
        }
      }
      catch( Exception e)
      {
        e.printStackTrace();
View Full Code Here

  {
    if (t instanceof MessageTimeoutException)
    {
      if (anErrorContext.containsKey(AsynchAEMessage.Command) && anErrorContext.containsKey(AsynchAEMessage.Endpoint))
      {
        Endpoint endpoint = null;
        try
        {
          endpoint = (Endpoint) anErrorContext.get(AsynchAEMessage.Endpoint);
          int command = ((Integer) anErrorContext.get(AsynchAEMessage.Command)).intValue();
          if (AsynchAEMessage.Process == command)
          {
            if ( anErrorContext.containsKey(AsynchAEMessage.CasReference ) )
            {
             
              if (!super.exceedsThreshold(Monitor.ProcessRequestTimeoutCount, endpoint.getEndpoint(), aController))
              {
                if ( endpoint.isRetryEnabled() && aController instanceof AggregateAnalysisEngineController )
                {
                  String casReferenceId = (String)anErrorContext.get( AsynchAEMessage.CasReference);
                  //System.out.println(Thread.currentThread().getName() + " DefaultTimeoutHandler sending request to process CAS to endpoint::" + endpoint.getEndpoint()+" CasReferenceId::"+casReferenceId);
                  ((AggregateAnalysisEngineController) aController).retryProcessCASRequest(casReferenceId, endpoint, false);
                  return true; // Handled the exception
                }
              }
              else
              {
                String casReferenceId = (String)anErrorContext.get( AsynchAEMessage.CasReference);
                String action = getAction(Monitor.MetadataRequestTimeoutCount, endpoint.getEndpoint());

                if ( ErrorHandler.DISABLE.equalsIgnoreCase(action))
                {
                  List list = new ArrayList();
                  list.add(endpoint.getEndpoint());
                  ((AggregateAnalysisEngineController)aController).disableDelegates(list);
                 
                  //  The following should be done after consultation with the Flow
                  //((AggregateAnalysisEngineController)aController).dropCAS(casReferenceId, true);
                 
                 
                 
                  return true;
                }
               
               
               
               
                /*
                CacheEntry cachedEntry =
                  ((AggregateAnalysisEngineController) aController).getInProcessCache().getCacheEntryForCAS(casReferenceId);
                if ( cachedEntry.getNumberOfParallelDelegates() > 1 )
                {
                  if ( ErrorHandler.CONTINUE.equalsIgnoreCase(action) )
                  {
                  }
                }
                */
              }
             
            }
            else
            {
              //  unhandled error. Missing CasReference Id in error context
            }
          }
          else if (AsynchAEMessage.GetMeta == command)
          {
            String key = ((AggregateAnalysisEngineController) aController).lookUpDelegateKey(endpoint.getEndpoint());
            //System.out.println(Thread.currentThread().getName() + " DefaultTimeoutHandler handles Timeout For GetMetadata ");
            if (!exceedsThreshold(Monitor.MetadataRequestTimeoutCount, key, aController))
            {
              //System.out.println(Thread.currentThread().getName() + " DefaultTimeoutHandler sending request for metadata to endpoint::" + endpoint.getEndpoint());
              if (aController instanceof AggregateAnalysisEngineController)
              {
                ((AggregateAnalysisEngineController) aController).retryMetadataRequest(endpoint);
                return true; // Handled the exception
              }
            }
            else
            {
              String action = getAction(Monitor.MetadataRequestTimeoutCount, key); //endpoint.getEndpoint());
              if ( action != null )
              {
//                System.out.println(Thread.currentThread().getName() + " DefaultTimeoutHandler Exceeded Threshold - Taking Action:::"+action+" endpoint::" + endpoint.getEndpoint());
                  aController.takeAction(action, endpoint.getEndpoint(), anErrorContext);
                return true; // Handled the exception
              }
            }
          }
        }
View Full Code Here

      return false;
    }
    UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, getClass().getName(), "handleError",
        UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE, "UIMAEE_exception__WARNING", t);

    Endpoint endpoint = (Endpoint) anErrorContext.get(AsynchAEMessage.Endpoint);
    if ( endpoint != null )
    {
      Threshold threshold = null;
      if ( aController instanceof PrimitiveAnalysisEngineController )
      {
        threshold = (Threshold)delegateMap.get("");
      }
      else
      {
        threshold = super.getThreshold(endpoint, delegateMap, aController);
      }
      try
      {
        if ( aController instanceof AggregateAnalysisEngineController )
        {
          endpoint = ((AggregateAnalysisEngineController)aController).getClientEndpoint();
        }
        aController.getOutputChannel().sendReply(t, null, endpoint, AsynchAEMessage.CollectionProcessComplete);
      }
      catch( Exception e)
      {
        UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, getClass().getName(), "handleError",
            UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE, "UIMAEE_exception__WARNING", e);
      }

      if ( threshold != null && threshold.getAction().equalsIgnoreCase(ErrorHandler.TERMINATE ))
        {
        aController.takeAction(threshold.getAction(), endpoint.getEndpoint(), anErrorContext);
        }
        else if ( threshold == null )
        {
        UIMAFramework.getLogger(CLASS_NAME).logrb(Level.CONFIG, getClass().getName(), "handleError", UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE, "UIMAEE_no_threshold_for_endpoint__CONFIG", new Object[] { aController.getName(), "Collection Processing Complete",  aController.getName() });
        }
View Full Code Here

TOP

Related Classes of org.apache.uima.aae.controller.Endpoint

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.