{"action":"created","comment":{"url":"https://api.github.com/repos/amplab/tachyon/pulls/comments/46814741","id":46814741,"diff_hunk":"@@ -0,0 +1,577 @@\n+/*\n+ * Licensed to the University of California, Berkeley under one or more contributor license\n+ * agreements. See the NOTICE file distributed with this work for additional information regarding\n+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the\n+ * \"License\"); you may not use this file except in compliance with the License. You may obtain a\n+ * copy of the License at\n+ *\n+ * http://www.apache.org/licenses/LICENSE-2.0\n+ *\n+ * Unless required by applicable law or agreed to in writing, software distributed under the License\n+ * is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express\n+ * or implied. See the License for the specific language governing permissions and limitations under\n+ * the License.\n+ */\n+\n+package tachyon.fuse;\n+\n+import java.io.IOException;\n+import java.nio.file.Path;\n+import java.nio.file.Paths;\n+import java.util.HashMap;\n+import java.util.List;\n+import java.util.Map;\n+\n+import org.slf4j.Logger;\n+import org.slf4j.LoggerFactory;\n+import com.google.common.base.Preconditions;\n+import com.google.common.cache.CacheBuilder;\n+import com.google.common.cache.CacheLoader;\n+import com.google.common.cache.LoadingCache;\n+\n+import tachyon.Constants;\n+import tachyon.TachyonURI;\n+import tachyon.client.file.TachyonFile;\n+import tachyon.client.file.TachyonFileSystem;\n+import tachyon.exception.FileAlreadyExistsException;\n+import tachyon.exception.FileDoesNotExistException;\n+import tachyon.exception.InvalidPathException;\n+import tachyon.exception.TachyonException;\n+import tachyon.thrift.FileInfo;\n+\n+import jnr.ffi.Pointer;\n+import jnr.ffi.types.mode_t;\n+import jnr.ffi.types.off_t;\n+import jnr.ffi.types.size_t;\n+import ru.serce.jnrfuse.ErrorCodes;\n+import ru.serce.jnrfuse.FuseFillDir;\n+import ru.serce.jnrfuse.FuseStubFS;\n+import ru.serce.jnrfuse.struct.FileStat;\n+import ru.serce.jnrfuse.struct.FuseFileInfo;\n+\n+import static jnr.constants.platform.OpenFlags.O_RDONLY;\n+import static jnr.constants.platform.OpenFlags.O_WRONLY;\n+\n+/**\n+ * Main FUSE implementation class.\n+ *\n+ * Implements the FUSE callbacks defined by jnr-fuse\n+ */\n+public final class TachyonFuseFs extends FuseStubFS {\n+  private static final Logger LOG = LoggerFactory.getLogger(Constants.LOGGER_TYPE);\n+  private static final int MAX_OPEN_FILES = Integer.MAX_VALUE;\n+  // Limits the number of translated (FUSE to TachyonURI)  paths that are kept\n+  // in memory\n+  private static final int MAX_CACHED_PATHS = 500;\n+  private static final long[] UID_AND_GID = TachyonFuseUtils.getUidAndGid();\n+\n+  private final TachyonFileSystem mTFS;\n+  private final Path mMountPoint;\n+  private final Path mTachyonRootPath;\n+  private final String mTachyonMaster;\n+  // Keeps a cache of the most recently translated paths from String to TachyonURI\n+  private final LoadingCache<String, TachyonURI> mPathResolverCache;\n+\n+  private final Object mOpenFilesLock;\n+  // Table of open files with corresponding InputStreams and OutptuStreams\n+  private final Map<Long, OpenFileEntry> mOpenFiles;\n+  private long mOpenFileIds;\n+\n+  public TachyonFuseFs(TachyonFuseOptions opts) {\n+    super();\n+    mTFS = TachyonFileSystem.TachyonFileSystemFactory.get();\n+    mMountPoint = Paths.get(opts.getMountPoint());\n+    mTachyonMaster = opts.getMasterAddress();\n+    mTachyonRootPath = Paths.get(opts.getTachyonRoot());\n+    mOpenFileIds = 0L;\n+    mOpenFiles = new HashMap<Long, OpenFileEntry>();\n+    mOpenFilesLock = new Object();\n+\n+    mPathResolverCache = CacheBuilder.newBuilder()\n+        .maximumSize(MAX_CACHED_PATHS)\n+        .build(new PathCacheLoader());\n+\n+    Preconditions.checkArgument(mMountPoint.isAbsolute(),\n+        \"mount point should be an absolute path\");\n+    Preconditions.checkArgument(mTachyonRootPath.isAbsolute(),\n+        \"tachyon root path should be absolute\");\n+  }\n+\n+  @Override\n+  public int create(String path, @mode_t long mode, FuseFileInfo fi) {\n+    int ret = 0;\n+    final TachyonURI turi = mPathResolverCache.getUnchecked(path);\n+    final int flags = fi.flags.get();\n+    LOG.trace(\"create({}, {}) [Tachyon: {}]\", path, Integer.toHexString(flags), turi);\n+    LOG.warn(\"{}: mode is ignored in tachyon-fuse\", path);\n+    if ((flags & 3) != O_WRONLY.intValue()) {\n+      LOG.error(\"Files can only be created in O_WRONLY mode ({})\", path);\n+      return -ErrorCodes.EACCES();\n+    }\n+\n+    try {\n+\n+      final OpenFileEntry ofe = new OpenFileEntry();\n+      ofe.mIn = null;\n+      ofe.mOut = mTFS.getOutStream(turi);\n+      LOG.debug(\"Tachyon OutStream created for {}\", path);\n+\n+      synchronized (mOpenFilesLock) {\n+        if (mOpenFiles.size() == MAX_OPEN_FILES) {\n+          LOG.error(\"Cannot open {}: too many open files\", turi);\n+          return ErrorCodes.EMFILE();\n+        }\n+        mOpenFiles.put(mOpenFileIds, ofe);\n+        fi.fh.set(mOpenFileIds);\n+\n+        // Assuming I will never wrap around (2^64 open files are quite a lot anyway)\n+        mOpenFileIds += 1;\n+      }\n+      LOG.debug(\"{} created and opened in O_WRONLY mode\", path);\n+\n+    } catch (FileAlreadyExistsException e) {\n+      LOG.debug(\"File {} already exists\", turi, e);\n+      ret = ErrorCodes.EEXIST();\n+    } catch (IOException e) {\n+      LOG.error(\"IOException on {}\", path, e);\n+      ret = ErrorCodes.EFAULT();\n+    } catch (TachyonException e) {\n+      LOG.error(\"TachyonException on {}\", path, e);\n+      ret = ErrorCodes.EFAULT();\n+    } catch (Throwable e) {\n+      LOG.error(\"Unexpected exception on {}\", path, e);\n+      ret = ErrorCodes.EFAULT();\n+    }\n+\n+    return -ret;\n+  }\n+\n+  @Override\n+  public int flush(String path, FuseFileInfo fi) {\n+    LOG.trace(\"flush({})\", path);\n+    final long fd = fi.fh.get();\n+    OpenFileEntry oe = null;\n+    synchronized (mOpenFilesLock) {\n+      oe = mOpenFiles.get(fd);\n+    }\n+    if (oe == null) {\n+      LOG.error(\"Cannot find fd for {} in table\", path);\n+      return -ErrorCodes.EBADFD();\n+    }\n+    if (oe.mOut == null) {\n+      LOG.error(\"{} was not open for writing\", path);\n+      return -ErrorCodes.EBADFD();\n+    }\n+    try {\n+      oe.mOut.flush();\n+    } catch (IOException e) {\n+      return -ErrorCodes.EIO();\n+    }\n+\n+    return 0;\n+  }\n+\n+  @Override\n+  public int getattr(String path, FileStat stat) {\n+    int ret = 0;\n+    final TachyonURI turi = mPathResolverCache.getUnchecked(path);\n+    LOG.trace(\"getattr({}) [Tachyon: {}]\", path, turi);\n+    try {\n+      final TachyonFile tf = mTFS.openIfExists(turi);\n+      if (tf == null) {\n+        ret = ErrorCodes.ENOENT();\n+      } else {\n+        final FileInfo fi = mTFS.getInfo(tf);\n+        stat.st_size.set(fi.getLength());\n+\n+        final long ctime = fi.getLastModificationTimeMs();\n+        final long ctime_sec = fi.getLastModificationTimeMs() / 1000;\n+        final long ctime_nsec = (fi.getLastModificationTimeMs() % 1000) * 1000;\n+        stat.st_ctim.tv_sec.set(ctime_sec);\n+        stat.st_ctim.tv_nsec.set(ctime_nsec);\n+        stat.st_mtim.tv_sec.set(ctime_sec);\n+        stat.st_mtim.tv_nsec.set(ctime_nsec);\n+\n+        System.getProperty(\"user.name\");\n+\n+        stat.st_uid.set(UID_AND_GID[0]);\n+        stat.st_gid.set(UID_AND_GID[1]);\n+\n+        final int mode;\n+        if (fi.isFolder) {\n+          mode = FileStat.S_IFDIR;\n+        } else {\n+          mode = FileStat.S_IFREG;\n+        }\n+        stat.st_mode.set(mode);\n+      }\n+\n+    } catch (InvalidPathException e) {\n+      LOG.debug(\"Invalid path {}\", path, e);\n+      ret = ErrorCodes.ENOENT();\n+    } catch (FileDoesNotExistException e) {\n+      LOG.debug(\"File does not exist {}\", path, e);\n+      ret = ErrorCodes.ENOENT();\n+    } catch (IOException e) {\n+      LOG.error(\"IOException on {}\", path, e);\n+      ret = ErrorCodes.EFAULT();\n+    } catch (TachyonException e) {\n+      LOG.error(\"TachyonException on {}\", path, e);\n+      ret = ErrorCodes.EFAULT();\n+    } catch (Throwable e) {\n+      LOG.error(\"Unexpected exception on {}\", path, e);\n+      ret = ErrorCodes.EFAULT();\n+    }\n+\n+    return -ret;\n+  }\n+\n+  @Override\n+  public String getFSName() {\n+    return \"tachyon-fuse\";\n+  }\n+\n+  @Override\n+  public int mkdir(String path, @mode_t long mode) {\n+    int ret = 0;\n+    final TachyonURI turi = mPathResolverCache.getUnchecked(path);\n+    LOG.trace(\"mkdir({}) [Tachyon: {}]\", path, turi);\n+    LOG.warn(\"{}: mode is ignored in tachyon-fuse\", path);\n+    try {\n+      mTFS.mkdir(turi);\n+    } catch (FileAlreadyExistsException e) {\n+      LOG.debug(\"Cannot make dir. {} already exists\", path, e);\n+      ret = ErrorCodes.EEXIST();\n+    } catch (InvalidPathException e) {\n+      LOG.debug(\"Cannot make dir. Invalid path: {}\", path, e);\n+      ret = ErrorCodes.ENOENT();\n+    } catch (IOException e) {\n+      LOG.error(\"Cannot make dir. IOException: {}\", path, e);\n+      ret = ErrorCodes.EIO();\n+    } catch (TachyonException e) {\n+      LOG.error(\"Cannot make dir. {}\", path, e);\n+      ret = ErrorCodes.EFAULT();\n+    } catch (Throwable e) {\n+      LOG.error(\"Unexpected exception on {}\", path, e);\n+      ret = ErrorCodes.EFAULT();\n+    }\n+\n+    return -ret;\n+  }\n+\n+  @Override\n+  public int open(String path, FuseFileInfo fi) {\n+    int ret = 0;\n+    final TachyonURI turi = mPathResolverCache.getUnchecked(path);\n+    final int flags = fi.flags.get();\n+    LOG.trace(\"open({}, 0x{}) [Tachyon: {}]\", path, Integer.toHexString(flags), turi);\n+    LOG.warn(\"{}: mode is ignored in tachyon-fuse\", path);\n+\n+    if ((flags & 3) != O_RDONLY.intValue()) {\n+      LOG.error(\"Files can only be opened in O_RDONLY mode ({})\", path);\n+      return -ErrorCodes.EACCES();\n+    }\n+    try {\n+      final TachyonFile tf = mTFS.openIfExists(turi);\n+      if (tf == null) {\n+        LOG.error(\"File {} does not exist\", turi);\n+        return -ErrorCodes.ENOENT();\n+      }\n+      final FileInfo tfi = mTFS.getInfo(tf);\n+      if (tfi.isFolder) {\n+        LOG.error(\"File {} is a directory\", turi);\n+        return -ErrorCodes.ENOENT();\n+      }\n+      final OpenFileEntry ofe = new OpenFileEntry();\n+      ofe.mTfid = tf.getFileId();\n+      ofe.mIn = mTFS.getInStream(tf);\n+      ofe.mOut = null;\n+\n+      synchronized (mOpenFilesLock) {\n+        if (mOpenFiles.size() == MAX_OPEN_FILES) {\n+          LOG.error(\"Cannot open {}: too many open files\", turi);\n+          return ErrorCodes.EMFILE();\n+        }\n+        mOpenFiles.put(mOpenFileIds, ofe);\n+        fi.fh.set(mOpenFileIds);\n+\n+        // Assuming I will never wrap around (2^64 open files are quite a lot anyway)\n+        mOpenFileIds += 1;\n+      }\n+\n+    } catch (FileDoesNotExistException e) {\n+      LOG.debug(\"File does not exist {}\", path, e);\n+      ret = ErrorCodes.ENOENT();\n+    } catch (IOException e) {\n+      LOG.error(\"IOException on {}\", path, e);\n+      ret = ErrorCodes.EIO();\n+    } catch (TachyonException e) {\n+      LOG.error(\"TachyonException on {}\", path, e);\n+      ret = ErrorCodes.EFAULT();\n+    } catch (Throwable e) {\n+      LOG.error(\"Unexpected exception on {}\", path, e);\n+      ret = ErrorCodes.EFAULT();\n+    }\n+\n+    return -ret;\n+  }\n+\n+  @Override\n+  public int read(String path, Pointer buf, @size_t long size, @off_t long offset,\n+                  FuseFileInfo fi) {\n+\n+    if (size > Integer.MAX_VALUE) {\n+      LOG.error(\"Cannot read more than Integer.MAX_VALUE\");\n+      return ErrorCodes.EIO();","path":"fuse/src/main/java/tachyon/fuse/TachyonFuseFs.java","position":null,"original_position":325,"commit_id":"178a7d95feb233fcfac0efc6241201f07b033e07","original_commit_id":"8a22cd4a5c318fda0d7da8ef7221818211d4af5a","user":{"login":"andreareale","id":1241831,"avatar_url":"https://avatars.githubusercontent.com/u/1241831?v=3","gravatar_id":"","url":"https://api.github.com/users/andreareale","html_url":"https://github.com/andreareale","followers_url":"https://api.github.com/users/andreareale/followers","following_url":"https://api.github.com/users/andreareale/following{/other_user}","gists_url":"https://api.github.com/users/andreareale/gists{/gist_id}","starred_url":"https://api.github.com/users/andreareale/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/andreareale/subscriptions","organizations_url":"https://api.github.com/users/andreareale/orgs","repos_url":"https://api.github.com/users/andreareale/repos","events_url":"https://api.github.com/users/andreareale/events{/privacy}","received_events_url":"https://api.github.com/users/andreareale/received_events","type":"User","site_admin":false},"body":"changed","created_at":"2015-12-07T12:19:25Z","updated_at":"2015-12-07T12:19:25Z","html_url":"https://github.com/amplab/tachyon/pull/2216#discussion_r46814741","pull_request_url":"https://api.github.com/repos/amplab/tachyon/pulls/2216","_links":{"self":{"href":"https://api.github.com/repos/amplab/tachyon/pulls/comments/46814741"},"html":{"href":"https://github.com/amplab/tachyon/pull/2216#discussion_r46814741"},"pull_request":{"href":"https://api.github.com/repos/amplab/tachyon/pulls/2216"}}},"pull_request":{"url":"https://api.github.com/repos/amplab/tachyon/pulls/2216","id":52690978,"html_url":"https://github.com/amplab/tachyon/pull/2216","diff_url":"https://github.com/amplab/tachyon/pull/2216.diff","patch_url":"https://github.com/amplab/tachyon/pull/2216.patch","issue_url":"https://api.github.com/repos/amplab/tachyon/issues/2216","number":2216,"state":"open","locked":false,"title":"[TACHYON-655] Implement FUSE connector","user":{"login":"andreareale","id":1241831,"avatar_url":"https://avatars.githubusercontent.com/u/1241831?v=3","gravatar_id":"","url":"https://api.github.com/users/andreareale","html_url":"https://github.com/andreareale","followers_url":"https://api.github.com/users/andreareale/followers","following_url":"https://api.github.com/users/andreareale/following{/other_user}","gists_url":"https://api.github.com/users/andreareale/gists{/gist_id}","starred_url":"https://api.github.com/users/andreareale/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/andreareale/subscriptions","organizations_url":"https://api.github.com/users/andreareale/orgs","repos_url":"https://api.github.com/users/andreareale/repos","events_url":"https://api.github.com/users/andreareale/events{/privacy}","received_events_url":"https://api.github.com/users/andreareale/received_events","type":"User","site_admin":false},"body":"I will soon push a new PR with proper testing and more docs but, to keep the pipeline fed, please feel free to look at this code and comment. Thanks!","created_at":"2015-12-04T16:35:23Z","updated_at":"2015-12-07T12:19:25Z","closed_at":null,"merged_at":null,"merge_commit_sha":"c082d3635671448ef49da3a59ad760f9692c8d8a","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/amplab/tachyon/pulls/2216/commits","review_comments_url":"https://api.github.com/repos/amplab/tachyon/pulls/2216/comments","review_comment_url":"https://api.github.com/repos/amplab/tachyon/pulls/comments{/number}","comments_url":"https://api.github.com/repos/amplab/tachyon/issues/2216/comments","statuses_url":"https://api.github.com/repos/amplab/tachyon/statuses/178a7d95feb233fcfac0efc6241201f07b033e07","head":{"label":"ibm-research-ireland:fuse","ref":"fuse","sha":"178a7d95feb233fcfac0efc6241201f07b033e07","user":{"login":"ibm-research-ireland","id":14938632,"avatar_url":"https://avatars.githubusercontent.com/u/14938632?v=3","gravatar_id":"","url":"https://api.github.com/users/ibm-research-ireland","html_url":"https://github.com/ibm-research-ireland","followers_url":"https://api.github.com/users/ibm-research-ireland/followers","following_url":"https://api.github.com/users/ibm-research-ireland/following{/other_user}","gists_url":"https://api.github.com/users/ibm-research-ireland/gists{/gist_id}","starred_url":"https://api.github.com/users/ibm-research-ireland/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ibm-research-ireland/subscriptions","organizations_url":"https://api.github.com/users/ibm-research-ireland/orgs","repos_url":"https://api.github.com/users/ibm-research-ireland/repos","events_url":"https://api.github.com/users/ibm-research-ireland/events{/privacy}","received_events_url":"https://api.github.com/users/ibm-research-ireland/received_events","type":"Organization","site_admin":false},"repo":{"id":43545414,"name":"tachyon","full_name":"ibm-research-ireland/tachyon","owner":{"login":"ibm-research-ireland","id":14938632,"avatar_url":"https://avatars.githubusercontent.com/u/14938632?v=3","gravatar_id":"","url":"https://api.github.com/users/ibm-research-ireland","html_url":"https://github.com/ibm-research-ireland","followers_url":"https://api.github.com/users/ibm-research-ireland/followers","following_url":"https://api.github.com/users/ibm-research-ireland/following{/other_user}","gists_url":"https://api.github.com/users/ibm-research-ireland/gists{/gist_id}","starred_url":"https://api.github.com/users/ibm-research-ireland/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ibm-research-ireland/subscriptions","organizations_url":"https://api.github.com/users/ibm-research-ireland/orgs","repos_url":"https://api.github.com/users/ibm-research-ireland/repos","events_url":"https://api.github.com/users/ibm-research-ireland/events{/privacy}","received_events_url":"https://api.github.com/users/ibm-research-ireland/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ibm-research-ireland/tachyon","description":"Memory Centric Reliable Distributed Storage","fork":true,"url":"https://api.github.com/repos/ibm-research-ireland/tachyon","forks_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/forks","keys_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/teams","hooks_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/hooks","issue_events_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/issues/events{/number}","events_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/events","assignees_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/assignees{/user}","branches_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/branches{/branch}","tags_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/tags","blobs_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/git/refs{/sha}","trees_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/statuses/{sha}","languages_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/languages","stargazers_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/stargazers","contributors_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/contributors","subscribers_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/subscribers","subscription_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/subscription","commits_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/commits{/sha}","git_commits_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/git/commits{/sha}","comments_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/comments{/number}","issue_comment_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/issues/comments{/number}","contents_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/contents/{+path}","compare_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/merges","archive_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/downloads","issues_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/issues{/number}","pulls_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/pulls{/number}","milestones_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/milestones{/number}","notifications_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/labels{/name}","releases_url":"https://api.github.com/repos/ibm-research-ireland/tachyon/releases{/id}","created_at":"2015-10-02T09:38:26Z","updated_at":"2015-10-02T09:43:51Z","pushed_at":"2015-12-07T12:15:30Z","git_url":"git://github.com/ibm-research-ireland/tachyon.git","ssh_url":"git@github.com:ibm-research-ireland/tachyon.git","clone_url":"https://github.com/ibm-research-ireland/tachyon.git","svn_url":"https://github.com/ibm-research-ireland/tachyon","homepage":"http://tachyon-project.org","size":32444,"stargazers_count":1,"watchers_count":1,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":1,"default_branch":"master"}},"base":{"label":"amplab:master","ref":"master","sha":"1bbe1813b7bbb28f7183e4acf4b546e1f93d68be","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":"Memory Centric Reliable Distributed Storage","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-12-07T06:34:37Z","pushed_at":"2015-12-07T12:15:32Z","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":40588,"stargazers_count":1784,"watchers_count":1784,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":708,"mirror_url":null,"open_issues_count":31,"forks":708,"open_issues":31,"watchers":1784,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/amplab/tachyon/pulls/2216"},"html":{"href":"https://github.com/amplab/tachyon/pull/2216"},"issue":{"href":"https://api.github.com/repos/amplab/tachyon/issues/2216"},"comments":{"href":"https://api.github.com/repos/amplab/tachyon/issues/2216/comments"},"review_comments":{"href":"https://api.github.com/repos/amplab/tachyon/pulls/2216/comments"},"review_comment":{"href":"https://api.github.com/repos/amplab/tachyon/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/amplab/tachyon/pulls/2216/commits"},"statuses":{"href":"https://api.github.com/repos/amplab/tachyon/statuses/178a7d95feb233fcfac0efc6241201f07b033e07"}}}}