<commit_before>/**
 * @license
 * Copyright 2020 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.nanos.medusa',
  name: 'DefaultDaggerService',

  implements: [
    'foam.nanos.medusa.DaggerService',
    'foam.nanos.NanoService'
  ],

  axioms: [
    foam.pattern.Singleton.create()
  ],

  documentation: `Manage global indexes and hashes`,

  javaImports: [
    'foam.dao.ArraySink',
    'foam.dao.DAO',
    'static foam.mlang.MLang.*',
    'foam.nanos.logger.PrefixLogger',
    'foam.nanos.logger.Logger',
    'foam.nanos.pm.PM',
    'foam.util.SafetyUtil',
    'java.nio.charset.StandardCharsets',
    'java.security.MessageDigest',
    'java.util.ArrayList',
    'java.util.List'
  ],

  axioms: [
    {
      name: 'javaExtras',
      buildJavaClass: function(cls) {
        cls.extras.push(foam.java.Code.create({
          data: `
  public static String byte2Hex(byte[] bytes) {
    StringBuffer stringBuffer = new StringBuffer();
    String temp = null;
    for (int i=0;i<bytes.length;i++){
      temp = Integer.toHexString(bytes[i] & 0xFF);
      if (temp.length()==1){
        stringBuffer.append("0");
      }
      stringBuffer.append(temp);
    }
    return stringBuffer.toString();
  }
          `
        }));
      }
    }
  ],

  constants: [
    {
      name: 'BOOTSTRAP_INDEX',
      value: 0,
      type: 'Long'
    },
    {
      name: 'NUM_BOOTSTRAP_ENTRIES',
      value: 2,
      type: 'Long'
    }
  ],

  properties: [
    {
      name: 'index',
      label: 'Global Index',
      class: 'Long',
      visibility: 'RO'
    },
    {
      name: 'hashingEnabled',
      class: 'Boolean',
      value: true
    },
    {
      name: 'algorithm',
      class: 'String',
      value: 'SHA-256'
    },
    {
      documentation: `Current links[] index to use. linksIndex flips back forth between 0 and 1.`,
      name: 'linksIndex',
      class: 'Int',
      value: 1,
      visibility: 'HIDDEN'
    },
    {
      name: 'links',
      class: 'Array',
      javaFactory: 'return new foam.nanos.medusa.DaggerLink[2];',
      visibility: 'HIDDEN'
    },
    {
      name: 'initialized',
      class: 'Boolean',
      value: false,
      visibility: 'HIDDEN'
    },
    {
      name: 'dao',
      class: 'foam.dao.DAOProperty',
      javaFactory: `
      return (DAO) getX().get("internalMedusaDAO");
      `
    },
    {
      name: 'logger',
      class: 'FObjectProperty',
      of: 'foam.nanos.logger.Logger',
      visibility: 'HIDDEN',
      javaFactory: `
      return new PrefixLogger(new Object[] {
        this.getClass().getSimpleName()
      }, (Logger) getX().get("logger"));
      `
    }
  ],

  methods: [
    {
      name: 'start',
      javaCode: `
      ClusterConfigSupport support = (ClusterConfigSupport) getX().get("clusterConfigSupport");
      setHashingEnabled(support.getHashingEnabled());

      ClusterConfig config = support.getConfig(getX(), support.getConfigId());
      if ( config == null ||
           config.getType() == MedusaType.NODE ||
           config.getZone() > 0L ) {
        getLogger().debug("start", "exit");
        return;
      }

      for ( int i = 0; i < getLinks().length; i++ ) {
        getLinks()[i] = new MedusaEntry.Builder(getX()).setIndex(BOOTSTRAP_INDEX).setHash(getBootstrapHash(getX())).build();
      }

      DAO dao = getDao();

      MedusaEntry entry = new MedusaEntry();
      entry = link(getX(), entry);
      entry = hash(getX(), entry);
      entry.setNSpecName("daggerService");
      entry.setNode(support.getConfigId());
      entry.setPromoted(true);
      entry = (MedusaEntry) dao.put_(getX(), entry);
      updateLinks(getX(), entry);

      entry = new MedusaEntry();
      entry = link(getX(), entry);
      entry = hash(getX(), entry);
      entry.setNSpecName("daggerService");
      entry.setNode(support.getConfigId());
      entry.setPromoted(true);
      entry = (MedusaEntry) dao.put_(getX(), entry);
      updateLinks(getX(), entry);
     `
    },
    {
      documentation: `// TODO: get initial hash from HSM for new deployment`,
      name: 'getBootstrapHash',
      args: [
        {
          name: 'x',
          type: 'Context'
        }
      ],
      type: 'String',
      javaCode: `
      return "466c58623cd600209e95a981bad03e5d899ea6d6905cebee5ea0746bf16e1534";
      `
    },
    {
      name: 'link',
      javaCode: `
      DaggerLinks links = getNextLinks(x);
      entry.setIndex(links.getGlobalIndex());
      entry.setIndex1(links.getLink1().getIndex());<commit_msg>Update documentation. Provide for setting bootstrap hash via JVM -Dproperty<commit_after>/**
 * @license
 * Copyright 2020 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.nanos.medusa',
  name: 'DefaultDaggerService',

  implements: [
    'foam.nanos.medusa.DaggerService',
    'foam.nanos.NanoService'
  ],

  axioms: [
    foam.pattern.Singleton.create()
  ],

  documentation: `Manage global indexes and hashes`,

  javaImports: [
    'foam.dao.ArraySink',
    'foam.dao.DAO',
    'static foam.mlang.MLang.*',
    'foam.nanos.logger.PrefixLogger',
    'foam.nanos.logger.Logger',
    'foam.nanos.pm.PM',
    'foam.util.SafetyUtil',
    'java.nio.charset.StandardCharsets',
    'java.security.MessageDigest',
    'java.util.ArrayList',
    'java.util.List'
  ],

  axioms: [
    {
      name: 'javaExtras',
      buildJavaClass: function(cls) {
        cls.extras.push(foam.java.Code.create({
          data: `
  public static String byte2Hex(byte[] bytes) {
    StringBuffer stringBuffer = new StringBuffer();
    String temp = null;
    for (int i=0;i<bytes.length;i++){
      temp = Integer.toHexString(bytes[i] & 0xFF);
      if (temp.length()==1){
        stringBuffer.append("0");
      }
      stringBuffer.append(temp);
    }
    return stringBuffer.toString();
  }
          `
        }));
      }
    }
  ],

  properties: [
    {
      documentation: 'Starting index.',
      name: 'bootstrapIndex',
      class: 'Long',
      value: 0
    },
    {
      documentation: 'Number of manually created entries to prime the system.',
      name: 'numBootstrapEntries',
      class: 'Long',
      value: 2
    },
    {
      documentation: `When false don't use a MessageDigest to calculate a hash. Provided for testing purposes only.`,
      name: 'hashingEnabled',
      class: 'Boolean',
      value: true
    },
    {
      name: 'algorithm',
      class: 'String',
      value: 'SHA-256'
    },
    {
      documentation: 'Current max promoted index',
      name: 'index',
      label: 'Global Index',
      class: 'Long',
      visibility: 'RO'
    },
    {
      documentation: `Current links[] index to use. linksIndex flips back forth between 0 and 1.`,
      name: 'linksIndex',
      class: 'Int',
      value: 1,
      visibility: 'HIDDEN'
    },
    {
      name: 'links',
      class: 'Array',
      javaFactory: 'return new foam.nanos.medusa.DaggerLink[2];',
      visibility: 'HIDDEN'
    },
    {
      name: 'initialized',
      class: 'Boolean',
      value: false,
      visibility: 'HIDDEN'
    },
    {
      name: 'dao',
      class: 'foam.dao.DAOProperty',
      javaFactory: `
      return (DAO) getX().get("internalMedusaDAO");
      `,
      visibility: 'HIDDEN'
    },
    {
      name: 'logger',
      class: 'FObjectProperty',
      of: 'foam.nanos.logger.Logger',
      transient: true,
      visibility: 'HIDDEN',
      javaFactory: `
      return new PrefixLogger(new Object[] {
        this.getClass().getSimpleName()
      }, (Logger) getX().get("logger"));
      `
    }
  ],

  methods: [
    {
      name: 'start',
      javaCode: `
      ClusterConfigSupport support = (ClusterConfigSupport) getX().get("clusterConfigSupport");
      setHashingEnabled(support.getHashingEnabled());

      ClusterConfig config = support.getConfig(getX(), support.getConfigId());
      if ( config == null ||
           config.getType() == MedusaType.NODE ||
           config.getZone() > 0L ) {
        getLogger().debug("start", "exit");
        return;
      }

      for ( int i = 0; i < getLinks().length; i++ ) {
        getLinks()[i] = new MedusaEntry.Builder(getX()).setIndex(getBootstrapIndex()).setHash(getBootstrapHash(getX())).build();
      }

      DAO dao = getDao();

      for ( int i = 0; i < getNumBootstrapEntries(); i++ ) {
        MedusaEntry entry = new MedusaEntry();
        entry = link(getX(), entry);
        entry = hash(getX(), entry);
        entry.setNSpecName("daggerService");
        entry.setNode(support.getConfigId());
        entry.setPromoted(true);
        entry = (MedusaEntry) dao.put_(getX(), entry);
        updateLinks(getX(), entry);
      }
     `
    },
    {
      documentation: `Initial hash to prime the system. Provide via:
    - JAVA_OPTS property:  -DBOOTSTRAP_HASH=
    - Explicitly set in DaggerService NSpec
    - // TODO: HSM`,
      name: 'getBootstrapHash',
      args: [
        {
          name: 'x',
          type: 'Context'
        }
      ],
      type: 'String',
      javaCode: `
      return System.getProperty(
                "BOOTSTRAP_HASH",
                "466c58623cd600209e95a981bad03e5d899ea6d6905cebee5ea0746bf16e1534"
             );
      `
    },
    {
      name: 'link',
      javaCode: `
      DaggerLinks links = getNextLinks(x);
      entry.setIndex(links.getGlobalIndex());
      entry.setIndex1(links.getLink1().getIndex());
{'fraction_non_alphanumeric': 0.14879257618896974, 'fraction_numerical': 0.013814193820520931, 'mean_word_length': 2.2771250863856256, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2358533', 'n_tokens_mistral': 3198, 'n_tokens_neox': 3106, 'n_words': 591}