/** Start the thread that periodically updates the metadata. */
  public void startUpdating() {
    if (update == true) {
      return;
    }

    final Sink metadataSink = new Sink();
    try {
      metadataSink.OpenRBNBConnection(rbnbController.getRBNBConnectionString(), rbnbSinkName);
    } catch (SAPIException e) {
      log.error("Failed to connect to RBNB server: " + e.getMessage());
      e.printStackTrace();
      return;
    }

    updateMetadata(metadataSink);

    updateThread =
        new Thread("MetadataManager") {
          public void run() {
            log.info("RBNB Metadata thread is starting.");

            updateMetadataThread(metadataSink);

            metadataSink.CloseRBNBConnection();

            channels.clear();
            ctree = null;

            log.info("RBNB Metadata thread is stopping.");
          }
        };
    update = true;
    updateThread.start();
  }
  /**
   * Updates the metadata and posts it to listeners. It also notifies all threads waiting on this
   * object.
   *
   * @param metadataSink the RBNB sink to use for the server connection
   */
  private synchronized void updateMetadata(Sink metadataSink) {
    // log.info("Updating channel listing at " + DataViewer.formatDate(System.currentTimeMillis
    // ()));

    Map<String, Channel> newChannels = new HashMap<String, Channel>();

    ChannelTree channelTree;
    try {
      // create metadata channel tree
      channelTree = getChannelTree(metadataSink, newChannels);
    } catch (SAPIException e) {
      log.error("Failed to update metadata: " + e.getMessage() + ".");

      if (!metadataSink.VerifyConnection()) {
        log.error(
            "Metadata RBNB connection is severed, try to reconnect to "
                + rbnbController.getRBNBConnectionString()
                + ".");
        metadataSink.CloseRBNBConnection();
        try {
          metadataSink.OpenRBNBConnection(rbnbController.getRBNBConnectionString(), "RDVMetadata");
        } catch (SAPIException error) {
          log.error("Failed to connect to RBNB server: " + error.getMessage());
          error.printStackTrace();
        }
      }

      return;
    }

    if (LocalChannelManager.getInstance().hasChannels()) {
      ChannelTree localChannelTree = getLocalChannelTree(newChannels, channelTree);
      ctree = localChannelTree.merge(channelTree);
    } else {
      ctree = channelTree;
    }

    channels = newChannels;

    // notify metadata listeners
    fireMetadataUpdated(ctree);
  }