)]}'
{
  "commit": "16419dad35792bd4f9c8cc6eaff38faa7c9cd522",
  "tree": "7640be0d7a4c83a2df542e0a55f03a3fb028bb75",
  "parents": [
    "5b0e73b849d19c9f072c4c6738a5d5adae413112"
  ],
  "author": {
    "name": "Shawn O. Pearce",
    "email": "spearce@spearce.org",
    "time": "Wed May 26 19:00:06 2010 -0700"
  },
  "committer": {
    "name": "Shawn O. Pearce",
    "email": "spearce@spearce.org",
    "time": "Thu May 27 08:27:32 2010 -0700"
  },
  "message": "Don\u0027t use interruptable pread() to access pack files\n\nThe J2SE NIO APIs require that FileChannel close the underlying file\ndescriptor if a thread is interrupted while it is inside of a read or\nwrite operation on that channel.  This is insane, because it means we\ncannot share the file descriptor between threads.  If a thread is in\nthe middle of the FileChannel variant of IO.readFully() and it\nreceives an interrupt, the pack will be automatically closed on us.\nThis causes the other threads trying to use that same FileChannel to\nreceive IOExceptions, which leads to the pack getting marked as\ninvalid.  Once the pack is marked invalid, JGit loses access to its\nentire contents and starts to report MissingObjectExceptions.\n\nBecause PackWriter must ensure that the chosen pack file stays\navailable until the current object\u0027s data is fully copied to the\noutput, JGit cannot simply reopen the pack when its automatically\nclosed due to an interrupt being sent at the wrong time.  The pack may\nhave been deleted by a concurrent `git gc` process, and that open file\ndescriptor might be the last reference to the inode on disk.  Once its\nclosed, the PackWriter loses access to that object representation, and\nit cannot complete sending the object the client.\n\nFortunately, RandomAccessFile\u0027s readFully method does not have this\nproblem.  Interrupts during readFully() are ignored.  However, it\nrequires us to first seek to the offset we need to read, then issue\nthe read call.  This requires locking around the file descriptor to\nprevent concurrent threads from moving the pointer before the read.\n\nThis reduces the concurrency level, as now only one window can be\npaged in at a time from each pack.  However, the WindowCache should\nalready be holding most of the pages required to handle the working\nset for a process, and its own internal locking was already limiting\nus on the number of concurrent loads possible.  Provided that most\nconcurrent accesses are getting hits in the WindowCache, or are for\ndifferent repositories on the same server, we shouldn\u0027t see a major\nperformance hit due to the more serialized loading.\n\nI would have preferred to use a pool of RandomAccessFiles for each\npack, with threads borrowing an instance dedicated to that thread\nwhenever they needed to page in a window.  This would permit much\nhigher levels of concurrency by using multiple file descriptors (and\nfile pointers) for each pack.  However the code became too complex to\ndevelop in any reasonable period of time, so I\u0027ve chosen to retrofit\nthe existing code with more serialization instead.\n\nBug: 308945\nChange-Id: I2e6e11c6e5a105e5aef68871b66200fd725134c9\nSigned-off-by: Shawn O. Pearce \u003cspearce@spearce.org\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "6b746e3193e2104f2799ec33559429d5a6179de7",
      "old_mode": 33188,
      "old_path": "org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/FileSender.java",
      "new_id": "731b4caa83c79f306fdcf4ff464c1c3fd06199c9",
      "new_mode": 33188,
      "new_path": "org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/FileSender.java"
    },
    {
      "type": "modify",
      "old_id": "8f4e691630e2f7205365e07c7c808d90ce22c022",
      "old_mode": 33188,
      "old_path": "org.eclipse.jgit/src/org/eclipse/jgit/lib/PackFile.java",
      "new_id": "829832e6a5e5ca84f7e883b13fcbcbc5763ebb6f",
      "new_mode": 33188,
      "new_path": "org.eclipse.jgit/src/org/eclipse/jgit/lib/PackFile.java"
    },
    {
      "type": "modify",
      "old_id": "17786542034489a31916f30b26b4505e9a24ad78",
      "old_mode": 33188,
      "old_path": "org.eclipse.jgit/src/org/eclipse/jgit/util/IO.java",
      "new_id": "1f2042d4c2d6e61446e5f06de19800e7132ed788",
      "new_mode": 33188,
      "new_path": "org.eclipse.jgit/src/org/eclipse/jgit/util/IO.java"
    }
  ]
}
