Пример #1
0
  /**
   * {@inheritDoc}
   *
   * <p>Enqueues a send event to this client session's event queue for servicing.
   */
  public ClientSession send(ByteBuffer message) {
    try {
      if (message.remaining() > SimpleSgsProtocol.MAX_PAYLOAD_LENGTH) {
        throw new IllegalArgumentException(
            "message too long: "
                + message.remaining()
                + " > "
                + SimpleSgsProtocol.MAX_PAYLOAD_LENGTH);
      } else if (!isConnected()) {
        throw new IllegalStateException("client session not connected");
      }
      /*
       * TODO: Possible optimization: if we have passed our own special
       * buffer to the app, we can detect that here and possibly avoid a
       * copy.  Our special buffer could be one we passed to the
       * receivedMessage callback, or we could add a special API to
       * pre-allocate buffers. -JM
       */
      ByteBuffer buf = ByteBuffer.wrap(new byte[1 + message.remaining()]);
      buf.put(SimpleSgsProtocol.SESSION_MESSAGE).put(message).flip();
      addEvent(new SendEvent(buf.array()));
      if (sessionService.sendMessageOp != null) {
        sessionService.sendMessageOp.report();
      }

      return this;

    } catch (RuntimeException e) {
      if (logger.isLoggable(Level.FINEST)) {
        logger.logThrow(
            Level.FINEST, e, "send message:{0} throws", HexDumper.format(message, 0x50));
      }
      throw e;
    }
  }
  /** {@inheritDoc} */
  public void doShutdown() {
    if (protocolAcceptor != null) {
      try {
        protocolAcceptor.close();
      } catch (IOException ignore) {
      }
    }
    for (ClientSessionHandler handler : handlers.values()) {
      handler.shutdown();
    }
    handlers.clear();

    if (exporter != null) {
      try {
        exporter.unexport();
        logger.log(Level.FINEST, "client session server unexported");
      } catch (RuntimeException e) {
        logger.logThrow(Level.FINEST, e, "unexport server throws");
        // swallow exception
      }
    }

    synchronized (flushContextsLock) {
      flushContextsLock.notifyAll();
    }
  }
Пример #3
0
    /** Processes (at least) the first event in the queue. */
    void serviceEvent() {
      checkState();

      ClientSessionServiceImpl sessionService = ClientSessionServiceImpl.getInstance();
      ManagedQueue<SessionEvent> eventQueue = getQueue();
      DataService dataService = ClientSessionServiceImpl.getDataService();

      for (int i = 0; i < sessionService.eventsPerTxn; i++) {
        SessionEvent event = eventQueue.poll();
        if (event == null) {
          // no more events
          break;
        }

        logger.log(Level.FINEST, "processing event:{0}", event);

        int cost = event.getCost();
        if (cost > 0) {
          dataService.markForUpdate(this);
          writeBufferAvailable += cost;
          if (logger.isLoggable(Level.FINEST)) {
            logger.log(
                Level.FINEST,
                "{0} cleared reservation of " + "{1,number,#} bytes, leaving {2,number,#}",
                this,
                cost,
                writeBufferAvailable);
          }
        }

        event.serviceEvent(this);
      }
    }
  /**
   * Private method that determines whether a given task should be re-tried based on the given
   * {@code Throwable} that caused failure. If this returns {@code true} then the task should be
   * re-tried. Otherwise, the task should be dropped.
   */
  private boolean shouldRetry(ScheduledTaskImpl task, Throwable t) {
    // NOTE: as a first-pass implementation this simply instructs the
    // caller to try again if retry is requested, but other strategies
    // (like the number of times re-tried) might be considered later
    if ((t instanceof ExceptionRetryStatus) && (((ExceptionRetryStatus) t).shouldRetry())) {
      return true;
    }

    // we're not re-trying the task, so log that it's being dropped
    if (logger.isLoggable(Level.WARNING)) {
      if (task.isRecurring()) {
        logger.logThrow(
            Level.WARNING,
            t,
            "skipping a recurrence of "
                + "a task that failed with a non-retryable "
                + "exception: {0}",
            task);
      } else {
        logger.logThrow(
            Level.WARNING,
            t,
            "dropping a task that " + "failed with a non-retryable exception: {0}",
            task);
      }
    }

    return false;
  }
Пример #5
0
 /**
  * Attempts to enqueue the specified {@code event}, and returns {@code true} if successful, and
  * {@code false} otherwise.
  *
  * @param event the event
  * @return {@code true} if successful, and {@code false} otherwise
  * @throws MessageRejectedException if the cost of the event exceeds the available buffer space
  *     in the queue
  */
 boolean offer(SessionEvent event) {
   int cost = event.getCost();
   if (cost > writeBufferAvailable) {
     ClientSessionServiceImpl sessionService = ClientSessionServiceImpl.getInstance();
     if (sessionService.receiveMessageRejectedOp != null) {
       sessionService.receiveMessageRejectedOp.report();
     }
     throw new MessageRejectedException(
         "Not enough queue space: "
             + writeBufferAvailable
             + " bytes available, "
             + cost
             + " requested");
   }
   boolean success = getQueue().offer(event);
   if (success && cost > 0) {
     ClientSessionServiceImpl.getDataService().markForUpdate(this);
     writeBufferAvailable -= cost;
     if (logger.isLoggable(Level.FINEST)) {
       logger.log(
           Level.FINEST,
           "{0} reserved {1,number,#} leaving {2,number,#}",
           this,
           cost,
           writeBufferAvailable);
     }
   }
   return success;
 }
 /** {@inheritDoc} */
 public void doReady() {
   channelService = txnProxy.getService(ChannelServiceImpl.class);
   acceptFuture = acceptor.accept(new AcceptorListener());
   try {
     if (logger.isLoggable(Level.CONFIG)) {
       logger.log(Level.CONFIG, "listening on {0}", acceptor.getLocalAddress());
     }
   } catch (IOException ioe) {
     throw new RuntimeException(ioe.getMessage(), ioe);
   }
 }
Пример #7
0
  /** {@inheritDoc} */
  protected void doShutdown() {
    logger.log(Level.FINEST, "shutdown");

    try {
      if (exporter != null) {
        exporter.unexport();
      }
    } catch (RuntimeException e) {
      logger.logThrow(Level.FINEST, e, "unexport server throws");
      // swallow exception
    }
  }
Пример #8
0
 /**
  * If the session is connected, enqueues a disconnect event to this client session's event queue,
  * and marks this session as disconnected.
  */
 void disconnect() {
   if (isConnected()) {
     addEvent(new DisconnectEvent());
     sessionService.getDataService().markForUpdate(this);
     connected = false;
   }
   logger.log(Level.FINEST, "disconnect returns");
 }
Пример #9
0
  /** {@inheritDoc} */
  public Channel getChannel(String name) {
    try {
      return ChannelImpl.getInstance(name);

    } catch (RuntimeException e) {
      logger.logThrow(Level.FINEST, e, "getChannel:{0} throws");
      throw e;
    }
  }
Пример #10
0
  /**
   * Creates an instance of <code>FIFOSchedulerQueue</code>.
   *
   * @param properties the available system properties
   */
  public FIFOSchedulerQueue(Properties properties) {
    logger.log(Level.CONFIG, "Creating a FIFO Scheduler Queue");

    if (properties == null) {
      throw new NullPointerException("Properties cannot be null");
    }

    queue = new LinkedBlockingQueue<ScheduledTask>();
    timedTaskHandler = new TimedTaskHandler(this);
  }
Пример #11
0
  /** {@inheritDoc} */
  public Channel createChannel(String name, ChannelListener listener, Delivery delivery) {
    try {
      Channel channel = ChannelImpl.newInstance(name, listener, delivery, writeBufferSize);
      return channel;

    } catch (RuntimeException e) {
      logger.logThrow(Level.FINEST, e, "createChannel:{0} throws");
      throw e;
    }
  }
  /**
   * Creates an instance of {@code TransactionSchedulerImpl}.
   *
   * @param properties the {@code Properties} for the system
   * @param transactionCoordinator the {@code TransactionCoordinator} used by the system to manage
   *     transactions
   * @param profileCollectorHandle the {@code ProfileCollectorHandler} used to manage collection of
   *     per-task profiling data
   * @param accessCoordinator the {@code AccessCoordinator} used by the system to managed shared
   *     data
   * @throws InvocationTargetException if there is a failure initializing the {@code SchedulerQueue}
   * @throws Exception if there is any failure creating the scheduler
   */
  TransactionSchedulerImpl(
      Properties properties,
      TransactionCoordinator transactionCoordinator,
      ProfileCollectorHandle profileCollectorHandle,
      AccessCoordinatorHandle accessCoordinator)
      throws Exception {
    logger.log(Level.CONFIG, "Creating a Transaction Scheduler");

    if (properties == null) {
      throw new NullPointerException("Properties cannot be null");
    }
    if (transactionCoordinator == null) {
      throw new NullPointerException("Coordinator cannot be null");
    }
    if (profileCollectorHandle == null) {
      throw new NullPointerException("Collector handle cannot be null");
    }
    if (accessCoordinator == null) {
      throw new NullPointerException("AccessCoordinator cannot be null");
    }

    this.transactionCoordinator = transactionCoordinator;
    this.profileCollectorHandle = profileCollectorHandle;
    this.accessCoordinator = accessCoordinator;

    String queueName = properties.getProperty(SCHEDULER_QUEUE_PROPERTY, DEFAULT_SCHEDULER_QUEUE);
    try {
      Class<?> queueClass = Class.forName(queueName);
      Constructor<?> queueCtor = queueClass.getConstructor(Properties.class);
      this.backingQueue = (SchedulerQueue) (queueCtor.newInstance(properties));
    } catch (InvocationTargetException e) {
      if (logger.isLoggable(Level.CONFIG)) {
        logger.logThrow(
            Level.CONFIG, e.getCause(), "Queue {0} " + "failed to initialize", queueName);
      }
      throw e;
    } catch (Exception e) {
      if (logger.isLoggable(Level.CONFIG)) {
        logger.logThrow(Level.CONFIG, e, "Queue {0} unavailable", queueName);
      }
      throw e;
    }

    // startup the requested number of consumer threads
    // NOTE: this is a simple implmentation to replicate the previous
    // behvavior, with the assumption that it will change if the
    // scheduler starts trying to add or drop consumers adaptively
    int requestedThreads =
        Integer.parseInt(
            properties.getProperty(CONSUMER_THREADS_PROPERTY, DEFAULT_CONSUMER_THREADS));
    if (logger.isLoggable(Level.CONFIG)) {
      logger.log(Level.CONFIG, "Using {0} transaction consumer threads", requestedThreads);
    }
    this.executor = Executors.newCachedThreadPool();
    for (int i = 0; i < requestedThreads; i++) {
      executor.submit(new TaskConsumer());
    }
  }
  /** Trigger a one-time presence update. */
  public void updatePresence() {
    if (!service.isValidConfiguration()) {
      logger.log(
          Level.WARNING,
          "Tried to update presence information, but XMPP configuration was not valid. Make sure to set an account name and password.");
      return;
    }

    service.doUpdateStatusMessage();
  }
 /** Notifies the scheduler that a thread has been interrupted and is finishing its work. */
 private void notifyThreadLeaving() {
   profileCollectorHandle.notifyThreadRemoved();
   // NOTE: we're not yet trying to adapt the number of threads being
   // used, so we assume that threads are only lost when the system
   // wants to shutdown...in practice, this should look at some
   // threshold and see if another consumer needs to be created
   if (threadCount.decrementAndGet() == 0) {
     logger.log(Level.CONFIG, "No more threads are consuming tasks");
     shutdown();
   }
 }
 /**
  * Returns a set of protocol descriptors for the specified {@code nodeId}, or {@code null} if
  * there are no descriptors for the node. This method must be run outside a transaction.
  */
 Set<ProtocolDescriptor> getProtocolDescriptors(long nodeId) {
   checkNonTransactionalContext();
   GetProtocolDescriptorsTask protocolDescriptorsTask = new GetProtocolDescriptorsTask(nodeId);
   try {
     transactionScheduler.runTask(protocolDescriptorsTask, taskOwner);
     return protocolDescriptorsTask.descriptors;
   } catch (Exception e) {
     logger.logThrow(Level.WARNING, e, "GetProtocolDescriptorsTask for node:{0} throws", nodeId);
     return null;
   }
 }
  /** {@inheritDoc} */
  public void doReady() throws Exception {
    channelService = txnProxy.getService(ChannelServiceImpl.class);
    try {
      protocolAcceptor.accept(protocolListener);
    } catch (IOException e) {
      if (logger.isLoggable(Level.CONFIG)) {
        logger.logThrow(Level.CONFIG, e, "Failed to start accepting connections");
      }
      throw e;
    }

    transactionScheduler.runTask(
        new AbstractKernelRunnable("AddProtocolDescriptorMapping") {
          public void run() {
            getProtocolDescriptorsMap()
                .put(localNodeId, Collections.singleton(protocolAcceptor.getDescriptor()));
          }
        },
        taskOwner);
  }
Пример #17
0
  /**
   * Runs a transactional task to query the status of the node with the specified {@code nodeId} and
   * returns {@code true} if the node is alive and {@code false} otherwise.
   *
   * <p>This method must be called from outside a transaction or {@code IllegalStateException} will
   * be thrown.
   */
  boolean isAlive(long nodeId) {
    // Make sure that we're not in a transactional context.
    try {
      getTransaction();
      throw new IllegalStateException("isAlive called from a transactional context");
    } catch (TransactionNotActiveException e) {
    }

    try {
      CheckNodeStatusTask nodeStatus = new CheckNodeStatusTask(nodeId);
      transactionScheduler.runTask(nodeStatus, taskOwner);
      return nodeStatus.isAlive;
    } catch (Exception e) {
      if (logger.isLoggable(Level.WARNING)) {
        logger.logThrow(Level.WARNING, e, "running CheckNodeStatusTask throws");
      }
      // TBD: is this the correct value to return?
      return false;
    }
  }
  /** {@inheritDoc} */
  public void doShutdown() {
    final IoFuture<?, ?> future = acceptFuture;
    acceptFuture = null;
    if (future != null) {
      future.cancel(true);
    }

    if (acceptor != null) {
      try {
        acceptor.close();
      } catch (IOException e) {
        logger.logThrow(Level.FINEST, e, "closing acceptor throws");
        // swallow exception
      }
    }

    if (asyncChannelGroup != null) {
      asyncChannelGroup.shutdown();
      boolean groupShutdownCompleted = false;
      try {
        groupShutdownCompleted = asyncChannelGroup.awaitTermination(1, TimeUnit.SECONDS);
      } catch (InterruptedException e) {
        logger.logThrow(Level.FINEST, e, "shutdown acceptor interrupted");
        Thread.currentThread().interrupt();
      }
      if (!groupShutdownCompleted) {
        logger.log(Level.WARNING, "forcing async group shutdown");
        try {
          asyncChannelGroup.shutdownNow();
        } catch (IOException e) {
          logger.logThrow(Level.FINEST, e, "shutdown acceptor throws");
          // swallow exception
        }
      }
    }
    logger.log(Level.FINEST, "acceptor shutdown");

    if (exporter != null) {
      try {
        exporter.unexport();
        logger.log(Level.FINEST, "client session server unexported");
      } catch (RuntimeException e) {
        logger.logThrow(Level.FINEST, e, "unexport server throws");
        // swallow exception
      }
    }

    for (ClientSessionHandler handler : handlers.values()) {
      handler.shutdown();
    }
    handlers.clear();

    flushContextsThread.interrupt();
  }
 /** {@inheritDoc} */
 public void sendProtocolMessageNonTransactional(
     BigInteger sessionRefId, ByteBuffer message, Delivery delivery) {
   ClientSessionHandler handler = handlers.get(sessionRefId);
   /*
    * If a local handler exists, forward message to local handler
    * to send to client session.
    */
   if (handler != null) {
     byte[] bytes = new byte[message.remaining()];
     message.get(bytes);
     handler.sendProtocolMessage(bytes, delivery);
   } else {
     logger.log(Level.FINE, "Discarding messages for unknown session:{0}", sessionRefId);
     return;
   }
 }
Пример #20
0
 /** {@inheritDoc} */
 public void run() {
   String channelServerKey = getChannelServerKey(nodeId);
   try {
     ManagedSerializable wrappedProxy =
         (ManagedSerializable) getDataService().getServiceBinding(channelServerKey);
     channelServer = (ChannelServer) wrappedProxy.get();
   } catch (NameNotBoundException e) {
     channelServer = null;
   } catch (ObjectNotFoundException e) {
     logger.logThrow(
         Level.SEVERE,
         e,
         "ChannelServer binding:{0} exists, but object removed",
         channelServerKey);
     channelServer = null;
   }
 }
Пример #21
0
 /**
  * Constructs an instance of this class with the specified {@code sessionService}, {@code
  * identity}, and the local node ID, and stores this instance with the following bindings:
  *
  * <p>
  *
  * <pre>
  * com.sun.sgs.impl.service.session.impl.&lt;idBytes&gt;
  * com.sun.sgs.impl.service.session.node.&lt;nodeId&gt;.impl.&lt;idBytes&gt;
  * </pre>
  *
  * This method should only be called within a transaction.
  *
  * @param sessionService a client session service
  * @param identity the session's identity
  * @throws TransactionException if there is a problem with the current transaction
  */
 ClientSessionImpl(ClientSessionServiceImpl sessionService, Identity identity) {
   if (sessionService == null) {
     throw new NullPointerException("null sessionService");
   }
   if (identity == null) {
     throw new IllegalStateException("session's identity is not set");
   }
   this.sessionService = sessionService;
   this.identity = identity;
   this.nodeId = sessionService.getLocalNodeId();
   writeBufferCapacity = sessionService.getWriteBufferSize();
   DataService dataService = sessionService.getDataService();
   ManagedReference<ClientSessionImpl> sessionRef = dataService.createReference(this);
   id = sessionRef.getId();
   this.wrappedSessionRef = dataService.createReference(new ClientSessionWrapper(sessionRef));
   idBytes = id.toByteArray();
   dataService.setServiceBinding(getSessionKey(), this);
   dataService.setServiceBinding(getSessionNodeKey(), this);
   dataService.setServiceBinding(getEventQueueKey(), new EventQueue(this));
   logger.log(Level.FINEST, "Stored session, identity:{0} id:{1}", identity, id);
 }
 /**
  * Returns the proxy for the client session server on the specified {@code nodeId}, or {@code
  * null} if no server exists.
  *
  * @param nodeId a node ID
  * @return the proxy for the client session server on the specified {@code nodeId}, or {@code
  *     null}
  */
 ClientSessionServer getClientSessionServer(long nodeId) {
   if (nodeId == localNodeId) {
     return serverImpl;
   } else {
     String sessionServerKey = getClientSessionServerKey(nodeId);
     try {
       ManagedSerializable wrappedProxy =
           (ManagedSerializable) dataService.getServiceBinding(sessionServerKey);
       return (ClientSessionServer) wrappedProxy.get();
     } catch (NameNotBoundException e) {
       return null;
     } catch (ObjectNotFoundException e) {
       logger.logThrow(
           Level.SEVERE,
           e,
           "ClientSessionServer binding:{0} exists, " + "but object removed",
           sessionServerKey);
       throw e;
     }
   }
 }
  /**
   * Start updating the presence information. Tells the PresenceManager to plug into the
   * UserListener system so it can be notified of user join/leave events, which it takes as signals
   * to update the presence information.
   */
  public void startPresenceUpdating() {
    if (!service.isValidConfiguration()) {
      logger.log(
          Level.WARNING,
          "Tried to start presence updating, but XMPP configuration was not valid. Make sure to set an account name and password.");
      return;
    }

    // Start a recurring task that updates the status messages.

    // lets try using the UserManager notification mechanism for deciding when a good time to update
    // would be.
    UserManager manager = UserManager.getUserManager();

    listener = new PresenceUserListener();
    // Using this inner class as an indirection to avoid serialization problems.
    manager.addUserListener(listener);

    // Kick off a task that periodically cleans out expired XMPP connections
    // (ie connections from which we haven't seen an event in a while)
    // no need to run this that often; being off by a few seconds is no big deal.
    AppContext.getTaskManager().schedulePeriodicTask(new ExpireConnectionsTask(), 0, 3000);
  }
Пример #24
0
 /** {@inheritDoc} */
 public ProfileConsumer registerProfileProducer(ProfileProducer producer) {
   if (logger.isLoggable(Level.CONFIG))
     logger.log(Level.CONFIG, "Registering profile producer {0}", producer);
   return new ProfileConsumerImpl(producer, profileCollector);
 }
Пример #25
0
  /**
   * Private helper that creates the services and their associated managers, taking care to call out
   * the standard services first, because we need to get the ordering constant and make sure that
   * they're all present.
   */
  private void fetchServices(ComponentRegistryImpl services, HashSet<Object> managerSet)
      throws Exception {
    // before we start, figure out if we're running with only a sub-set
    // of services, in which case there should be no external services
    String finalService = appProperties.getProperty(StandardProperties.FINAL_SERVICE);
    StandardService finalStandardService = null;
    String externalServices = appProperties.getProperty(StandardProperties.SERVICES);
    String externalManagers = appProperties.getProperty(StandardProperties.MANAGERS);
    if (finalService != null) {
      if ((externalServices != null) || (externalManagers != null))
        throw new IllegalArgumentException(
            "Cannot specify external " + "services and a final " + "service");

      // validate the final service
      try {
        finalStandardService = Enum.valueOf(StandardService.class, finalService);
      } catch (IllegalArgumentException iae) {
        if (logger.isLoggable(Level.SEVERE))
          logger.logThrow(Level.SEVERE, iae, "Invalid final " + "service name: {0}", finalService);
        throw iae;
      }

      // make sure we're not running with an application
      if (!appProperties
          .getProperty(StandardProperties.APP_LISTENER)
          .equals(StandardProperties.APP_LISTENER_NONE))
        throw new IllegalArgumentException(
            "Cannot specify an app " + "listener and a final " + "service");
    } else {
      finalStandardService = StandardService.LAST_SERVICE;
    }

    // load the data service

    String dataServiceClass =
        appProperties.getProperty(StandardProperties.DATA_SERVICE, DEFAULT_DATA_SERVICE);
    String dataManagerClass =
        appProperties.getProperty(StandardProperties.DATA_MANAGER, DEFAULT_DATA_MANAGER);
    services.addComponent(setupService(dataServiceClass, dataManagerClass, managerSet));

    // load the watch-dog service, which has no associated manager

    if (StandardService.WatchdogService.ordinal() > finalStandardService.ordinal()) return;

    String watchdogServiceClass =
        appProperties.getProperty(StandardProperties.WATCHDOG_SERVICE, DEFAULT_WATCHDOG_SERVICE);
    Service watchdogService = createService(Class.forName(watchdogServiceClass));
    services.addComponent(watchdogService);
    if (watchdogService instanceof ProfileProducer) {
      if (profileRegistrar != null)
        ((ProfileProducer) watchdogService).setProfileRegistrar(profileRegistrar);
    }

    // load the node mapping service, which has no associated manager

    if (StandardService.NodeMappingService.ordinal() > finalStandardService.ordinal()) return;

    String nodemapServiceClass =
        appProperties.getProperty(
            StandardProperties.NODE_MAPPING_SERVICE, DEFAULT_NODE_MAPPING_SERVICE);
    Service nodemapService = createService(Class.forName(nodemapServiceClass));
    services.addComponent(nodemapService);
    if (nodemapService instanceof ProfileProducer) {
      if (profileRegistrar != null)
        ((ProfileProducer) nodemapService).setProfileRegistrar(profileRegistrar);
    }

    // load the task service

    if (StandardService.TaskService.ordinal() > finalStandardService.ordinal()) return;

    String taskServiceClass =
        appProperties.getProperty(StandardProperties.TASK_SERVICE, DEFAULT_TASK_SERVICE);
    String taskManagerClass =
        appProperties.getProperty(StandardProperties.TASK_MANAGER, DEFAULT_TASK_MANAGER);
    services.addComponent(setupService(taskServiceClass, taskManagerClass, managerSet));

    // load the client session service, which has no associated manager

    if (StandardService.ClientSessionService.ordinal() > finalStandardService.ordinal()) return;

    String clientSessionServiceClass =
        appProperties.getProperty(
            StandardProperties.CLIENT_SESSION_SERVICE, DEFAULT_CLIENT_SESSION_SERVICE);
    Service clientSessionService = createService(Class.forName(clientSessionServiceClass));
    services.addComponent(clientSessionService);
    if (clientSessionService instanceof ProfileProducer) {
      if (profileRegistrar != null)
        ((ProfileProducer) clientSessionService).setProfileRegistrar(profileRegistrar);
    }

    // load the channel service

    if (StandardService.ChannelService.ordinal() > finalStandardService.ordinal()) return;

    String channelServiceClass =
        appProperties.getProperty(StandardProperties.CHANNEL_SERVICE, DEFAULT_CHANNEL_SERVICE);
    String channelManagerClass =
        appProperties.getProperty(StandardProperties.CHANNEL_MANAGER, DEFAULT_CHANNEL_MANAGER);
    services.addComponent(setupService(channelServiceClass, channelManagerClass, managerSet));

    // finally, load any external services and their associated managers
    if ((externalServices != null) && (externalManagers != null)) {
      String[] serviceClassNames = externalServices.split(":", -1);
      String[] managerClassNames = externalManagers.split(":", -1);
      if (serviceClassNames.length != managerClassNames.length) {
        if (logger.isLoggable(Level.SEVERE))
          logger.log(
              Level.SEVERE,
              "External service count " + "({0}) does not match manager count ({1}).",
              serviceClassNames.length,
              managerClassNames.length);
        throw new IllegalArgumentException("Mis-matched service " + "and manager count");
      }

      for (int i = 0; i < serviceClassNames.length; i++) {
        if (!managerClassNames[i].equals("")) {
          services.addComponent(
              setupService(serviceClassNames[i], managerClassNames[i], managerSet));
        } else {
          Class<?> serviceClass = Class.forName(serviceClassNames[i]);
          Service service = createService(serviceClass);
          services.addComponent(service);
          if ((profileRegistrar != null) && (service instanceof ProfileProducer))
            ((ProfileProducer) service).setProfileRegistrar(profileRegistrar);
        }
      }
    }
  }
Пример #26
0
  /**
   * Creates each of the <code>Service</code>s in order, in preparation for starting up an
   * application. At completion, this schedules an <code>AppStartupRunner</code> to finish
   * application startup.
   */
  public void run() {
    if (logger.isLoggable(Level.CONFIG))
      logger.log(Level.CONFIG, "{0}: starting services", appName);

    // create an empty context and register with the scheduler
    ComponentRegistryImpl services = new ComponentRegistryImpl();
    ComponentRegistryImpl managers = new ComponentRegistryImpl();
    AppKernelAppContext ctx = new AppKernelAppContext(appName, services, managers);
    MasterTaskScheduler scheduler = systemRegistry.getComponent(MasterTaskScheduler.class);
    try {
      scheduler.registerApplication(ctx, appProperties);
    } catch (Exception e) {
      if (logger.isLoggable(Level.SEVERE))
        logger.logThrow(Level.SEVERE, e, "{0}: failed app scheduler " + "setup", appName);
      return;
    }

    // create the application's identity, and set as the current owner
    IdentityImpl id = new IdentityImpl("app:" + appName);
    TaskOwnerImpl owner = new TaskOwnerImpl(id, ctx);
    ThreadState.setCurrentOwner(owner);

    // get the managers and services that we're using
    HashSet<Object> managerSet = new HashSet<Object>();
    try {
      fetchServices(services, managerSet);
    } catch (Exception e) {
      if (logger.isLoggable(Level.SEVERE))
        logger.logThrow(Level.SEVERE, e, "{0}: failed to create " + "services", appName);

      ctx.shutdownServices();
      return;
    }

    // register any profiling managers and fill in the manager registry
    for (Object manager : managerSet) {
      if (profileRegistrar != null) {
        if (manager instanceof ProfileProducer)
          ((ProfileProducer) manager).setProfileRegistrar(profileRegistrar);
      }
      managers.addComponent(manager);
    }

    // with the managers created, setup the final context and owner
    ctx = new AppKernelAppContext(appName, services, managers);
    owner = new TaskOwnerImpl(id, ctx);
    ThreadState.setCurrentOwner(owner);

    // notify all of the services that the application state is ready
    try {
      for (Object s : services) ((Service) s).ready();
    } catch (Exception e) {
      logger.logThrow(
          Level.SEVERE,
          e,
          "{0}: failed when notifying services that application is " + "ready",
          appName);
      // shutdown all of the services
      ctx.shutdownServices();
      return;
    }

    // At this point the services are now created, so the final step
    // is to try booting the application by running a special
    // KernelRunnable in an unbounded transaction. Note that if we're
    // running as a "server" then we don't actually start an app
    if (!appProperties
        .getProperty(StandardProperties.APP_LISTENER)
        .equals(StandardProperties.APP_LISTENER_NONE)) {
      AppStartupRunner startupRunner = new AppStartupRunner(ctx, appProperties);
      UnboundedTransactionRunner unboundedTransactionRunner =
          new UnboundedTransactionRunner(startupRunner);
      try {
        if (logger.isLoggable(Level.CONFIG))
          logger.log(Level.CONFIG, "{0}: starting application", appName);
        // run the startup task, notifying the kernel on success
        scheduler.runTask(unboundedTransactionRunner, owner, true);
        kernel.contextReady(owner, true);
      } catch (Exception e) {
        if (logger.isLoggable(Level.CONFIG))
          logger.logThrow(Level.CONFIG, e, "{0}: failed to " + "start application", appName);
        return;
      }
    } else {
      // we're running without an application, so we're finished
      kernel.contextReady(owner, false);
    }

    if (logger.isLoggable(Level.CONFIG))
      logger.log(Level.CONFIG, "{0}: finished service config runner", appName);
  }
Пример #27
0
  /**
   * Invokes the {@code disconnected} callback on this session's {@code ClientSessionListener} (if
   * present and {@code notify} is {@code true}), removes the listener and its binding (if present),
   * and then removes this session and its bindings from the specified {@code dataService}. If the
   * bindings have already been removed from the {@code dataService} this method takes no action.
   * This method should only be called within a transaction.
   *
   * @param dataService a data service
   * @param graceful {@code true} if disconnection is graceful, and {@code false} otherwise
   * @param notify {@code true} if the {@code disconnected} callback should be invoked
   * @throws TransactionException if there is a problem with the current transaction
   */
  void notifyListenerAndRemoveSession(
      final DataService dataService, final boolean graceful, boolean notify) {
    String sessionKey = getSessionKey();
    String sessionNodeKey = getSessionNodeKey();
    String listenerKey = getListenerKey();
    String eventQueueKey = getEventQueueKey();

    /*
     * Get ClientSessionListener, and remove its binding and
     * wrapper if applicable.  The listener may not be bound
     * in the data service if: the AppListener.loggedIn callback
     * either threw a non-retryable exception or returned a
     * null listener, or the application removed the
     * ClientSessionListener object from the data service.
     */
    ClientSessionListener listener = null;
    try {
      ManagedObject obj = dataService.getServiceBinding(listenerKey);
      dataService.removeServiceBinding(listenerKey);
      if (obj instanceof ListenerWrapper) {
        dataService.removeObject(obj);
        listener = ((ListenerWrapper) obj).get();
      } else {
        listener = (ClientSessionListener) obj;
      }

    } catch (NameNotBoundException e) {
      logger.logThrow(Level.FINE, e, "removing ClientSessionListener for session:{0} throws", this);
    }

    /*
     * Remove event queue and associated binding.
     */
    try {
      ManagedObject eventQueue = dataService.getServiceBinding(eventQueueKey);
      dataService.removeServiceBinding(eventQueueKey);
      dataService.removeObject(eventQueue);
    } catch (NameNotBoundException e) {
      logger.logThrow(Level.FINE, e, "removing EventQueue for session:{0} throws", this);
    }

    /*
     * Invoke listener's 'disconnected' callback if 'notify'
     * is true and a listener exists for this client session.  If the
     * 'disconnected' callback throws a non-retryable exception,
     * schedule a task to remove this session and its associated
     * bindings without invoking the listener, and rethrow the
     * exception so that the currently executing transaction aborts.
     */
    if (notify && listener != null) {
      try {
        listener.disconnected(graceful);
      } catch (RuntimeException e) {
        if (!isRetryableException(e)) {
          logger.logThrow(
              Level.WARNING,
              e,
              "invoking disconnected callback on listener:{0} " + " for session:{1} throws",
              listener,
              this);
          sessionService.scheduleTask(
              new AbstractKernelRunnable() {
                public void run() {
                  ClientSessionImpl sessionImpl = ClientSessionImpl.getSession(dataService, id);
                  sessionImpl.notifyListenerAndRemoveSession(dataService, graceful, false);
                }
              },
              identity);
        }
        throw e;
      }
    }

    /*
     * Remove this session's state and bindings.
     */
    try {
      dataService.removeServiceBinding(sessionKey);
      dataService.removeServiceBinding(sessionNodeKey);
      dataService.removeObject(this);
    } catch (NameNotBoundException e) {
      logger.logThrow(Level.WARNING, e, "session binding already removed:{0}", sessionKey);
    }

    /*
     * Remove this session's wrapper object, if it still exists.
     */
    try {
      dataService.removeObject(wrappedSessionRef.get());
    } catch (ObjectNotFoundException e) {
      // already removed
    }
  }
  /** {@inheritDoc} */
  public void report(ProfileReport profileReport) {
    if (profileReport.wasTaskSuccessful()) {
      commitCount++;
    } else {
      abortCount++;
    }

    totalRunningTime += profileReport.getRunningTime();

    for (String op : profileReport.getReportedOperations()) {
      Long i = opCounts.get(op);
      opCounts.put(op, Long.valueOf(i == null ? 1 : i + 1));
    }

    Map<String, Long> counterMap = profileReport.getUpdatedTaskCounters();
    if (counterMap != null) {
      for (Entry<String, Long> entry : counterMap.entrySet()) {
        String key = entry.getKey();
        long value = 0;
        if (localCounters.containsKey(key)) {
          value = localCounters.get(key);
        }
        localCounters.put(key, entry.getValue() + value);
      }
    }

    if ((commitCount + abortCount) >= logOps) {
      if (logger.isLoggable(Level.FINE)) {
        long now = System.currentTimeMillis();
        Formatter opCountTally = new Formatter();
        boolean first = true;
        for (String op : opCounts.keySet()) {
          if (!first) {
            opCountTally.format("%n");
          }
          first = false;
          Long count = opCounts.get(op);
          opCountTally.format("  %s: %d", op, (count == null) ? 0 : count.longValue());
          opCounts.put(op, 0L);
        }

        Formatter counterTally = new Formatter();
        if (!localCounters.isEmpty()) {
          counterTally.format("[task counters]%n");
          for (Entry<String, Long> entry : localCounters.entrySet()) {
            counterTally.format("  %s: %d%n", entry.getKey(), entry.getValue());
          }
        }

        logger.log(
            Level.FINE,
            "Operations [logOps="
                + logOps
                + "]:\n"
                + "  succeeded: "
                + commitCount
                + "  failed: "
                + abortCount
                + "\n"
                + "  elapsed time: "
                + (now - lastReport)
                + " ms\n"
                + "  running time: "
                + totalRunningTime
                + " ms "
                + "[threads="
                + threadCount
                + "]\n"
                + opCountTally.toString()
                + "\n"
                + counterTally.toString());
      } else {
        for (String op : opCounts.keySet()) {
          opCounts.put(op, 0L);
        }
      }

      commitCount = 0;
      abortCount = 0;
      totalRunningTime = 0;
      localCounters.clear();
      lastReport = System.currentTimeMillis();
    }
  }
  /**
   * Constructs an instance of this class with the specified properties.
   *
   * @param properties service properties
   * @param systemRegistry system registry
   * @param txnProxy transaction proxy
   * @throws Exception if a problem occurs when creating the service
   */
  public ClientSessionServiceImpl(
      Properties properties, ComponentRegistry systemRegistry, TransactionProxy txnProxy)
      throws Exception {
    super(properties, systemRegistry, txnProxy, logger);

    logger.log(Level.CONFIG, "Creating ClientSessionServiceImpl properties:{0}", properties);
    PropertiesWrapper wrappedProps = new PropertiesWrapper(properties);

    try {
      appPort = wrappedProps.getRequiredIntProperty(StandardProperties.APP_PORT, 1, 65535);

      /*
       * Get the property for controlling session event processing.
       */
      eventsPerTxn =
          wrappedProps.getIntProperty(
              EVENTS_PER_TXN_PROPERTY, DEFAULT_EVENTS_PER_TXN, 1, Integer.MAX_VALUE);

      readBufferSize =
          wrappedProps.getIntProperty(
              READ_BUFFER_SIZE_PROPERTY, DEFAULT_READ_BUFFER_SIZE, 8192, Integer.MAX_VALUE);

      writeBufferSize =
          wrappedProps.getIntProperty(
              WRITE_BUFFER_SIZE_PROPERTY, DEFAULT_WRITE_BUFFER_SIZE, 8192, Integer.MAX_VALUE);

      /*
       * Export the ClientSessionServer.
       */
      int serverPort =
          wrappedProps.getIntProperty(SERVER_PORT_PROPERTY, DEFAULT_SERVER_PORT, 0, 65535);
      serverImpl = new SessionServerImpl();
      exporter = new Exporter<ClientSessionServer>(ClientSessionServer.class);
      try {
        int port = exporter.export(serverImpl, serverPort);
        serverProxy = exporter.getProxy();
        if (logger.isLoggable(Level.CONFIG)) {
          logger.log(Level.CONFIG, "export successful. port:{0,number,#}", port);
        }
      } catch (Exception e) {
        try {
          exporter.unexport();
        } catch (RuntimeException re) {
        }
        throw e;
      }

      /*
       * Get services and initialize service-related and other
       * instance fields.
       */
      identityManager = systemRegistry.getComponent(IdentityCoordinator.class);
      flushContextsThread.start();
      contextFactory = new ContextFactory(txnProxy);
      watchdogService = txnProxy.getService(WatchdogService.class);
      nodeMapService = txnProxy.getService(NodeMappingService.class);
      taskService = txnProxy.getService(TaskService.class);
      localNodeId = watchdogService.getLocalNodeId();
      watchdogService.addRecoveryListener(new ClientSessionServiceRecoveryListener());
      int acceptorBacklog =
          wrappedProps.getIntProperty(ACCEPTOR_BACKLOG_PROPERTY, DEFAULT_ACCEPTOR_BACKLOG);

      /*
       * Check service version.
       */
      transactionScheduler.runTask(
          new AbstractKernelRunnable() {
            public void run() {
              checkServiceVersion(VERSION_KEY, MAJOR_VERSION, MINOR_VERSION);
            }
          },
          taskOwner);

      /*
       * Store the ClientSessionServer proxy in the data store.
       */
      transactionScheduler.runTask(
          new AbstractKernelRunnable() {
            public void run() {
              dataService.setServiceBinding(
                  getClientSessionServerKey(localNodeId),
                  new ManagedSerializable<ClientSessionServer>(serverProxy));
            }
          },
          taskOwner);

      /*
       * Listen for incoming client connections.
       */
      InetSocketAddress listenAddress = new InetSocketAddress(appPort);
      AsynchronousChannelProvider provider =
          // TODO fetch from config
          AsynchronousChannelProvider.provider();
      asyncChannelGroup =
          // TODO fetch from config
          provider.openAsynchronousChannelGroup(Executors.newCachedThreadPool());
      acceptor = provider.openAsynchronousServerSocketChannel(asyncChannelGroup);
      try {
        acceptor.bind(listenAddress, acceptorBacklog);
        if (logger.isLoggable(Level.CONFIG)) {
          logger.log(Level.CONFIG, "bound to port:{0,number,#}", getListenPort());
        }
      } catch (Exception e) {
        logger.logThrow(Level.WARNING, e, "acceptor failed to listen on {0}", listenAddress);
        try {
          acceptor.close();
        } catch (IOException ioe) {
          logger.logThrow(Level.WARNING, ioe, "problem closing acceptor");
        }
        throw e;
      }
      // TBD: listen for UNRELIABLE connections as well?

    } catch (Exception e) {
      if (logger.isLoggable(Level.CONFIG)) {
        logger.logThrow(Level.CONFIG, e, "Failed to create ClientSessionServiceImpl");
      }
      doShutdown();
      throw e;
    }
  }
Пример #30
0
  /**
   * Constructs an instance of this class with the specified {@code properties}, {@code
   * systemRegistry}, and {@code txnProxy}.
   *
   * @param properties service properties
   * @param systemRegistry system registry
   * @param txnProxy transaction proxy
   * @throws Exception if a problem occurs when creating the service
   */
  public ChannelServiceImpl(
      Properties properties, ComponentRegistry systemRegistry, TransactionProxy txnProxy)
      throws Exception {
    super(properties, systemRegistry, txnProxy, logger);

    logger.log(Level.CONFIG, "Creating ChannelServiceImpl properties:{0}", properties);
    PropertiesWrapper wrappedProps = new PropertiesWrapper(properties);

    try {
      synchronized (ChannelServiceImpl.class) {
        if (contextMap == null) {
          contextMap = new TransactionContextMap<Context>(txnProxy);
        }
      }
      contextFactory = new ContextFactory(contextMap);
      WatchdogService watchdogService = txnProxy.getService(WatchdogService.class);
      sessionService = txnProxy.getService(ClientSessionService.class);
      localNodeId = watchdogService.getLocalNodeId();

      writeBufferSize =
          wrappedProps.getIntProperty(
              WRITE_BUFFER_SIZE_PROPERTY, DEFAULT_WRITE_BUFFER_SIZE, 8192, Integer.MAX_VALUE);
      /*
       * Get the property for controlling channel event processing.
       */
      eventsPerTxn =
          wrappedProps.getIntProperty(
              EVENTS_PER_TXN_PROPERTY, DEFAULT_EVENTS_PER_TXN, 1, Integer.MAX_VALUE);

      /*
       * Export the ChannelServer.
       */
      int serverPort =
          wrappedProps.getIntProperty(SERVER_PORT_PROPERTY, DEFAULT_SERVER_PORT, 0, 65535);
      serverImpl = new ChannelServerImpl();
      exporter = new Exporter<ChannelServer>(ChannelServer.class);
      try {
        int port = exporter.export(serverImpl, serverPort);
        serverProxy = exporter.getProxy();
        logger.log(Level.CONFIG, "ChannelServer export successful. port:{0,number,#}", port);
      } catch (Exception e) {
        try {
          exporter.unexport();
        } catch (RuntimeException re) {
        }
        throw e;
      }

      /*
       * Check service version.
       */
      transactionScheduler.runTask(
          new AbstractKernelRunnable() {
            public void run() {
              checkServiceVersion(VERSION_KEY, MAJOR_VERSION, MINOR_VERSION);
            }
          },
          taskOwner);

      /*
       * Store the ChannelServer proxy in the data store.
       */
      transactionScheduler.runTask(
          new AbstractKernelRunnable() {
            public void run() {
              dataService.setServiceBinding(
                  getChannelServerKey(localNodeId),
                  new ManagedSerializable<ChannelServer>(serverProxy));
            }
          },
          taskOwner);

      /*
       * Add listeners for handling recovery and for receiving
       * notification of client session disconnection.
       */
      watchdogService.addRecoveryListener(new ChannelServiceRecoveryListener());

      watchdogService.addNodeListener(new ChannelServiceNodeListener());

      sessionService.registerSessionDisconnectListener(new ChannelSessionDisconnectListener());

    } catch (Exception e) {
      if (logger.isLoggable(Level.CONFIG)) {
        logger.logThrow(Level.CONFIG, e, "Failed to create ChannelServiceImpl");
      }
      doShutdown();
      throw e;
    }
  }