/**
   * Set NetworkTypeahead weighted connections store maxScn.
   *
   * <pre>
   * JVM arguments:
   *     -server -Xms4g -Xmx8g
   *
   * Program arguments:
   *     network-typeahead-member.config maxScn
   * </pre>
   *
   * @param args
   * @throws Exception
   */
  public static void main(String[] args) throws Exception {
    /** Load properties. */
    Properties properties = new Properties();
    try {
      String configFile = args[0];
      FileInputStream inStream = new FileInputStream(configFile);
      InputStreamReader reader = new InputStreamReader(inStream, "UTF-8");
      properties.load(reader);
      PropertiesResolver.resolve(properties);
      properties.list(System.out);
    } catch (Exception e) {
      e.printStackTrace();
      System.exit(1);
    }

    long maxScn = 0;
    try {
      maxScn = Long.parseLong(args[1]);
    } catch (Exception e) {
      e.printStackTrace();
      System.exit(1);
    }

    Chronos c = new Chronos();
    NetworkTypeaheadConfig<TypeaheadElement> config;
    WeightedNetworkTypeaheadInitializer<TypeaheadElement> initializer;

    /** Configure NetworkTypeahead */
    config = TypeaheadConfigFactory.createNetworkTypeaheadConfig(properties);
    config.setElementStoreCached(false); // disable cache to bypass serialization
    config.setElementStoreSegmentFactory(new ChannelSegmentFactory());
    config.setConnectionsStoreSegmentFactory(new ChannelSegmentFactory());
    initializer = new WeightedNetworkTypeaheadInitializer<TypeaheadElement>(config);

    WeightedNetworkTypeahead<TypeaheadElement> typeahead =
        (WeightedNetworkTypeahead<TypeaheadElement>) initializer.getTypeahead();

    // Set NetworkTypehead connections store hwMark
    typeahead.getConnectionsStore().saveHWMark(maxScn);
    typeahead.getConnectionsStore().sync();

    System.out.printf("Time: %d ms.%n", c.tick());
  }
  /**
   *
   *
   * <pre>
   * java NetworkTypeaheadWeightedConnectionsStoreBootstrap -server -Xms4G -Xmx16G \
   *      connectionsDir maxScn configFile ...
   *
   * java NetworkTypeaheadWeightedConnectionsStoreBootstrap -server -Xms4G -Xmx16G \
   *      bootstrap/member/connections 170403771779 \
   *      config/network-typeahead/member/i001.config \
   *      config/network-typeahead/member/i002.config \
   *      config/network-typeahead/member/i003.config
   * </pre>
   *
   * @param args
   * @throws Exception
   */
  public static void main(String args[]) throws Exception {
    Chronos c = new Chronos();
    MultiConnectionsHandler multiHandler = new MultiConnectionsHandler();

    File connectionsDir = new File(args[0]);
    long maxScn = Long.parseLong(args[1]);
    for (int i = 2; i < args.length; i++) {
      /** Load bootstrap properties. */
      Properties properties = new Properties();
      try {
        String configFile = args[i];
        FileInputStream inStream = new FileInputStream(configFile);
        InputStreamReader reader = new InputStreamReader(inStream, "UTF-8");
        properties.load(reader);
        PropertiesResolver.resolve(properties);
        properties.list(System.out);
      } catch (Exception e) {
        e.printStackTrace();
        System.exit(1);
      }

      /** Configure NetworkTypeahead */
      NetworkTypeaheadConfig<TypeaheadElement> config =
          TypeaheadConfigFactory.createNetworkTypeaheadConfig(properties);
      config.setElementStoreCached(false); // disable cache to bypass serialization
      config.setElementStoreSegmentFactory(new ChannelSegmentFactory());
      config.setConnectionsStoreSegmentFactory(
          new WriteBufferSegmentFactory(config.getConnectionsStoreSegmentMB()));

      WeightedNetworkTypeaheadInitializer<TypeaheadElement> initializer =
          new WeightedNetworkTypeaheadInitializer<TypeaheadElement>(config);
      WeightedNetworkTypeahead<TypeaheadElement> typeahead =
          (WeightedNetworkTypeahead<TypeaheadElement>) initializer.getTypeahead();

      ConnectionFilter connectionFilter = typeahead.getConnectionFilter();
      ArrayStoreWeights weightedConnectionsStore = typeahead.getConnectionsStore();
      System.out.printf("Added %s%n", config.getConnectionsStoreDir().getParent());

      multiHandler.add(
          new WeightedConnectionsStoreConnectionsHandler(
              weightedConnectionsStore, connectionFilter, maxScn));
    }

    if (multiHandler.isEmpty()) return;

    /** Bootstrap weighted-connections-store */
    System.out.println("-- starting bootstrap --");

    ConnectionsScanner scanner = new ConnectionsScanner(connectionsDir);
    scanner.scan(multiHandler);

    Iterator<ConnectionsHandler> iter = multiHandler.iterator();
    while (iter.hasNext()) {
      ArrayStoreWeights weightedConnectionsStore;
      weightedConnectionsStore =
          ((WeightedConnectionsStoreConnectionsHandler) iter.next()).getWeightedConnectionsStore();
      weightedConnectionsStore.sync();
    }

    System.out.println();
    System.out.printf("Bootstrap done in %d seconds%n", c.getTotalTime() / 1000);
  }
  @Override
  protected WeightedNetworkTypeahead<SimpleElement> createTypeahead() throws Exception {
    NetworkTypeaheadConfig<SimpleElement> config = new NetworkTypeaheadConfig<SimpleElement>();

    config.setName("Network");

    config.setPartitionStart(getPartitionStart());
    config.setPartitionCount(getPartitionCount());

    config.setElementSerializer(createElementSerializer());
    config.setElementStoreDir(new File(getHomeDir(), "element-store"));
    config.setElementStoreIndexStart(getElementStoreIndexStart());
    config.setElementStoreCapacity(getElementStoreCapacity());
    config.setElementStoreSegmentMB(32);

    config.setConnectionsStoreDir(new File(getHomeDir(), "weighted-connections-store"));
    config.setConnectionsStoreIndexStart(getConnectionsStoreIndexStart());
    config.setConnectionsStoreCapacity(getConnectionsStoreCapacity());
    config.setConnectionsStoreSegmentMB(32);

    config.setConnectionFilter(createConnectionFilter());
    config.setSelectorFactory(createSelectorFactory());
    config.setFilterPrefixLength(getFilterPrefixLength());

    WeightedNetworkTypeaheadInitializer<SimpleElement> initializer =
        new WeightedNetworkTypeaheadInitializer<SimpleElement>(config);

    return (WeightedNetworkTypeahead<SimpleElement>) initializer.getTypeahead();
  }