Package org.openntf.domino.tests.jpg

Source Code of org.openntf.domino.tests.jpg.ShardingDatabase

package org.openntf.domino.tests.jpg;

import static java.lang.Math.pow;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.openntf.domino.Database;
import org.openntf.domino.DbDirectory;
import org.openntf.domino.Document;
import org.openntf.domino.Session;

/**
* @author jgallagher
*
*/
public class ShardingDatabase {
  private final Session session_;

  private final String server_;
  private final HashingStrategy hashingStrategy_;
  private final ServerStrategy serverStrategy_;

  private final String baseName_;
  private boolean recalcOnSave_;
  private final Map<String, Database> dbCache_ = new HashMap<String, Database>();
  private final Map<String, DbDirectory> dbdirCache_ = new HashMap<String, DbDirectory>();
  private final int places_;

  public ShardingDatabase(final Session session, final HashingStrategy hashingStrategy, final String server, final String baseName,
      final int places) {
    if (session == null)
      throw new IllegalArgumentException("session cannot be null");
    if (baseName == null || baseName.length() == 0)
      throw new IllegalArgumentException("baseName cannot be null or zero-length");
    if (places < 0)
      throw new IllegalArgumentException("databases must be nonnegative");

    session_ = session;
    baseName_ = baseName.toLowerCase().endsWith(".nsf") ? baseName.substring(0, baseName.length() - 4) : baseName;
    places_ = places;

    hashingStrategy_ = hashingStrategy;
    server_ = server == null ? "" : server;
    dbdirCache_.put("only", session_.getDbDirectory(server_));
    serverStrategy_ = null;
  }

  public ShardingDatabase(final Session session, final HashingStrategy hashingStrategy, final ServerStrategy serverStrategy,
      final String baseName, final int places) {
    if (session == null)
      throw new IllegalArgumentException("session cannot be null");
    if (baseName == null || baseName.length() == 0)
      throw new IllegalArgumentException("baseName cannot be null or zero-length");
    if (places < 1)
      throw new IllegalArgumentException("places must be greater than zero");
    if (serverStrategy == null)
      throw new IllegalArgumentException("serverStrategy cannot be null");

    session_ = session;
    baseName_ = baseName.toLowerCase().endsWith(".nsf") ? baseName.substring(0, baseName.length() - 4) : baseName;
    places_ = places;

    hashingStrategy_ = hashingStrategy;
    server_ = null;
    serverStrategy_ = serverStrategy;
  }

  public void initializeDatabases() {
    if (places_ > 0) {
      for (int i = 0; i < pow(16, places_); i++) {
        String hashChunk = Integer.toString(i, 16).toLowerCase();
        while (hashChunk.length() < places_)
          hashChunk = "0" + hashChunk;
        String server = serverStrategy_ == null ? server_ : serverStrategy_.getServerForHashChunk(hashChunk);
        DbDirectory dbdir = getDbDirectoryForHashChunk(hashChunk);
        String dbName = baseName_ + "-" + hashChunk + ".nsf";
        Database database = session_.getDatabase(server, dbName, true);
        if (!database.isOpen()) {
          database = createDatabase(dbdir, dbName);
        }
        dbCache_.put(dbName, database);
      }
    } else {
      Database database = session_.getDatabase(server_, baseName_ + ".nsf");
      if (!database.isOpen()) {
        database = createDatabase(getDbDirectoryForHashChunk(null), baseName_ + ".nsf");
      }
      dbCache_.put(baseName_ + ".nsf", database);
    }
  }

  public ShardingDocument createDocument() {
    return new ShardingDocument(getStagingDatabase().createDocument());
  }

  public ShardingDocument getDocumentByUNID(final String unid) {
    return new ShardingDocument(getDatabaseForHash(unid).getDocumentByUNID(unid));
  }

  private Database getStagingDatabase() {
    StringBuilder builder = new StringBuilder();
    for (int i = 0; i < places_; i++) {
      builder.append('0');
    }
    String hashChunk = builder.toString();
    String dbName = baseName_ + "-" + hashChunk + ".nsf";

    if (!dbCache_.containsKey(dbName)) {
      String server = serverStrategy_ == null ? server_ : serverStrategy_.getServerForHashChunk(hashChunk);
      Database database = session_.getDatabase(server, dbName, true);
      if (!database.isOpen()) {
        DbDirectory dbdir = getDbDirectoryForHashChunk(hashChunk);
        database = createDatabase(dbdir, dbName);
      }
      dbCache_.put(dbName, database);
    }

    return dbCache_.get(dbName);
  }

  private Database getDatabaseForHash(final String hash) {
    String hashChunk = hash.substring(0, places_);
    String dbName = baseName_ + "-" + hashChunk + ".nsf";

    if (!dbCache_.containsKey(dbName)) {
      String server = serverStrategy_ == null ? server_ : serverStrategy_.getServerForHashChunk(hashChunk);
      Database database = session_.getDatabase(server, dbName, true);
      if (!database.isOpen()) {
        DbDirectory dbdir = getDbDirectoryForHashChunk(hashChunk);
        database = createDatabase(dbdir, dbName);
      }
      dbCache_.put(dbName, database);
    }

    return dbCache_.get(dbName);
  }

  private DbDirectory getDbDirectoryForHashChunk(final String hashChunk) {
    if (server_ != null) {
      return dbdirCache_.get("only");
    } else {
      if (!dbdirCache_.containsKey(hashChunk)) {
        String server = serverStrategy_ == null ? server_ : serverStrategy_.getServerForHashChunk(hashChunk);
        dbdirCache_.put(hashChunk, session_.getDbDirectory(server));
      }
      return dbdirCache_.get(hashChunk);
    }
  }

  private Database createDatabase(final DbDirectory dbdir, final String dbName) {
    Database database = dbdir.createDatabase(dbName, true);
    database.createView();
    database.setOption(Database.DBOption.LZ1, true);
    database.setOption(Database.DBOption.COMPRESSDESIGN, true);
    database.setOption(Database.DBOption.COMPRESSDOCUMENTS, true);
    database.setOption(Database.DBOption.NOUNREAD, true);
    return database;
  }

  public interface ServerStrategy {
    String getServerForHashChunk(final String hashChunk);
  }

  public interface HashingStrategy {
    String getHashForMap(final Map<String, Object> doc);
  }

  public class ShardingDocument {
    private Document doc_;

    protected ShardingDocument(final Document origDoc) {
      doc_ = origDoc;
    }

    public Object getItemValue(final String itemName) {
      return doc_.getItemValue(itemName);
    }

    public void replaceItemValue(final String itemName, final Object value) {
      doc_.replaceItemValue(itemName, value);
    }

    public Document getDoc() {
      return doc_;
    }

    public boolean save() {
      Database destDB;
      if (doc_.isNewNote() && hashingStrategy_ != null) {
        String hash = hashingStrategy_.getHashForMap(doc_);
        doc_.setUniversalID(hash);
        doc_.replaceItemValue("$Created", new Date());
        destDB = getDatabaseForHash(hash);
      } else {
        destDB = getDatabaseForHash(doc_.getUniversalID());
      }

      Database currentDB = doc_.getParentDatabase();
      if (!(currentDB.getFilePath().equalsIgnoreCase(destDB.getFilePath()) && currentDB.getServer().equalsIgnoreCase(
          destDB.getServer()))) {

        Document destDoc = destDB.createDocument();
        doc_.copyAllItems(destDoc, true);
        destDoc.replaceItemValue("$Created", doc_.getCreated());
        destDoc.setUniversalID(doc_.getUniversalID());
        doc_ = destDoc;
      }

      return doc_.save();
    }
  }

  public boolean isRecalcOnSave() {
    return recalcOnSave_;
  }

  public void setRecalcOnSave(final boolean recalcOnSave) {
    this.recalcOnSave_ = recalcOnSave;
  }
}
TOP

Related Classes of org.openntf.domino.tests.jpg.ShardingDatabase

TOP
Copyright © 2018 www.massapi.com. 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.