{"action":"created","comment":{"url":"https://api.github.com/repos/amplab/tachyon/pulls/comments/33797296","id":33797296,"diff_hunk":"@@ -15,351 +15,56 @@\n \n package tachyon.worker;\n \n-import java.io.IOException;\n-import java.net.InetSocketAddress;\n-import java.net.UnknownHostException;\n-import java.util.concurrent.ExecutorService;\n-import java.util.concurrent.Executors;\n-\n-import org.apache.thrift.protocol.TBinaryProtocol;\n-import org.apache.thrift.server.TServer;\n-import org.apache.thrift.server.TThreadPoolServer;\n-import org.apache.thrift.transport.TFramedTransport;\n-import org.apache.thrift.transport.TServerSocket;\n-import org.apache.thrift.transport.TTransportException;\n import org.slf4j.Logger;\n import org.slf4j.LoggerFactory;\n \n-import com.google.common.base.Throwables;\n-\n import tachyon.Constants;\n-import tachyon.Users;\n-import tachyon.Version;\n import tachyon.conf.TachyonConf;\n-import tachyon.metrics.MetricsSystem;\n-import tachyon.thrift.Command;\n-import tachyon.thrift.NetAddress;\n-import tachyon.thrift.WorkerService;\n-import tachyon.underfs.UnderFileSystem;\n-import tachyon.util.CommonUtils;\n-import tachyon.util.NetworkUtils;\n-import tachyon.util.ThreadFactoryUtils;\n-import tachyon.web.UIWebServer;\n-import tachyon.web.WorkerUIWebServer;\n+import tachyon.worker.block.BlockWorker;\n \n /**\n- * Entry point for a worker daemon.\n+ * Entry point for the Tachyon Worker. This class is responsible for initializing the different\n+ * workers that are configured to run.\n  */\n-public class TachyonWorker implements Runnable {\n+public class TachyonWorker {\n   private static final Logger LOG = LoggerFactory.getLogger(Constants.LOGGER_TYPE);\n \n   /**\n-   * Create a new TachyonWorker based on the given TachyonConfig.\n+   * Main method for Tachyon Worker. A Block Worker will be started and the Tachyon Worker will\n+   * continue to run until the Block Worker thread exits.\n    *\n-   * @param tachyonConf The instance of {@link tachyon.conf.TachyonConf} to be used by Worker\n-   * @return The new TachyonWorker\n+   * @param args command line arguments, should be empty\n    */\n-  public static synchronized TachyonWorker createWorker(TachyonConf tachyonConf) {\n-    String masterHostname =\n-        tachyonConf.get(Constants.MASTER_HOSTNAME, NetworkUtils.getLocalHostName(tachyonConf));\n-    int masterPort = tachyonConf.getInt(Constants.MASTER_PORT, Constants.DEFAULT_MASTER_PORT);\n-    String workerHostName = NetworkUtils.getLocalHostName(tachyonConf);\n-    int workerPort = tachyonConf.getInt(Constants.WORKER_PORT, Constants.DEFAULT_WORKER_PORT);\n-    int dataPort =\n-        tachyonConf.getInt(Constants.WORKER_DATA_PORT, Constants.DEFAULT_WORKER_DATA_SERVER_PORT);\n-    int minWorkerThreads =\n-        tachyonConf.getInt(Constants.WORKER_MIN_WORKER_THREADS, Runtime.getRuntime()\n-            .availableProcessors());\n-    int maxWorkerThreads =\n-        tachyonConf.getInt(Constants.WORKER_MAX_WORKER_THREADS,\n-            Constants.DEFAULT_WORKER_MAX_WORKER_THREADS);\n-\n-    return new TachyonWorker(new InetSocketAddress(masterHostname, masterPort),\n-        new InetSocketAddress(workerHostName, workerPort), dataPort, minWorkerThreads,\n-        maxWorkerThreads, tachyonConf);\n-  }\n-\n-  private static void setMasterAddress(String masterAddress, TachyonConf conf) {\n-    if (masterAddress == null) {\n-      return;\n-    }\n-    String masterHostnameConf =\n-        conf.get(Constants.MASTER_HOSTNAME, NetworkUtils.getLocalHostName(conf));\n-    String masterPortConf = conf.get(Constants.MASTER_PORT, Constants.DEFAULT_MASTER_PORT + \"\");\n-    String[] address = masterAddress.split(\":\");\n-    String masterHostname = address[0];\n-    if (!masterHostnameConf.equals(masterHostname)) {\n-      LOG.warn(\"Master host in configuration ({}) is different from the command line ({}).\",\n-          masterHostnameConf, masterHostname);\n-      conf.set(Constants.MASTER_HOSTNAME, masterHostname);\n-    }\n-    String masterPort = masterPortConf;\n-    if (address.length > 1) {\n-      masterPort = address[1];\n-      if (!masterPortConf.equals(masterPort)) {\n-        LOG.warn(\"Master port in configuration ({}) is different from the command line ({}).\",\n-            masterPortConf, masterPort);\n-        conf.set(Constants.MASTER_PORT, masterPort);\n-      }\n-    }\n-    return;\n-  }\n-\n-  public static void main(String[] args) throws UnknownHostException {\n-    if (args.length > 1) {\n-      LOG.info(\"Usage: java -cp target/tachyon-\" + Version.VERSION + \"-jar-with-dependencies.jar \"\n-          + \"tachyon.Worker [<MasterHost:Port>]\");\n-      System.exit(-1);\n-    }\n-\n+  public static void main(String[] args) {\n+    checkArgs(args);\n     TachyonConf tachyonConf = new TachyonConf();\n-    if (args.length == 1) {\n-      setMasterAddress(args[0], tachyonConf);\n-    }\n-\n-    String resolvedWorkerHost = NetworkUtils.getLocalHostName(tachyonConf);\n-    LOG.info(\"Resolved local TachyonWorker host to \" + resolvedWorkerHost);\n-\n+    BlockWorker worker = null;\n     try {\n-      TachyonWorker worker = TachyonWorker.createWorker(tachyonConf);\n-      worker.start();\n+      worker = new BlockWorker(tachyonConf);\n+      worker.process();\n     } catch (Exception e) {\n-      LOG.error(\"Uncaught exception terminating worker\", e);\n-      System.exit(-1);\n-    }\n-  }\n-\n-  private final InetSocketAddress mMasterAddress;\n-  private final NetAddress mWorkerAddress;\n-  private final UIWebServer mWebServer;\n-  private final int mWebPort;\n-  private TServer mServer;\n-\n-  private TServerSocket mServerTServerSocket;\n-  private final WorkerStorage mWorkerStorage;\n-\n-  private final WorkerServiceHandler mWorkerServiceHandler;\n-\n-  private final MetricsSystem mWorkerMetricsSystem;\n-\n-  private final DataServer mDataServer;\n-\n-  private final Thread mHeartbeatThread;\n-\n-  private volatile boolean mStop = false;\n-\n-  private final int mPort;\n-  private final int mDataPort;\n-  private final ExecutorService mExecutorService = Executors.newFixedThreadPool(1,\n-      ThreadFactoryUtils.build(\"heartbeat-worker-%d\", true));\n-  private final TachyonConf mTachyonConf;\n-\n-  /**\n-   * @param masterAddress The TachyonMaster's address.\n-   * @param workerAddress This TachyonWorker's address.\n-   * @param dataPort This TachyonWorker's data server's port\n-   * @param minWorkerThreads The min number of worker threads used in TThreadPoolServer\n-   * @param maxWorkerThreads The max number of worker threads used in TThreadPoolServer\n-   * @param tachyonConf The {@link TachyonConf} instance for configuration properties\n-   */\n-  private TachyonWorker(InetSocketAddress masterAddress, InetSocketAddress workerAddress,\n-      int dataPort, int minWorkerThreads, int maxWorkerThreads, TachyonConf tachyonConf) {\n-    TachyonConf.assertValidPort(masterAddress, tachyonConf);\n-    TachyonConf.assertValidPort(workerAddress, tachyonConf);\n-    TachyonConf.assertValidPort(dataPort, tachyonConf);\n-\n-    mTachyonConf = tachyonConf;\n-\n-    mMasterAddress = masterAddress;\n-\n-    mWorkerStorage = new WorkerStorage(mMasterAddress, mExecutorService, mTachyonConf);\n-\n-    mWorkerServiceHandler = new WorkerServiceHandler(mWorkerStorage);\n-\n-    mWebPort = mTachyonConf.getInt(Constants.WORKER_WEB_PORT, Constants.DEFAULT_WORKER_WEB_PORT);\n-\n-    // Extract the port from the generated socket.\n-    // When running tests, its great to use port '0' so the system will figure out what port to use\n-    // (any random free port).\n-    // In a production or any real deployment setup, port '0' should not be used as it will make\n-    // deployment more complicated.\n-    InetSocketAddress dataAddress = new InetSocketAddress(workerAddress.getHostName(), dataPort);\n-    BlocksLocker blockLocker = new BlocksLocker(mWorkerStorage, Users.DATASERVER_USER_ID);\n-    mDataServer = DataServer.Factory.createDataServer(dataAddress, blockLocker, mTachyonConf);\n-    mDataPort = mDataServer.getPort();\n-\n-    mHeartbeatThread = new Thread(this);\n-    try {\n-      LOG.info(\"Tachyon Worker version \" + Version.VERSION + \" tries to start @ \" + workerAddress);\n-      WorkerService.Processor<WorkerServiceHandler> processor =\n-          new WorkerService.Processor<WorkerServiceHandler>(mWorkerServiceHandler);\n-\n-      mServerTServerSocket = new TServerSocket(workerAddress);\n-      mPort = NetworkUtils.getPort(mServerTServerSocket);\n-\n-      mServer =\n-          new TThreadPoolServer(new TThreadPoolServer.Args(mServerTServerSocket)\n-              .minWorkerThreads(minWorkerThreads).maxWorkerThreads(maxWorkerThreads)\n-              .processor(processor).transportFactory(new TFramedTransport.Factory())\n-              .protocolFactory(new TBinaryProtocol.Factory(true, true)));\n-    } catch (TTransportException e) {\n-      LOG.error(e.getMessage(), e);\n-      throw Throwables.propagate(e);\n-    }\n-    mWorkerAddress =\n-        new NetAddress(workerAddress.getAddress().getCanonicalHostName(), mPort, mDataPort);\n-\n-    // Connect to UFS before initializing the workerStorage.\n-    try {\n-      connectToUFS();\n-    } catch (IOException ioe) {\n-      LOG.error(\"Worker @ \" + workerAddress + \" failed to connect to the under file system\", ioe);\n-      throw Throwables.propagate(ioe);\n-    }\n-\n-    mWorkerStorage.initialize(mWorkerAddress);\n-\n-    mWebServer =\n-        new WorkerUIWebServer(\"Tachyon Worker\", new InetSocketAddress(workerAddress.getHostName(),\n-            mWebPort), mWorkerStorage, mTachyonConf);\n-\n-    mWorkerMetricsSystem = new MetricsSystem(\"worker\", mTachyonConf);\n-    mWorkerMetricsSystem.registerSource(mWorkerStorage.getWorkerSource());\n-  }\n-\n-  /**\n-   * Gets the data port of the worker. For unit tests only.\n-   */\n-  public int getDataPort() {\n-    return mDataPort;\n-  }\n-\n-  /**\n-   * Gets the metadata port of the worker. For unit tests only.\n-   */\n-  public int getMetaPort() {\n-    return mPort;\n-  }\n-\n-  /**\n-   * Gets the underlying {@link tachyon.conf.TachyonConf} instance for the Worker.\n-   */\n-  public TachyonConf getTachyonConf() {\n-    return mTachyonConf;\n-  }\n-\n-  /**\n-   * Get the worker server handler class. This is for unit test only.\n-   *\n-   * @return the WorkerServiceHandler\n-   */\n-  WorkerServiceHandler getWorkerServiceHandler() {\n-    return mWorkerServiceHandler;\n-  }\n-\n-  private void connectToUFS() throws IOException {\n-    String tachyonHome = mTachyonConf.get(Constants.TACHYON_HOME, Constants.DEFAULT_HOME);\n-    String ufsAddress =\n-        mTachyonConf.get(Constants.UNDERFS_ADDRESS, tachyonHome + \"/underFSStorage\");\n-    UnderFileSystem ufs = UnderFileSystem.get(ufsAddress, mTachyonConf);\n-    ufs.connectFromWorker(mTachyonConf, NetworkUtils.getFqdnHost(mWorkerAddress));\n-  }\n-\n-  @Override\n-  public void run() {\n-    long lastHeartbeatMs = System.currentTimeMillis();\n-    Command cmd = null;\n-    while (!mStop) {\n-      long diff = System.currentTimeMillis() - lastHeartbeatMs;\n-      int hbIntervalMs =\n-          mTachyonConf.getInt(Constants.WORKER_TO_MASTER_HEARTBEAT_INTERVAL_MS,\n-              Constants.SECOND_MS);\n-      if (diff < hbIntervalMs) {\n-        LOG.debug(\"Heartbeat process takes {} ms.\", diff);\n-        CommonUtils.sleepMs(LOG, hbIntervalMs - diff);\n-      } else {\n-        LOG.error(\"Heartbeat process takes \" + diff + \" ms.\");\n-      }\n-\n+      LOG.error(\"Uncaught exception, shutting down workers and then exiting.\", e);\n       try {\n-        cmd = mWorkerStorage.heartbeat();\n-\n-        lastHeartbeatMs = System.currentTimeMillis();\n-      } catch (IOException e) {\n-        LOG.error(e.getMessage(), e);\n-        mWorkerStorage.resetMasterClient();\n-        CommonUtils.sleepMs(LOG, Constants.SECOND_MS);\n-        cmd = null;\n-        int heartbeatTimeout =\n-            mTachyonConf.getInt(Constants.WORKER_HEARTBEAT_TIMEOUT_MS, 10 * Constants.SECOND_MS);\n-        if (System.currentTimeMillis() - lastHeartbeatMs >= heartbeatTimeout) {\n-          throw new RuntimeException(\"Heartbeat timeout \"\n-              + (System.currentTimeMillis() - lastHeartbeatMs) + \"ms\");\n-        }\n-      }\n-\n-      if (cmd != null) {\n-        switch (cmd.mCommandType) {\n-          case Unknown:\n-            LOG.error(\"Unknown command: \" + cmd);\n-            break;\n-          case Nothing:\n-            LOG.debug(\"Nothing command: {}\", cmd);\n-            break;\n-          case Register:\n-            LOG.info(\"Register command: \" + cmd);\n-            mWorkerStorage.register();\n-            break;\n-          case Free:\n-            mWorkerStorage.freeBlocks(cmd.mData);\n-            LOG.info(\"Free command: \" + cmd);\n-            break;\n-          case Delete:\n-            LOG.info(\"Delete command: \" + cmd);\n-            break;\n-          default:\n-            throw new RuntimeException(\"Un-recognized command from master \" + cmd.toString());\n+        if (worker != null) {\n+          worker.stop();\n         }\n+      } catch (Exception ex) {\n+        LOG.error(\"Failed to stop block worker. Exiting.\", ex);\n       }\n-\n-      mWorkerStorage.checkStatus();\n+      System.exit(-1);\n     }\n+    System.exit(0);\n   }\n \n   /**\n-   * Start the data server thread and heartbeat thread of this TachyonWorker.\n-   */\n-  public void start() throws IOException {\n-    mHeartbeatThread.start();\n-    mWorkerMetricsSystem.start();\n-    mWebServer.addHandler(mWorkerMetricsSystem.getServletHandler());\n-    mWebServer.startWebServer();\n-\n-    LOG.info(\"The worker server started @ \" + mWorkerAddress);\n-    mServer.serve();\n-    LOG.info(\"The worker server ends @ \" + mWorkerAddress);\n-  }\n-\n-  /**\n-   * Stop this TachyonWorker. Stop all the threads belong to this TachyonWorker.\n+   * Verifies that no parameters are passed in\n    *\n-   * @throws IOException\n-   * @throws InterruptedException\n+   * @param args command line arguments\n    */\n-  public void stop() throws IOException, InterruptedException {\n-    mStop = true;\n-    mWorkerStorage.stop();\n-    mWorkerMetricsSystem.stop();\n-    mDataServer.close();\n-    mServer.stop();\n-    mServerTServerSocket.close();\n-    mExecutorService.shutdown();\n-    while (!mDataServer.isClosed() || mServer.isServing() || mHeartbeatThread.isAlive()) {\n-      // TODO The reason to stop and close again is due to some issues in Thrift.\n-      mServer.stop();\n-      mServerTServerSocket.close();\n-      CommonUtils.sleepMs(null, 100);\n+  private static void checkArgs(String[] args) {\n+    if (args.length != 0) {\n+      LOG.info(\"Usage: java TachyonWorker\");","path":"servers/src/main/java/tachyon/worker/TachyonWorker.java","position":383,"original_position":383,"commit_id":"74e9ca1bce3338c76688b76ba333d1e1a70f7a54","original_commit_id":"74e9ca1bce3338c76688b76ba333d1e1a70f7a54","user":{"login":"apc999","id":1413748,"avatar_url":"https://avatars.githubusercontent.com/u/1413748?v=3","gravatar_id":"","url":"https://api.github.com/users/apc999","html_url":"https://github.com/apc999","followers_url":"https://api.github.com/users/apc999/followers","following_url":"https://api.github.com/users/apc999/following{/other_user}","gists_url":"https://api.github.com/users/apc999/gists{/gist_id}","starred_url":"https://api.github.com/users/apc999/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apc999/subscriptions","organizations_url":"https://api.github.com/users/apc999/orgs","repos_url":"https://api.github.com/users/apc999/repos","events_url":"https://api.github.com/users/apc999/events{/privacy}","received_events_url":"https://api.github.com/users/apc999/received_events","type":"User","site_admin":false},"body":"Isn't it 'LOG.info(\"Usage: java -cp target/tachyon-\" + Version.VERSION + \"-jar-with-dependencies.jar tachyon.Worker\");` ?","created_at":"2015-07-02T16:42:52Z","updated_at":"2015-07-02T16:42:52Z","html_url":"https://github.com/amplab/tachyon/pull/1017#discussion_r33797296","pull_request_url":"https://api.github.com/repos/amplab/tachyon/pulls/1017","_links":{"self":{"href":"https://api.github.com/repos/amplab/tachyon/pulls/comments/33797296"},"html":{"href":"https://github.com/amplab/tachyon/pull/1017#discussion_r33797296"},"pull_request":{"href":"https://api.github.com/repos/amplab/tachyon/pulls/1017"}}},"pull_request":{"url":"https://api.github.com/repos/amplab/tachyon/pulls/1017","id":38702106,"html_url":"https://github.com/amplab/tachyon/pull/1017","diff_url":"https://github.com/amplab/tachyon/pull/1017.diff","patch_url":"https://github.com/amplab/tachyon/pull/1017.patch","issue_url":"https://api.github.com/repos/amplab/tachyon/issues/1017","number":1017,"state":"open","locked":false,"title":"[WIP] [TACHYON-515] Tachyon Worker Improvement","user":{"login":"calvinjia","id":2223813,"avatar_url":"https://avatars.githubusercontent.com/u/2223813?v=3","gravatar_id":"","url":"https://api.github.com/users/calvinjia","html_url":"https://github.com/calvinjia","followers_url":"https://api.github.com/users/calvinjia/followers","following_url":"https://api.github.com/users/calvinjia/following{/other_user}","gists_url":"https://api.github.com/users/calvinjia/gists{/gist_id}","starred_url":"https://api.github.com/users/calvinjia/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/calvinjia/subscriptions","organizations_url":"https://api.github.com/users/calvinjia/orgs","repos_url":"https://api.github.com/users/calvinjia/repos","events_url":"https://api.github.com/users/calvinjia/events{/privacy}","received_events_url":"https://api.github.com/users/calvinjia/received_events","type":"User","site_admin":false},"body":"https://tachyon.atlassian.net/browse/TACHYON-515\r\n\r\nThis is a rebased version of the worker_wip branch.","created_at":"2015-06-27T02:02:10Z","updated_at":"2015-07-02T16:42:52Z","closed_at":null,"merged_at":null,"merge_commit_sha":"13b446f5bbdbacf04a524353bd17610f4eff17d3","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/amplab/tachyon/pulls/1017/commits","review_comments_url":"https://api.github.com/repos/amplab/tachyon/pulls/1017/comments","review_comment_url":"https://api.github.com/repos/amplab/tachyon/pulls/comments{/number}","comments_url":"https://api.github.com/repos/amplab/tachyon/issues/1017/comments","statuses_url":"https://api.github.com/repos/amplab/tachyon/statuses/74e9ca1bce3338c76688b76ba333d1e1a70f7a54","head":{"label":"amplab:rebased_worker_wip","ref":"rebased_worker_wip","sha":"74e9ca1bce3338c76688b76ba333d1e1a70f7a54","user":{"login":"amplab","id":1438454,"avatar_url":"https://avatars.githubusercontent.com/u/1438454?v=3","gravatar_id":"","url":"https://api.github.com/users/amplab","html_url":"https://github.com/amplab","followers_url":"https://api.github.com/users/amplab/followers","following_url":"https://api.github.com/users/amplab/following{/other_user}","gists_url":"https://api.github.com/users/amplab/gists{/gist_id}","starred_url":"https://api.github.com/users/amplab/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/amplab/subscriptions","organizations_url":"https://api.github.com/users/amplab/orgs","repos_url":"https://api.github.com/users/amplab/repos","events_url":"https://api.github.com/users/amplab/events{/privacy}","received_events_url":"https://api.github.com/users/amplab/received_events","type":"Organization","site_admin":false},"repo":{"id":7276954,"name":"tachyon","full_name":"amplab/tachyon","owner":{"login":"amplab","id":1438454,"avatar_url":"https://avatars.githubusercontent.com/u/1438454?v=3","gravatar_id":"","url":"https://api.github.com/users/amplab","html_url":"https://github.com/amplab","followers_url":"https://api.github.com/users/amplab/followers","following_url":"https://api.github.com/users/amplab/following{/other_user}","gists_url":"https://api.github.com/users/amplab/gists{/gist_id}","starred_url":"https://api.github.com/users/amplab/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/amplab/subscriptions","organizations_url":"https://api.github.com/users/amplab/orgs","repos_url":"https://api.github.com/users/amplab/repos","events_url":"https://api.github.com/users/amplab/events{/privacy}","received_events_url":"https://api.github.com/users/amplab/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/amplab/tachyon","description":" A Reliable Memory Centric Distributed Storage System","fork":false,"url":"https://api.github.com/repos/amplab/tachyon","forks_url":"https://api.github.com/repos/amplab/tachyon/forks","keys_url":"https://api.github.com/repos/amplab/tachyon/keys{/key_id}","collaborators_url":"https://api.github.com/repos/amplab/tachyon/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/amplab/tachyon/teams","hooks_url":"https://api.github.com/repos/amplab/tachyon/hooks","issue_events_url":"https://api.github.com/repos/amplab/tachyon/issues/events{/number}","events_url":"https://api.github.com/repos/amplab/tachyon/events","assignees_url":"https://api.github.com/repos/amplab/tachyon/assignees{/user}","branches_url":"https://api.github.com/repos/amplab/tachyon/branches{/branch}","tags_url":"https://api.github.com/repos/amplab/tachyon/tags","blobs_url":"https://api.github.com/repos/amplab/tachyon/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/amplab/tachyon/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/amplab/tachyon/git/refs{/sha}","trees_url":"https://api.github.com/repos/amplab/tachyon/git/trees{/sha}","statuses_url":"https://api.github.com/repos/amplab/tachyon/statuses/{sha}","languages_url":"https://api.github.com/repos/amplab/tachyon/languages","stargazers_url":"https://api.github.com/repos/amplab/tachyon/stargazers","contributors_url":"https://api.github.com/repos/amplab/tachyon/contributors","subscribers_url":"https://api.github.com/repos/amplab/tachyon/subscribers","subscription_url":"https://api.github.com/repos/amplab/tachyon/subscription","commits_url":"https://api.github.com/repos/amplab/tachyon/commits{/sha}","git_commits_url":"https://api.github.com/repos/amplab/tachyon/git/commits{/sha}","comments_url":"https://api.github.com/repos/amplab/tachyon/comments{/number}","issue_comment_url":"https://api.github.com/repos/amplab/tachyon/issues/comments{/number}","contents_url":"https://api.github.com/repos/amplab/tachyon/contents/{+path}","compare_url":"https://api.github.com/repos/amplab/tachyon/compare/{base}...{head}","merges_url":"https://api.github.com/repos/amplab/tachyon/merges","archive_url":"https://api.github.com/repos/amplab/tachyon/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/amplab/tachyon/downloads","issues_url":"https://api.github.com/repos/amplab/tachyon/issues{/number}","pulls_url":"https://api.github.com/repos/amplab/tachyon/pulls{/number}","milestones_url":"https://api.github.com/repos/amplab/tachyon/milestones{/number}","notifications_url":"https://api.github.com/repos/amplab/tachyon/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/amplab/tachyon/labels{/name}","releases_url":"https://api.github.com/repos/amplab/tachyon/releases{/id}","created_at":"2012-12-21T17:43:46Z","updated_at":"2015-07-02T05:42:16Z","pushed_at":"2015-07-02T15:47:17Z","git_url":"git://github.com/amplab/tachyon.git","ssh_url":"git@github.com:amplab/tachyon.git","clone_url":"https://github.com/amplab/tachyon.git","svn_url":"https://github.com/amplab/tachyon","homepage":"http://tachyon-project.org","size":34278,"stargazers_count":1461,"watchers_count":1461,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":539,"mirror_url":null,"open_issues_count":21,"forks":539,"open_issues":21,"watchers":1461,"default_branch":"master"}},"base":{"label":"amplab:master","ref":"master","sha":"d6054a7be4506610280514f9c4192849f63e0d8d","user":{"login":"amplab","id":1438454,"avatar_url":"https://avatars.githubusercontent.com/u/1438454?v=3","gravatar_id":"","url":"https://api.github.com/users/amplab","html_url":"https://github.com/amplab","followers_url":"https://api.github.com/users/amplab/followers","following_url":"https://api.github.com/users/amplab/following{/other_user}","gists_url":"https://api.github.com/users/amplab/gists{/gist_id}","starred_url":"https://api.github.com/users/amplab/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/amplab/subscriptions","organizations_url":"https://api.github.com/users/amplab/orgs","repos_url":"https://api.github.com/users/amplab/repos","events_url":"https://api.github.com/users/amplab/events{/privacy}","received_events_url":"https://api.github.com/users/amplab/received_events","type":"Organization","site_admin":false},"repo":{"id":7276954,"name":"tachyon","full_name":"amplab/tachyon","owner":{"login":"amplab","id":1438454,"avatar_url":"https://avatars.githubusercontent.com/u/1438454?v=3","gravatar_id":"","url":"https://api.github.com/users/amplab","html_url":"https://github.com/amplab","followers_url":"https://api.github.com/users/amplab/followers","following_url":"https://api.github.com/users/amplab/following{/other_user}","gists_url":"https://api.github.com/users/amplab/gists{/gist_id}","starred_url":"https://api.github.com/users/amplab/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/amplab/subscriptions","organizations_url":"https://api.github.com/users/amplab/orgs","repos_url":"https://api.github.com/users/amplab/repos","events_url":"https://api.github.com/users/amplab/events{/privacy}","received_events_url":"https://api.github.com/users/amplab/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/amplab/tachyon","description":" A Reliable Memory Centric Distributed Storage System","fork":false,"url":"https://api.github.com/repos/amplab/tachyon","forks_url":"https://api.github.com/repos/amplab/tachyon/forks","keys_url":"https://api.github.com/repos/amplab/tachyon/keys{/key_id}","collaborators_url":"https://api.github.com/repos/amplab/tachyon/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/amplab/tachyon/teams","hooks_url":"https://api.github.com/repos/amplab/tachyon/hooks","issue_events_url":"https://api.github.com/repos/amplab/tachyon/issues/events{/number}","events_url":"https://api.github.com/repos/amplab/tachyon/events","assignees_url":"https://api.github.com/repos/amplab/tachyon/assignees{/user}","branches_url":"https://api.github.com/repos/amplab/tachyon/branches{/branch}","tags_url":"https://api.github.com/repos/amplab/tachyon/tags","blobs_url":"https://api.github.com/repos/amplab/tachyon/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/amplab/tachyon/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/amplab/tachyon/git/refs{/sha}","trees_url":"https://api.github.com/repos/amplab/tachyon/git/trees{/sha}","statuses_url":"https://api.github.com/repos/amplab/tachyon/statuses/{sha}","languages_url":"https://api.github.com/repos/amplab/tachyon/languages","stargazers_url":"https://api.github.com/repos/amplab/tachyon/stargazers","contributors_url":"https://api.github.com/repos/amplab/tachyon/contributors","subscribers_url":"https://api.github.com/repos/amplab/tachyon/subscribers","subscription_url":"https://api.github.com/repos/amplab/tachyon/subscription","commits_url":"https://api.github.com/repos/amplab/tachyon/commits{/sha}","git_commits_url":"https://api.github.com/repos/amplab/tachyon/git/commits{/sha}","comments_url":"https://api.github.com/repos/amplab/tachyon/comments{/number}","issue_comment_url":"https://api.github.com/repos/amplab/tachyon/issues/comments{/number}","contents_url":"https://api.github.com/repos/amplab/tachyon/contents/{+path}","compare_url":"https://api.github.com/repos/amplab/tachyon/compare/{base}...{head}","merges_url":"https://api.github.com/repos/amplab/tachyon/merges","archive_url":"https://api.github.com/repos/amplab/tachyon/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/amplab/tachyon/downloads","issues_url":"https://api.github.com/repos/amplab/tachyon/issues{/number}","pulls_url":"https://api.github.com/repos/amplab/tachyon/pulls{/number}","milestones_url":"https://api.github.com/repos/amplab/tachyon/milestones{/number}","notifications_url":"https://api.github.com/repos/amplab/tachyon/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/amplab/tachyon/labels{/name}","releases_url":"https://api.github.com/repos/amplab/tachyon/releases{/id}","created_at":"2012-12-21T17:43:46Z","updated_at":"2015-07-02T05:42:16Z","pushed_at":"2015-07-02T15:47:17Z","git_url":"git://github.com/amplab/tachyon.git","ssh_url":"git@github.com:amplab/tachyon.git","clone_url":"https://github.com/amplab/tachyon.git","svn_url":"https://github.com/amplab/tachyon","homepage":"http://tachyon-project.org","size":34278,"stargazers_count":1461,"watchers_count":1461,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":539,"mirror_url":null,"open_issues_count":21,"forks":539,"open_issues":21,"watchers":1461,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/amplab/tachyon/pulls/1017"},"html":{"href":"https://github.com/amplab/tachyon/pull/1017"},"issue":{"href":"https://api.github.com/repos/amplab/tachyon/issues/1017"},"comments":{"href":"https://api.github.com/repos/amplab/tachyon/issues/1017/comments"},"review_comments":{"href":"https://api.github.com/repos/amplab/tachyon/pulls/1017/comments"},"review_comment":{"href":"https://api.github.com/repos/amplab/tachyon/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/amplab/tachyon/pulls/1017/commits"},"statuses":{"href":"https://api.github.com/repos/amplab/tachyon/statuses/74e9ca1bce3338c76688b76ba333d1e1a70f7a54"}}}}