Package com.facebook.LinkBench

Source Code of com.facebook.LinkBench.LinkStoreRocksDb

/*
* Copyright 2012, Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.facebook.LinkBench;

import com.facebook.rocks.swift.*;
import com.facebook.swift.service.ThriftClientManager;
import com.facebook.nifty.client.FramedClientConnector;
import com.google.common.net.HostAndPort;
import org.apache.thrift.transport.TTransportException;

import java.io.IOException;
import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.commons.codec.binary.Hex;

import static com.google.common.net.HostAndPort.fromParts;

/*
* This file implements Linkbench methods for loading/requesting data to rocksDb
* database server by calling thrift apis after creating a java thrift client
* through swift : rocksClient for the link and the node operations.
*/

public class LinkStoreRocksDb extends GraphStore {
  private static final ThriftClientManager clientManager =
    new ThriftClientManager();
  private ThreadLocal<RocksService> rocksClient =
      new ThreadLocal<RocksService>();

  /* RocksDb database server configuration keys */
  public static final String CONFIG_HOST = "host";
  public static final String CONFIG_PORT = "port";
  public static final String CONFIG_WRITE_SYNC = "write_options_sync";
  public static final String CONFIG_WRITE_DISABLE_WAL =
    "write_options_disableWAL";

  public static final String CONFIG_USER = "user";
  public static final String CONFIG_PASSWORD = "password";

  public static final int DEFAULT_BULKINSERT_SIZE = 1024;
  private static final boolean INTERNAL_TESTING = false;

  private static int totalThreads = 0;

  String host;
  int port;
  WriteOptions writeOptions;
  String user;
  String pwd;

  Level debuglevel;

  int bulkInsertSize = DEFAULT_BULKINSERT_SIZE;

  private final Logger logger = Logger.getLogger(ConfigUtil.LINKBENCH_LOGGER);

  private RocksService getRocksClient() throws Exception {
    if (rocksClient.get() == null) {
      try {
        rocksClient.set(clientManager.createClient(
          new FramedClientConnector(fromParts(host, port)),
          RocksService.class).get());
        logger.info("Opened Rocksdb connection to " + host
                    + ":" + port);
      } catch (Exception e) {
        logger.error("Error in open rocksdb to " + host
                     + ":" + port + " " + e);
        throw e;
      }
    }
    return rocksClient.get();
  }

  static synchronized void incrThreads() {
     totalThreads++;
  }

  static synchronized boolean isLastThread() {
    if (--totalThreads == 0) {
      return true;
    } else {
      return false;
    }
  }

  @Override
  public void close() {
    try {
      if (!isLastThread()) {
        return;
      }
      if (clientManager != null) {
        clientManager.close();
      }
    } catch (Exception ioex) {
      logger.error("Error while closing client connection: " + ioex);
    }
  }

  @Override
  public void initialize(Properties p, Phase currentPhase, int threadId)
      throws IOException, Exception {
    incrThreads();
    host = ConfigUtil.getPropertyRequired(p, CONFIG_HOST);
    port = ConfigUtil.getInt(p, CONFIG_PORT);
    writeOptions = new WriteOptions();
    writeOptions.setSync(ConfigUtil.getBool(p, CONFIG_WRITE_SYNC, false));
    writeOptions.setDisableWAL(
      ConfigUtil.getBool(p, CONFIG_WRITE_DISABLE_WAL, false));
    debuglevel = ConfigUtil.getDebugLevel(p);
  }

  public LinkStoreRocksDb() {
    super();
  }

  public LinkStoreRocksDb(Properties props) throws IOException, Exception {
    super();
    initialize(props, Phase.LOAD, 0);
  }

  public void clearErrors(int threadID) {
    logger.warn("Closing Rocksdb connection in threadID " + threadID);
    try {
      if (rocksClient.get() != null) {
        rocksClient.get().close();
        rocksClient.remove();
      }
    } catch (Throwable e) {
      logger.error("Error in Reopen!" + e);
      e.printStackTrace();
    }
  }

  @Override
  public boolean addLink(String dbid, Link l, boolean noinverse)
      throws Exception{
    try {
      return addLinkImpl(dbid, l, noinverse);
    } catch (Exception ex) {
      logger.error("addlink failed! " + ex);
      throw ex;
    }
  }

  private boolean addLinkImpl(String dbid, Link l, boolean noinverse)
      throws Exception {

    if (Level.DEBUG.isGreaterOrEqual(debuglevel)) {
      logger.debug("addLink " + l.id1 +
                         "." + l.id2 +
                         "." + l.link_type);
    }
    AssocVisibility av = AssocVisibility.values()[l.visibility];
    String s = "wormhole...";
    dbid += "assocs";
    long result = getRocksClient().TaoAssocPut(
        dbid.getBytes(), l.link_type, l.id1, l.id2, l.time,
        av, true, Long.valueOf(l.version), l.data, s.getBytes(),
        writeOptions);

    return result == 1;
  }

  /**
   * Internal method: add links without updating the count
   */
  private boolean addLinksNoCount(String dbid, List<Link> links)
      throws Exception {
    if (links.size() == 0)
      return false;

    dbid += "assocs";
    for (Link l:links) {
      AssocVisibility av = AssocVisibility.values()[l.visibility];
      String s = "wormhole...";
      long result =
      getRocksClient().TaoAssocPut(dbid.getBytes(), l.link_type, l.id1,
         l.id2, l.time, av, false, Long.valueOf(l.version), l.data,
         s.getBytes(), writeOptions);
    }
    return true;
}

  @Override
  public boolean deleteLink(String dbid, long id1, long link_type, long id2,
                         boolean noinverse, boolean expunge)
    throws Exception {
    try {
      return deleteLinkImpl(dbid, id1, link_type, id2, noinverse, expunge);
    } catch (Exception ex) {
      logger.error("deletelink failed! " + ex);
      throw ex;
    }
  }

  private boolean deleteLinkImpl(String dbid, long id1, long link_type,
    long id2, boolean noinverse, boolean expunge) throws Exception {
    if (Level.DEBUG.isGreaterOrEqual(debuglevel)) {
      logger.debug("deleteLink " + id1 +
                         "." + id2 +
                         "." + link_type);
    }
    String s = "wormhole...";
    dbid += "assocs";
    long result = getRocksClient().TaoAssocDelete(
      dbid.getBytes() , link_type, id1, id2,
      -1 /*version ignored*/, AssocVisibility.HARD_DELETE, true,
      s.getBytes(), writeOptions);
    return result == 1;
  }

  @Override
  public boolean updateLink(String dbid, Link l, boolean noinverse)
    throws Exception {
    // Retry logic is in addLink
    boolean added = addLink(dbid, l, noinverse);
    return !added; // return true if updated instead of added
  }


  // lookup using id1, type, id2
  @Override
  public Link getLink(String dbid, long id1, long link_type, long id2)
    throws Exception {
    try {
      return getLinkImpl(dbid, id1, link_type, id2);
    } catch (Exception ex) {
      logger.error("getLink failed! " + ex);
      throw ex;
    }
  }

  private Link getLinkImpl(String dbid, long id1, long link_type, long id2)
    throws Exception {
    Link res[] = multigetLinks(dbid, id1, link_type, new long[] {id2});
    if (res == null)
      return null;
    assert(res.length <= 1);
    return res.length == 0 ? null : res[0];
  }


  @Override
  public Link[] multigetLinks(String dbid, long id1, long link_type,
    long[] id2s) throws Exception {
    try {
      return multigetLinksImpl(dbid, id1, link_type, id2s);
    } catch (Exception ex) {
      logger.error("multigetlinks failed! " + ex);
      throw ex;
    }
  }

  private Link[] multigetLinksImpl(String dbid, long id1, long link_type,
    long[] id2s) throws Exception {
    List<Long> l = new ArrayList<Long>();
    for (int i = 0; i < id2s.length; i++) {
      l.add(new Long(id2s[i]));
    }
    dbid += "assocs";
    List<TaoAssocGetEntry> tr = getRocksClient().TaoAssocGetID2s(
        dbid.getBytes(),
      link_type, id1, l);
    Link results[] = new Link[tr.size()];
    int i = 0;
    for (TaoAssocGetEntry tar : tr) {
      results[i] = new Link(id1, link_type, tar.getId2(),
          LinkStore.VISIBILITY_DEFAULT, tar.getData(),
          (int)(tar.getVersion()), tar.getTime());
    }
    return results;
  }

  // lookup using just id1, type
  @Override
  public Link[] getLinkList(String dbid, long id1, long link_type)
    throws Exception {
    return getLinkListImpl(
        dbid, id1, link_type, 0, Long.MAX_VALUE, 0, rangeLimit);
  }

  @Override
  public Link[] getLinkList(String dbid, long id1, long link_type,
    long minTimestamp, long maxTimestamp, int offset, int limit)
    throws Exception {
    try {
      return getLinkListImpl(dbid, id1, link_type, minTimestamp,
                             maxTimestamp, offset, limit);
    } catch (Exception ex) {
      logger.error("getLinkList failed! " + ex);
      throw ex;
    }
  }

  private Link[] getLinkListImpl(String dbid, long id1, long link_type,
    long minTimestamp, long maxTimestamp, int offset, int limit)
    throws Exception {
    dbid += "assocs";
    List<TaoAssocGetEntry> tr = getRocksClient().TaoAssocGetTimeRange(
        dbid.getBytes(), link_type, id1, minTimestamp, maxTimestamp,
        Long.valueOf(offset), Long.valueOf(limit));
    Link results[] = new Link[tr.size()];
    int i = 0;
    for (TaoAssocGetEntry tar : tr) {
      results[i] = new Link(id1, link_type, tar.getId2(),
          LinkStore.VISIBILITY_DEFAULT, tar.getData(),
          (int)(tar.getVersion()), tar.getTime());
      i++;
    }
    return results;
  }

  // count the #links
  @Override
  public long countLinks(String dbid, long id1, long link_type)
    throws Exception {
    try {
      return countLinksImpl(dbid, id1, link_type);
    } catch (Exception ex) {
      logger.error("countLinks failed! " + ex);
      throw ex;
    }
  }

  private long countLinksImpl(String dbid, long id1, long link_type)
    throws Exception {
    dbid += "assocs";
    long count = getRocksClient().TaoAssocCount(
      dbid.getBytes(), link_type, id1);
    if (Level.TRACE.isGreaterOrEqual(debuglevel)) {
      logger.trace("Count result: " + id1 + "," + link_type +
                         " is " + count);
    }
    return count;
  }

  @Override
  public int bulkLoadBatchSize() {
    return bulkInsertSize;
  }

  @Override
  public void addBulkLinks(String dbid, List<Link> links, boolean noinverse)
    throws Exception {
    try {
      addBulkLinksImpl(dbid, links, noinverse);
    } catch (Exception ex) {
      logger.error("addBulkLinks failed! " + ex);
      throw ex;
    }
  }

  private void addBulkLinksImpl(String dbid, List<Link> links,
    boolean noinverse) throws Exception {
    if (Level.TRACE.isGreaterOrEqual(debuglevel)) {
      logger.trace("addBulkLinks: " + links.size() + " links");
    }
    addLinksNoCount(dbid, links);
  }

  @Override
  public void addBulkCounts(String dbid, List<LinkCount> counts)
    throws Exception {
    try {
      addBulkCountsImpl(dbid, counts);
    } catch (Exception ex) {
      logger.error("addbulkCounts failed! " + ex);
      throw ex;
    }
  }

  private void addBulkCountsImpl(String dbid, List<LinkCount> counts)
    throws Exception {
    if (Level.TRACE.isGreaterOrEqual(debuglevel)) {
      logger.trace("addBulkCounts: " + counts.size() + " link counts");
    }
    if (counts.size() == 0)
      return;

    dbid += "assocs";
    for (LinkCount count: counts) {
      getRocksClient().TaoAssocCountPut(
        dbid.getBytes(), count.link_type, count.id1, count.count, null, writeOptions);
    }
  }

  @Override
  public void resetNodeStore(String dbid, long startID) throws Exception {
    //doesn't have a defined utility for Rocksdb
  }

  @Override
  public long addNode(String dbid, Node node) throws Exception {
    try {
      return addNodeImpl(dbid, node);
    } catch (Exception ex) {
      logger.error("addNode failed! " + ex);
      throw ex;
    }
  }

  private long addNodeImpl(String dbid, Node node) throws Exception {
    long ids[] = bulkAddNodes(dbid, Collections.singletonList(node));
    assert(ids.length == 1);
    return ids[0];
  }

  @Override
  public long[] bulkAddNodes(String dbid, List<Node> nodes) throws Exception {
    try {
      return bulkAddNodesImpl(dbid, nodes);
    } catch (Exception ex) {
      logger.error("bulkAddNodes failed! " + ex);
      throw ex;
    }
  }

  private long[] bulkAddNodesImpl(String dbid, List<Node> nodes)
    throws Exception {
    long newIds[] = new long[nodes.size()];
    int i = 0;
    for (Node n : nodes) {
      getRocksClient().TaoFBObjectPut(
        n.id, n.type, (int) n.version, (int) n.version,
        (long) n.time, n.data, true, null, writeOptions);
      newIds[i++] = n.id;
    }
    return newIds;
  }

  @Override
  public Node getNode(String dbid, int type, long id) throws Exception {
    try {
      return getNodeImpl(dbid, type, id);
    } catch (Exception ex) {
      logger.error("getnode failed! " + ex);
      throw ex;
    }
  }

  private Node getNodeImpl(String dbid, int type, long id) throws Exception {
    ReadOptions ropts = new ReadOptions();
    ropts.setVerifyChecksums(true);
    ropts.setFillCache(true);

    TaoFBObjectGetResult rgr = getRocksClient().TaoFBObjectGet(id, type);
    if (!rgr.isFound()) {
      return null; //Node was not found
    } else {
      return new Node(
        id, type, rgr.getVersion(), (int) rgr.getUpdateTime(), rgr.getData());
    }
  }

  @Override
  public boolean updateNode(String dbid, Node node) throws Exception {
    try {
      return updateNodeImpl(dbid, node);
    } catch (Exception ex) {
      logger.error("updateNode failed! " + ex);
      throw ex;
    }
  }

  private boolean updateNodeImpl(String dbid, Node node) throws Exception {
    return addNode(dbid, node) == 1;
  }

  @Override
  public boolean deleteNode(String dbid, int type, long id) throws Exception {
    try {
      return deleteNodeImpl(dbid, type, id);
    } catch (Exception ex) {
      logger.error("deleteNode failed! " + ex);
      throw ex;
    }
  }

  private boolean deleteNodeImpl(String dbid, int type, long id)
    throws Exception {
    getRocksClient().
      TaoFBObjectDel(id, type, null, writeOptions);
    return true;
  }
}
TOP

Related Classes of com.facebook.LinkBench.LinkStoreRocksDb

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.