Commit Graph

257 Commits

Author SHA1 Message Date
Adam Simpkins
b0d1e57975 update logging statements to use folly logging APIs
Summary:
Update eden to log via the new folly logging APIs rather than with glog.

This adds a new --logging flag that takes a logging configuration string.
By default we set the log level to INFO for all eden logs, and WARNING for
everything else.  (I suspect we may eventually want to run with some
high-priority debug logs enabled for some or all of eden, but this seems like a
reasonable default to start with.)

Reviewed By: wez

Differential Revision: D5290783

fbshipit-source-id: 14183489c48c96613e2aca0f513bfa82fd9798c7
2017-06-22 13:50:13 -07:00
Adam Simpkins
6b62f186c7 drop Future from the name of ObjectStore APIs
Summary:
Now that the non-future versions of these APIs have been removed, rename
getBlobFuture() to getBlob(), and getTreeFuture() to getTree()

Reviewed By: wez

Differential Revision: D5295690

fbshipit-source-id: 30dcb88854b23160692b9cd83a632f863e07b491
2017-06-21 17:20:50 -07:00
Adam Simpkins
33cb16d97e remove the deprecated ObjectStore::getBlob() API
Summary:
Remove the blocking getBlob() API.

There were a few call sites in FileData still using this blocking API.  For now
I simply updated them to use getBlobFuture() and make a blocking get() call on
the returned future.  These call sites already had TODO comments documenting
the blocking behavior.

I plan to rename getBlobFuture() to getBlob() in a subsequent diff.

Reviewed By: wez

Differential Revision: D5295726

fbshipit-source-id: 748fd7a140b9b59da339a330071f732bba38cb35
2017-06-21 17:20:50 -07:00
Adam Simpkins
5740a0645b remove ObjectStores.h
Summary:
Remove the ObjectStores.h and .cpp files.  These files contained helper
functions for looking up Tree and TreeEntry objects based on a deep relative
path.

These functions are no longer used anywhere anymore (the code that performs
deep lookups always does inode lookups instead).  Additionally, this file is
the only place still using some of the blocking, non-Future-based APIs for
object lookups.  Deleting these files will let us remove these deprecated
blocking APIs.

Reviewed By: wez

Differential Revision: D5295691

fbshipit-source-id: 89229827305490eba4d3a581954a90c5cf63238d
2017-06-21 17:20:48 -07:00
Andrew Gallagher
03bdaff954 codemod: format TARGETS with buildifier [4/5] (D5092623)
Reviewed By: igorsugak

fbshipit-source-id: 277a9d2bdc1d7e3ff3075bfe2d7307502fd0a507
2017-06-01 17:52:40 -07:00
Michael Bolin
57f5d72a27 Reimplement dirstate used by Eden's Hg extension as a subclass of Hg's dirstate.
Summary:
This is a major change to Eden's Hg extension.

Our initial attempt to implement `edendirstate` was to create a "clean room"
implementation that did not share code with `mercurial/dirstate.py`. This was
helpful in uncovering the subset of the dirstate API that matters for Eden. It
also provided a better safeguard against upstream changes to `dirstate.py` in
Mercurial itself.

In this implementation, the state transition management was mostly done
on the server in `Dirstate.cpp`. We also made a modest attempt to make
`Dirstate.cpp` "SCM-agnostic" such that the same APIs could be used for
Git at some point.

However, as we have tried to support more of the sophisticated functionality
in Mercurial, particularly `hg histedit`, achieving parity between the clean room
implementation and Mercurial's internals has become more challenging.
Ultimately, the clean room implementation is likely the right way to go for Eden,
but for now, we need to prioritize having feature parity with vanilla Hg when
using Eden. Once we have a more complete set of integration tests in place,
we can reimplement Eden's dirstate more aggressively to optimize things.

Fortunately, the [[ https://bitbucket.org/facebook/hg-experimental/src/default/sqldirstate/ | sqldirstate ]]
extension has already demonstrated that it is possible to provide a faithful
dirstate implementation that subclasses the original `dirstate` while using a different
storage mechanism. As such, I used `sqldirstate` as a model when implementing
the new `eden_dirstate` (distinguishing it from our v1 implementation, `edendirstate`).

In particular, `sqldirstate` uses SQL tables as storage for the following private fields
of `dirstate`: `_map`, `_dirs`, `_copymap`, `_filefoldmap`, `_dirfoldmap`. Because
`_filefoldmap` and `_dirfoldmap` exist to deal with case-insensitivity issues, we
do not support them in `eden_dirstate` and add code to ensure the codepaths that
would access them in `dirstate` never get exercised. Similarly, we also implemented
`eden_dirstate` so that it never accesses `_dirs`. (`_dirs` is a multiset of all directories in the
dirstate, which is an O(repo) data structure, so we do not want to maintain it in Eden.
It appears to be primarily used for checking whether a path to a file already exists in
the dirstate as a directory. We can protect against that in more efficient ways.)

That leaves only `_map` and `_copymap` to worry about. `_copymap` contains the set
of files that have been marked "copied" in the current dirstate, so it is fairly small and
can be stored on disk or in memory with little concern. `_map` is a bit trickier because
it is expected to have an entry for every file in the dirstate. In `sqldirstate`, it is stored
across two tables: `files` and `nonnormalfiles`. For Eden, we already represent the data
analogous to the `files` table in RocksDB/the overlay, so we do not need to create a new
equivalent to the `files` table. We do, however, need an equivalent to the `nonnormalfiles`
table, which we store in as Thrift-serialized data in an ordinary file along with the `_copymap`
data.

In our Hg extension, our implementation of `_map` is `eden_dirstate_map`, which is defined
in a Python file of the same name. Our implementation of `_copymap` is `dummy_copymap`,
which is defined in `eden_dirstate.py`. Both of these collections are simple pass-through data
structures that translate their method calls to Thrift server calls. I expect we will want to
optimize this in the future via some client-side caching, as well as creating batch APIs for talking
to the server via Thrift.

One advantage of this new implementation is that it enables us to delete
`eden/hg/eden/overrides.py`, which overrode the entry points for `hg add` and `hg remove`.
Between the recent implementation of `dirstate.walk()` for Eden and this switch
to the real dirstate, we can now use the default implementation of `hg add` and `hg remove`
(although we have to play some tricks, like in the implementation of `eden_dirstate.status()`
in order to make `hg remove` work).

In the course of doing this revision, I discovered that I had to make a minor fix to
`EdenMatchInfo.make_glob_list()` because `hg add foo` was being treated as
`hg add foo/**/*` even when `foo` was just a file (as opposed to a directory), in which
case the glob was not matching `foo`!

I also had to do some work in `eden_dirstate.status()` in which the `match` argument
was previously largely ignored. It turns out that `dirstate.py` uses `status()` for a number
of things with the `match` specified as a filter, so the output of `status()` must be filtered
by `match` accordingly. Ultimately, this seems like work that would be better done on the
server, but for simplicity, we're just going to do it in Python, for now.

For the reasons explained above, this revision deletes a lot of code `Dirstate.cpp`.
As such, `DirstateTest.cpp` does not seem worth refactoring, though the scenarios it was
testing should probably be converted to integration tests. At a high level, the role of
`DirstatePersistence` has not changed, but the exact data it writes is much different.
Its corresponding unit test is also disabled, for now.

Note that this revision does not change the name of the file where "dirstate data" is written
(this is defined as `kDirstateFile` in `ClientConfig.cpp`), so we should blow away any existing
instances of this file once this change lands. (It is still early enough in the project that it does
not seem worth the overhead of a proper migration.)

The true test of the success of this new approach is the ease with which we can write more
integration tests for things like `hg histedit` and `hg graft`. Ideally, these should require very
few changes to `eden_dirstate.py`.

Reviewed By: simpkins

Differential Revision: D5071778

fbshipit-source-id: e8fec4d393035d80f36516ac050cad025dc3ba31
2017-05-26 12:05:29 -07:00
Eric Niebler
801fce3a91 Replace FOLLY_WARN_UNUSED_RESULT with FOLLY_NODISCARD everywhere
Summary: `[[nodiscard]]` is the future. Let's start now.

Reviewed By: yfeldblum

Differential Revision: D5108297

fbshipit-source-id: c98f44af9e282616af92f9171516b6ea18e68c6d
2017-05-24 20:40:38 -07:00
Victor Gao
f5c853a552 apply clang-tidy modernize-use-override
Summary:
This is generated by applying clang-tidy `-checks=modernize-use-override` to all the c++ code in project eden.
It enforces the use of the keywords `virtual`, `verride` and `final` in a way compliant to the style guide.

Reviewed By: igorsugak

Differential Revision: D5108807

fbshipit-source-id: 596f2d73f1137de350114416edb1c37da5423ed5
2017-05-23 16:10:26 -07:00
Eric Niebler
27c4156b1f Add FOLLY_NODISCARD for [[nodiscard]] attribute when it exists, FOLLY_WARN_UNUSED_RESULT uses FOLLY_NODISCARD.
Summary: The `nodiscard` attribute was added to standard C++ in C++17. Prefer the standard formulation when it is available; otherwise, use `__attribute__((__warn_unused_result__))` on compilers that support the GNU extensions, and `_Check_return_` on MSVC. The old `FOLLY_WARN_UNUSED_RESULT` is now expands to `FOLLY_NODISCARD`.

Reviewed By: yfeldblum

Differential Revision: D5105137

fbshipit-source-id: 9aa22e81cd9f0b89f9343433aeae3ba365227ccb
2017-05-23 09:05:33 -07:00
Yiding Jia
cf7935f0ab Add missing includes in eden files
Summary:
These files are defining flags, so they should import gflags.
This import being missing causes open source build to fail.

Reviewed By: bolinfest

Differential Revision: D4992246

fbshipit-source-id: 61eb35b43ae6f9ff88bd34a9ebc8db6d80ac9d08
2017-05-03 10:30:32 -07:00
Adam Simpkins
c3f47540b0 update the Dirstate to use TreeInode directly to unlink files
Summary:
Update Dirstate::remove() to directly call TreeInode::unlink() instead of going
through the EdenDispatcher.  Internal code should be able to use TreeInode
directly without going through the FUSE Dispatcher.  This prevents us from
having to look up the TreeInode object by inode number again.

This also fixes TreeInode::unlink() and TreeInode::rmdir() to perform FUSE
cache invalidation correctly.  EdenDispatcher used to do this for unlink()
calls, but it was missing for rmdir() calls.

Reviewed By: wez

Differential Revision: D4968832

fbshipit-source-id: 51fda5de196392c640436ca6ad7d8333e6799db9
2017-05-01 18:54:42 -07:00
Adam Simpkins
a521832407 simplify the Dirstate::removeAll() code
Summary:
This replaces the shouldFileBeDeletedByHgRemove() function with a much simpler
and safer check.

It turns out this code was more complicated than it needed to be: it looked up
the inode in question and confirmed that it still existed, even though it's
calling function had already previously looked up the inode object.

I believe this deletes the last place in the code that still assumes that an
InodeBase object must be loaded if the inode has previously been materialized.
This also removes one of the last remaining places that directly holds the
TreeInode contents_ lock outside of TreeInode.cpp.

Reviewed By: bolinfest

Differential Revision: D4968834

fbshipit-source-id: a37bc0d7889eb81cca5b045cbc82732a53ef53d4
2017-05-01 18:54:41 -07:00
Adam Simpkins
51df0c0663 refactor Dirstate::addAll() to clean up some old code
Summary:
This updates the Dirstate::addAll() code to use EdenMount::diff() internally,
instead of getStatusForExistingDirectory().

This lets us delete getStatusForExistingDirectory() and several other helper
functions that it used.  The logic in getStatusForExistingDirectory() was based
on the incorrect assumption that files can only be modified from their expected
source control state if they are materialized.  This could result in incorrect
results in a variety of cases (particularly after renames, or "hg reset"
operations).  The EdenMount::diff() code does not have this problem.

That said, this new addAll() code does still have some performance issues--it
currently does a full tree diff for each input path.  We should ideally fix
this in the future to only diff the necessary subtree for each path.  However,
in the short term this trade-off seems worth being able to delete all of this
older, buggy code.  diff() should be cheap enough in most cases that this won't
be a major problem unless a large number of paths are given as input.

Reviewed By: bolinfest

Differential Revision: D4968835

fbshipit-source-id: 1834aa98a26dcaa0e1c06c7ac25c57944fa1b5f7
2017-05-01 18:54:41 -07:00
Adam Simpkins
eb1a2b671c minor clean up to GitIgnoreStack handling
Summary:
Make sure we use pointers to const GitIgnoreStack objects when possible.

Also change the code to store the root GitIgnoreStack object for a diff()
operation in the DiffContext object, instead of having EdenMount::diff()
allocate it separately on the heap.  This will make it easier to consolidate a
bit more logic in the DiffContext class in the future.  In particular, I
suspect we will want a version of diff() that only works on one portion of the
tree.  Putting more of the functionality in DiffContext will make it slightly
easier to share code between the full-mount diff and the subtree diff
functions.  This also happens to save a memory allocation for now.

Reviewed By: wez

Differential Revision: D4968833

fbshipit-source-id: 1dc33b3d44cdf00e93b22d810c3a736d27c13638
2017-04-28 19:21:34 -07:00
Adam Simpkins
a9b2c41328 update the hg extension to support multiple parents
Summary:
Update the eden thrift APIs to support multiple thrift parents, and update the
hg extension to use the new thrift APIs.

Reviewed By: bolinfest

Differential Revision: D4949139

fbshipit-source-id: 98a7bd17ccad7be6a429df34ecfaf3fe7ae0b39a
2017-04-27 17:37:03 -07:00
Adam Simpkins
f5e924af94 support storing two parent commits
Summary:
This updates the ClientConfig and EdenMount code to support storing two parent
commits.

This changes the on-disk SNAPSHOT file contents add an 8-byte header that
includes a file identifier and a file format version number, followed by up to
two commit hashes.  The code currently can read either the old or new format
from the SNAPSHOT file.  We should be able to drop the code for reading the old
format fairly soon if we want, though.

This diff only updates the ClientConfig and EdenMount code, and does not yet
update the thrift APIs or the eden mercurial extension yet.  I will update the
rest of the code in a subsequent diff.

Reviewed By: bolinfest, wez

Differential Revision: D4943917

fbshipit-source-id: cf456e67b845aa0cf8b45c822985cb932df107b4
2017-04-27 11:50:13 -07:00
Adam Simpkins
d090035fa4 add unit tests for FileInode::setattr()
Summary: Add some unit tests that check the behavior of setattr() and getattr().

Reviewed By: bolinfest, wez

Differential Revision: D4941215

fbshipit-source-id: 6691f51aea742d0159a16112ca291546a8adc928
2017-04-26 21:51:36 -07:00
Adam Simpkins
87cbfe142b update the in-memory snapshot correctly after a commit
Summary:
This fixes "hg commit" so that it correctly updates the in-memory snapshot.
This has been broken ever since I added the in-memory snapshot when
implementing checkout().  The existing scmMarkCommitted() method updated only
the Dirstate object and the on-disk SNAPSHOT file.

This diff fixes checkout() and resetCommit() to clear the Dirstate user
directives correctly, and then replaces calls to scmMarkCommitted() with
resetCommit().

Reviewed By: bolinfest

Differential Revision: D4935943

fbshipit-source-id: 5ffcfd5db99f30c730ede202c5e013afa682bac9
2017-04-24 18:06:59 -07:00
Adam Simpkins
841c9006e3 honor trailing slashes on gitignore patterns
Summary:
Update the gitignore code so that patterns ending in a trailing slash correctly
match only directories.  Fortunately we have file type information available
during TreeInode::computeDiff(), so getting the correct file type information
does not add any extra overhead.  The older ignore checking code in
Dirstate.cpp can also do a reasonable job of getting file type information.
That code should also be removed at some point in the future, and use the
TreeInode logic for computing ignore status.

Reviewed By: bolinfest

Differential Revision: D4901326

fbshipit-source-id: 1222c8142876c91e1b80ec937ec84c0c28737224
2017-04-20 21:21:15 -07:00
Wez Furlong
c51abba97a avoid an issue reported by ASAN
Summary:
The temporary Hash object doesn't live long enough for the copy into
the string, so make an explicit temporary to extend its lifetime.

Reviewed By: simpkins

Differential Revision: D4900457

fbshipit-source-id: 948d919b929285c30ee1f9f0111cba20b60d4dc6
2017-04-17 15:35:09 -07:00
Adam Simpkins
a6ae3edab9 move eden/utils and eden/fuse into eden/fs
Summary:
This change makes it so that all of the C++ code related to the edenfs daemon
is now contained in the eden/fs subdirectory.

Reviewed By: bolinfest, wez

Differential Revision: D4889053

fbshipit-source-id: d0bd4774cc0bdb5d1d6b6f47d716ecae52391f37
2017-04-14 11:39:02 -07:00
Adam Simpkins
4bb5948640 fix an invalid memory access in the checkout code
Summary:
Fix a subtle crash during checkout when handling newly added entries that
already exist in the working directory: CheckoutAction passed the entry name to
checkoutUpdateEntry() as a PathComponentPiece.  However, this
PathComponentPiece could refer to the entry name owned by newScmEntry_, and it
also passed newScmEntry_ into checkoutUpdateEntry() as an rvalue reference.
As a result, if the string data was stored invalidated by the move the name
would no longer be valid when checkoutUpdateEntry() tried to use it.

This bug is triggered by doing an "hg update --clean", where a file added in
the destination commit already exists on disk, and has an entry name of 23
characters or less.  (The 23 character limit is fbstring's upper bound on
small string optimizations, where it will store the string data inline in the
object, causing it to be invalidated on move.)

This also fixes a crash in a VLOG() statement when the verbose log level for
TreeInode.cpp was set to 4 or greater.

Reviewed By: bolinfest

Differential Revision: D4882544

fbshipit-source-id: 917ede6eeae2224aaa0724b8b30324f3c3a5c924
2017-04-13 17:34:38 -07:00
Wez Furlong
acb6539f87 add .eden/client symlink
Summary:
The intent is to provide a way to locate the SNAPSHOT file
for tools that want to have a very fast way to figure out the commit
id without making any RPCs or subprocess invocations.

Reviewed By: simpkins

Differential Revision: D4824176

fbshipit-source-id: 5adca225d9984146852dad1e83de0d903848c1e5
2017-04-06 13:20:02 -07:00
Adam Simpkins
b4527fe5bb simplify InodePtr classes
Summary:
This simplifies the InodePtrImpl class by removing support for pointer-to-const
Inode objects.  We don't currently use pointer-to-const Inode objects, and I
don't really anticipate that we will ever need this.

The primary motivating factor behind this diff is a recent change in clang that
breaks the existing code: clang PR31606 prevents children classes from
inheriting template constructor instantiations from their parent which take a
reference to the parent class type as the only argument.

While this could have been fixed by explicitly defining the necessary
constructors in the child class (or simply by overriding newPtrLocked() and
newPtrFromExisting() to return the subclass type), dropping support for
pointer-to-const allows us to simplify the code and resolve this issue.

Reviewed By: wez

Differential Revision: D4825526

fbshipit-source-id: 999de352788b13818b7f23788bb34686e193cd5d
2017-04-06 13:20:01 -07:00
Adam Simpkins
d6f7a2f91a report timestamps on non-materialized files
Summary:
This diff fixes FileData::stat() so that we report reasonable timestamp values
on non-materialized files, rather than always leaving them as 0.  We set the
timestamps to the time that we created the FileInode.  This ensures that
timestamps are updated correctly when files are modified by a checkout
operation.

Note that for materialized files the code reports the timestamp of the overlay
file.  This diff does not modify that behavior.  However, this behavior is
incorrect, as the overlay file timestamps are not updated by a FUSE client
opening, modifying, then closing a file (since we keep the underyling overlay
file handle open, and don't close it).

In the future we'll need to implement our own tracking of atime, mtime, and
ctime values.  We should probably store these in a header inside the overlay
file.  For now, this diff is a stop-gap measure that ensures we at least update
non-materialized file timestamps correctly on checkouts.

Reviewed By: bolinfest

Differential Revision: D4765632

fbshipit-source-id: 478da6441e213cdfe830f1c5129212182ce4eeb0
2017-04-03 15:50:32 -07:00
Adam Simpkins
6d4d187deb an "eden debug" CLI command and thrift APIs to support it
Summary:
This diff adds a new "eden debug" command, with a few subcommands:

- "eden debug inode": Report information about currently loaded inodes
- "eden debug tree": Report data about source control Tree objects
- "eden debug blobmeta": Report metadata about source control Blob objects
- "eden debug blob": Report the contents of source control Blob objects

This diff also includes the thrift APIs in edenfs to support these commands.

Reviewed By: bolinfest

Differential Revision: D4760528

fbshipit-source-id: 7dc2bd6e0e952ba6fb61702c672fb9417d603ffa
2017-04-03 15:50:32 -07:00
Igor Sugak
ad6811a301 use googletest instead of gtest with gmock
Summary:
This updates all of the references to gtest and gmock with googletest.

The change is mechanilcal, generated with the following one-liner:
```lang=bash
hg grep -lwE '(gtest|gmock)' 'glob:**/TARGETS' | grep -v '^third-party-buck' | xargs perl -pi -e '
$gt=qr!(["'"'"'])gtest\g1!;
(
  s!$gt(\s*,\s*(.any.|None))(\s*,\s*)?\),?!\1googletest\1\2, \1gtest\1\),!g or
  s!$gt((\s*,\s*(.any.|None)[^\)]+))\),?!\1googletest\1\2\),!g or
  s!\(\s*$gt,?\s*\),?!\(\1googletest\1, None, \1gtest\1\),!g or
  s!$gt,?!\(\1googletest\1, None, \1gtest\1\),!g
) unless /(name|type) *=/;

$gm=qr!(["'"'"'])gmock\g1!;
(
  s!$gm(\s*,\s*(.any.|None))(\s*,\s*)?\),?!\1googletest\1\2, \1gmock\1\),!g or
  s!$gm((\s*,\s*(.any.|None)[^\)]+))\),?!\1googletest\1\2\),!g or
  s!\(\s*$gm,?\s*\),?!\(\1googletest\1, None, \1gmock\1\),!g or
  s!$gm,?!\(\1googletest\1, None, \1gmock\1\),!g
) unless /(name|type) *=/;
'
```

Reviewed By: meyering

Differential Revision: D4643237

fbshipit-source-id: fda7f41760c7e44254231df87634631c343e6355
2017-04-01 09:21:54 -07:00
Wez Furlong
66ec00f294 connect the fuse stats to fb303
Summary:
Tweaks the stats stuff so that we can name the histograms and export them with p50, p90, p99 percentiles.

This is made a bit ugly because the fb303 stats code isn't yet open source, so
there's a moderately ugly preprocessor directive that we assume to be true for
our internal build.   We'll need to force that to be 0 for the open source build
until we open the stats code and make it available.

Reviewed By: bolinfest

Differential Revision: D4801868

fbshipit-source-id: 643909e63bd4a74b2cfa580be131f65c5673bc94
2017-03-31 11:39:48 -07:00
Wez Furlong
7c6f9608c2 add basic mknod support
Summary:
this is the bare minimum to support creating unix domain sockets.

We only support using mknod to create a unix socket; other uses will yield an error.

I've added an rdev field as a sibling of the existing mode field that we track,
as that is the additional parameter that we need to track as part of the
special file node.

Special file nodes are tracked in the overlay as empty files.

Reviewed By: bolinfest

Differential Revision: D4774099

fbshipit-source-id: 0824b7e509063faa8bede7aff82a7c51930c4f83
2017-03-30 23:53:05 -07:00
Adam Simpkins
6cced7c449 implement "hg status" using EdenMount::diff()
Summary:
This is an initial pass at implementing "hg status" using the new EdenMount and
TreeInode diff() code.

More work still needs to be done to clean things up here, but this makes
"hg status" more correct in the face of modified files and directories that are
not modified, and vice-versa.

In particular, the following still needs to be cleaned up in future diffs:
- Update the "hg status" code to more correctly process user directives for
  paths that did not appear in the diff output.  This will probably be
  simplified some by correctly updating the user directive list on checkout and
  resetCommit() operations.  It may also make things simpler if we store the
  user directives in a hierarchical path map, rather than in a flat list.
- Update the addAll() code to also use the new diff logic, rather than the
  getStatusForExistingDirectory() function.
- Clean up the locking some.  I think it may be worth changing the code to use
  a single lock to manage both the current commit ID for the mount and the
  dirstate user directives.  We probably should hold this lock for the duration
  of a diff operation.  The diff operation should also return the commit ID
  that it is based against.

Reviewed By: wez

Differential Revision: D4752281

fbshipit-source-id: 6a6d7e2815321b09c75e95aa7460b0da41931dc0
2017-03-30 21:35:00 -07:00
Wez Furlong
4235784907 add .eden "magic" dir
Summary:
It's not really magic because we don't have a virtual directory
inode base any more.  Instead, we mkdir and populate it at mount time.

What is slightly magical about it is that we give it some special powers:

* We know the inode number of the eden dir and prevent unlink operations
  on it or inside it.
* The .eden dir is present in the contents of the root inode and will
  show up when that directory is `readdir`'d
* When resolving a child of a TreeInode by name, we know to return the
  magic `.eden` inode number.  This means that it is possible to `stat`
  and consume the `.eden` directory from any directory inside the eden
  mount, even though it won't show up in `readdir` for those child dirs.

The contents of the `.eden` dir are:

* `socket` - a symlink back to the unix domain socket that our thrift
  server is listening on.  This means that it is a simple
  `readlink(".eden/socket")` operation to discover both whether a directory
  is part of an eden mount and how to talk to the server.

* `root` - a symlink back to the root of this eden mount.  This allows
  using `readlink(".eden/root")` as a simple 1-step operation to find
  the root of an eden mount, and avoids needing to walk up directory
  by directory as is the common pattern for locating `.hg` or `.git`
  dirs.

Reviewed By: simpkins

Differential Revision: D4637285

fbshipit-source-id: 0eabf98b29144acccef5c83bd367493399dc55bb
2017-03-24 23:07:42 -07:00
Adam Simpkins
0a6ea6bbfe fix EdenMount::diff() to skip .hg and .eden directories
Summary:
Update the EdenMount::diff() code to completely skip .hg and .eden directories.
This was implemented through the GitIgnore code, and adding a new HIDDEN status
The .hg and .eden directories are similar to ignored directories, but we never
want to report any information for them even when listIgnored is true.

This also changes the GitIgnore code to so that GitIgnoreStack computes the
basename for each path once, and passes it down into the underlying match code,
so we don't have to re-compute it for each pattern that needs the basename.

Reviewed By: wez

Differential Revision: D4751917

fbshipit-source-id: ec22d62f31a3ce9ef998a8ccb4413f72f1d7a487
2017-03-24 13:50:09 -07:00
Adam Simpkins
b6fe1a5111 update EdenMount::diff() to process .gitignore files
Summary:
This updates the diff() logic to process gitignore rules.

The bulk of the existing TreeInode::diff() was moved into a
TreeInode::computeDiff() function.  TreeInode::diff() now loads the gitignore
rules for this directory before calling computeDiff().  The argument list for
computeDiff() was now getting slightly unwieldy, so I created a new DiffContext
class to hold some of the arguments that are the same for the duration of the
entire diff operation.  This resulted in some rather mechanical changes through
the computeDiff() and DeferredDiffEntry code to update the argument lists.

Reviewed By: wez

Differential Revision: D4744690

fbshipit-source-id: c4981d9f49878b522e0b3faf35de837739066f3c
2017-03-24 13:50:09 -07:00
Adam Simpkins
a4d599c4c1 add one more checkout unit test
Summary:
Add a unit test that modifies a file and then does a forced checkout to revert
back to the original commit state.

This also includes some pretty-printers to make the tests print
CheckoutConflict objects nicely if any test assertions fail.

Reviewed By: bolinfest

Differential Revision: D4727779

fbshipit-source-id: b31dc90be28d17ed0f2a4076c96a08ba82588190
2017-03-21 12:53:26 -07:00
Adam Simpkins
d101f404dc add an EdenMount::diff() method
Summary:
This begins adding an EdenMount::diff() method, which walks through the inode
tree and reports differences from the current source control tree state.

My intent is to eventually update the Dirstate code to use this diff()
function, and to remove the existing getModifiedDirectories() logic.  The
getModifiedDirectories() code is currently incorrect, as it reports
materialized directories, which is not the same as directories that are
modified from the current source control state.

The ignore processing logic is not currently implemented in EdenMount::diff(),
but it should be relatively straightforward to add in a subsequent diff.

Reviewed By: bolinfest

Differential Revision: D4726048

fbshipit-source-id: ad0bb3b5d72bb3830f60fc2b2e56a81217c35353
2017-03-21 12:06:44 -07:00
Adam Simpkins
c8ea0d5ba6 implement removing directories during checkout
Summary:
Update the TreeInode and CheckoutAction to correctly be able to remove
directories during checkout operations.  This handles both removing directories
that are newly empty as a result of the checkout, and directories that are
replaced with a file or symlink.

This also refactors the rmdir/unlink code a bit so we can share some of its
logic for doing directory removal during the checkout operation.

Reviewed By: bolinfest

Differential Revision: D4708607

fbshipit-source-id: 3b9dd9cc3536845dad0d9278e3c5d3ac1ed04570
2017-03-17 17:13:20 -07:00
Adam Simpkins
7202883bf8 synchronize access to the CheckoutContext
Summary:
Synchronize access to the CheckoutContext conflicts_ list when recording
conflicts or errors during a checkout operation.

In theory it is possible for the checkout operation to be proceeding
simultaneously in multiple threads.  At the moment this does not happen because
the BackingStore implementations currently block, and always return
immediately-ready Future objects in the same thread.  However, once they are
updated to return Future objects that actually complete asynchronously in other
threads the checkout work will continue in these other threads.

Reviewed By: bolinfest

Differential Revision: D4708605

fbshipit-source-id: 885b0114d97dadcacf64652f795a7d3846412f11
2017-03-17 17:13:20 -07:00
Adam Simpkins
7de5d1d90c add a test for creating a new subdirectory via checkout()
Summary:
Add a test that exercises a checkout operation that creates a brand new
subdirectory.

Reviewed By: bolinfest

Differential Revision: D4693994

fbshipit-source-id: 70f43f67c2cdb10bd854f51d5ba2e61c45976975
2017-03-14 16:49:43 -07:00
Adam Simpkins
1add48d20b fix the build with gcc
Summary:
Unfortunately it looks like gcc won't support the [[nodiscard]] attribute until
the gcc-7.x release.  (The functionality is available in gcc-4.8 and later, but
using the name [[gnu::warn_unused_result]] instead.)

This changes the code to use the FOLLY_WARN_UNUSED_RESULT macro from
folly/Portability.h instead.  (This expands to older non-standard __attribute__
syntax for gcc and clang, and _Check_return_ on Windows.)

Reviewed By: bolinfest

Differential Revision: D4704184

fbshipit-source-id: d5c13630ea611a2f43080a501add42ce9fda6789
2017-03-14 14:31:54 -07:00
Adam Simpkins
bda49af5a3 add additional LoadBehavior types during checkout tests
Summary:
Add new ASSIGN_PARENT_INODE and ASSIGN_INODE types to LoadBehavior, to exercise
additional code paths during checkout operations.  This also cleans up the
overall handling of the LoadBehavior enum.

Reviewed By: bolinfest

Differential Revision: D4694548

fbshipit-source-id: e8359cfdadb1fabb1a0d07bc57a1a1610ed9ba57
2017-03-13 21:02:30 -07:00
Adam Simpkins
d1e1e4c621 refactor FileInode to avoid using its parent's TreeInode::Entry
Summary:
Refactor FileInode and FileData so that they no longer store the
TreeInode::Entry that refers to this file.  The TreeInode::Entry is owned by
the parent TreeInode and is not safe to access without holding the TreeInode
contents_ lock, which the FileInode code never did.  Additionally, once a
FileInode is unlocked the TreeInode::Entry is destroyed.  Previously the
FileInode code would retain its pointer to this now invalid data, and could
still dereference it.

In the future I think it might be worth refactoring the FileInode/FileData
split a bit more, but this at least addresses the issues around invalid
accesses to entry_.

Reviewed By: bolinfest

Differential Revision: D4688058

fbshipit-source-id: 17d5d0c4e756afc6e3c4bb279cb1bb5231f3134f
2017-03-10 18:29:29 -08:00
Adam Simpkins
90b44c1ec2 remove TreeInode::entry_
Summary:
Remove the TreeInode::entry_ member variable.  This was a pointer to the
TreeInode::Entry object representing this inode in the parent TreeInode.

However, it isn't safe for a child Inode to access the TreeInode::Entry owned
by its parent.  This Entry object is supposed to be protected by the parent
TreeInode's contents_ lock, and the child inode never held this when accessing
the Entry.

This updates the TreeInode code to never use entry_ any more.  I will work on
removing FileInode::entry_ in a subsequent diff.

This did require changing the overlay materialization code some.  Previously
the checkout code directly modified entry_ to inform the parent TreeInode if
the child was materialized or not.  Now we have to more explicitly tell the
parent TreeInode about changes to each child's materialization state.  With
this change we now keep the overlay data on disk more consistent during the
checkout process.  We should now always have overlay data for children inodes
on disk whenever the parent thinks they are materialized.  We may end up
writing out TreeInode overlay data frequently during the checkout process,
however.  We might be able to improve this in the future.  For now it seemed
simpler and safer to just update the data frequently to make sure it stays
consistent.

Reviewed By: bolinfest

Differential Revision: D4688055

fbshipit-source-id: d08a14b9304ac49826f0897a0b53281177d9d9f4
2017-03-10 18:29:29 -08:00
Adam Simpkins
a13d55796c delay removing overlay data until inodes are completely unreferenced
Summary:
Update the code so that we no longer immediately remove overlay data about a
file or directory when the inode is unlinked.  The file can continue being used
after it was unlinked if there are open file handles or other internal
references to it.

This updates the code to instead wait to remove the overlay data until the
InodeBase object is unloaded.

This does not fully fix all the outstanding issues with using inodes after they
have been unlinked, because the FileInode and TreeInode still use the entry_
pointer that now points to a bogus TreeInode::Entry.

Reviewed By: bolinfest

Differential Revision: D4688056

fbshipit-source-id: a9e1c1a9562590b8b81237057bfc4ef77795807f
2017-03-10 18:29:29 -08:00
Adam Simpkins
2369f6f810 address some issues with materializing inodes
Summary:
This changes a couple aspects of the materialization process:

- Write out child files in the overlay before their parent.  If we throw an
  exception or crash partway through this process, it is better to have the
  child not marked materialized in its parent, rather than to have the parent
  indicate that the child is materialized but to not actually have any overlay
  data for the child.  In the former case we will still load the correct child
  data the next time we need to, but in the latter case we would fail to load
  the child correctly.

- Hold the rename lock while materializing our parent directories, to ensure
  that we materialize the correct parent, and it cannot change while we are
  trying to perform the materialization.

- Make the parent responsible for modifying the child's TreeInode::Entry.  This
  data is owned by the parent and is protected by the parent's contents_ lock.
  The child really shouldn't ever be directly accessing this data without
  holding the parent's contents_ lock.

Reviewed By: bolinfest

Differential Revision: D4688057

fbshipit-source-id: 2662f79cb7d7febb086f4e0888a3d96a580c4bfa
2017-03-10 18:29:29 -08:00
Adam Simpkins
9980907d1e fix checkout to always report the specific list of files with conflicts
Summary:
This fixes the checkout code to always recurse into directories with conflicts,
and accurately list all individual files with conflicts.

Previously the checkout code always avoided recursing into unloaded directory
inodes that were affected by the checkout.  Since the inode was not loaded we
can easily replace it without recursing into it.  Unfortunately this resulted
in an inaccurate conflict list--we would report the directory itself as a
conflict.  This is insufficient for our mercurial extension, which needs to
know the specific list of files with conflicts, so it can ask mercurial to
perform conflict resolution on them.

Reviewed By: bolinfest

Differential Revision: D4672373

fbshipit-source-id: ff400a4a6e25b8b0754c66cb067a69d553a5c98b
2017-03-09 20:57:27 -08:00
Adam Simpkins
aec52ad41d update unlink() to load the child inode before removing it
Summary:
Loading the child inode is necessary to avoid race conditions with other
threads that may be currently trying to load the child inode in question.

This updates the code so that rmdir() and unlink() now share most of their
implementation.

Reviewed By: bolinfest

Differential Revision: D4664110

fbshipit-source-id: 871ca7b3c22819b24bc2639d9550bb45f6541f50
2017-03-08 17:09:36 -08:00
Adam Simpkins
02664c185f add more unit tests for checkout
Summary:
Replace the one very basic checkout unit test with several tests that
more thoroughly test file modification changes.  More tests for
directory changes and file type changes still need to be added, but this is a
first step for now.  I will continue adding more tests in upcoming diffs.

Reviewed By: wez

Differential Revision: D4641595

fbshipit-source-id: 443a68e4e3c673fe687446f3469f035b4f48f1b3
2017-03-02 14:24:10 -08:00
Adam Simpkins
dcf8e6a3a2 add an EdenMount::resetCommit() method
Summary:
Add a method to reset the current commit without changing the working
directory state, similar to "hg reset" and "git reset --soft".

This also adds a new EXPECT_FILE_INODE() check for use in the unit tests,
and FileInode::getPermissions() and FileData::readFull() methods to support
this check.

Reviewed By: wez

Differential Revision: D4641476

fbshipit-source-id: 1e516774fe8e292a8d82cc2c354619374a3abe37
2017-03-02 14:24:10 -08:00
Adam Simpkins
7100eecdaa additional refactoring of unit test initialization code
Summary:
The FakeTreeBuilder class in D4609587 provides a lot of the same functionality
as the TestMountBuilder class, but is not restricted to being used only at
mount initialization time.  (It also provides more powerful functionality for
controlling the ordering of events when loading data from the ObjectStore.)

This switches all of the existing tests to use FakeTreeBuilder rather than
TestMountBuilder, and removes the TestMountBuilder class.

One difference is that FakeTreeBuilder adds data to the FakeBackingStore, while
TestMountBuilder previously put data directly into the LocalStore.  This
shouldn't really make much difference for the behavior of the code.  Putting
data in the FakeBackingStore gives us more control over when data is available
during load operations, and exercises slightly more of the normal ObjectStore
code path.

Reviewed By: wez

Differential Revision: D4641288

fbshipit-source-id: ca2b45bf69bd373848c12a7b739b286aabe6aa9b
2017-03-02 14:24:10 -08:00
Adam Simpkins
4ac4d94cb8 add a FakeTreeBuilder class to make writing tests easier
Summary:
Add a FakeTreeBuilder class to make it easier to create Tree structures in the
FakeBackingStore using path names.  Previously the test code had to manually
chain together Trees and Blobs.  FakeTreeBuilder lets callers call setFile()
with a path name to define the file layout.  The files that were defined then
get converted into Tree and Blob data when finalize() is called.

This is similar to the existing TestMountBuilder::addFile() API.  However,
TestMountBuilder only populates the LocalStore.  FakeTreeBuilder populates
the FakeBackingStore instead.  The FakeBackingStore class allows tests to have
much more control about when objects appear ready from the backing store,
allowing control over the order in which Futures are fulfilled during the test.

Reviewed By: bolinfest

Differential Revision: D4609587

fbshipit-source-id: 9642d17daf0dc10f08901e51552bbb3c3e150b53
2017-03-02 14:24:10 -08:00
Adam Simpkins
ec85eb7ec7 fix warnings triggered with -Wshadow-compatible-local
Summary:
Make sure the eden coded compiles cleanly with -Wshadow-compatible-local

Pretty much all of the warnings were issues with lambdas shadowing names from
their parent context (even though they didn't ask to capture those names from
the parent).

Reviewed By: wez

Differential Revision: D4644849

fbshipit-source-id: 66629cd98b5af4760f3fbb256e44c0bc47e52316
2017-03-02 13:32:51 -08:00
Wez Furlong
c543f89404 add symlink support to the overlay
Summary:
Previously, we would only allow you to consume a symlink that was
checked into a revision, but not allow you to create a new one.

This diff adds support for making new symlinks.

It turns out that the code that we had for readlink had an unused code path for
reading an actual symlink out of the overlay.  My first pass at this diff tried
to make the materialization code generate such a symlink, but it was breakin
some other assumptions in the rest of the code.

This version of the code just stores the symlink target in the file contents.
This means that we can simplify readlink to just calling `readAll` on the
underlying file data, and that will load the contents out of the storage layer
if the file wasn't materialized.  This helps simplify things a bit more.

Reviewed By: bolinfest, simpkins

Differential Revision: D4604016

fbshipit-source-id: 3138d0f9880639d2bbeaf4bb03bef3f021c3ecb3
2017-03-02 08:18:45 -08:00
Wez Furlong
2fc9fc155c enable StreamingEdenService
Summary:
In order to send realtime subscription information to watchman
we need to use the thrift streaming data functionality.  Since this
isn't supported in java we originally broke this out into its own
thrift file.

It's now time to hook this up; this diff adds some plumbing so that
our thrift server knows to implement this interface.

This was made a bit more complicated because the inheritance in
the thrift definitions causes some ambiguities in the header maps
that buck uses to manage the includes.

I also had to rename the file from `eden.stream.thrift` to `streamingeden.thrift`
to avoid a problem with the period in the middle of the identifier.

For the server side of things, I've removed the `:thrift-cpp2` target
and replaced it with `thrift-streaming` instead.

This diff doesn't implement the endpoint, it is just setting things
up for the follow-on diff that does.

Reviewed By: bolinfest

Differential Revision: D4640639

fbshipit-source-id: b3625b0ff33a42945bf523944beed050f549a18c
2017-03-01 23:12:50 -08:00
Adam Simpkins
09006d0e4a Drop AutoHeaders.RECURSIVE_GLOB from TARGETS files
Summary:
Remove AutoHeaders.RECURSIVE_GLOB from all of our TARGETS files.  This is a
Facebook-internal directive that was added as part of a codemod.  The vanilla
open source buck does not know about this directive, and can't parse TARGETS
files that contain it.

All of the affected rules are cpp_unittest() and cpp_binary() rules that don't
actually have any header files, so these parameters didn't actually have any
effect.

Reviewed By: andrewjcg

Differential Revision: D4633748

fbshipit-source-id: 6227fe9b7f2ea838a0c72408ca195685bcae9f5a
2017-02-28 21:46:39 -08:00
Adam Simpkins
0515c8c6a4 fix a bug incrementing the wrong index during TreeInode checkout
Summary:
In TreeInode::computeCheckoutActions() the code incremented the wrong index
when we reached the end of the new tree before the old tree.

panda-facepalm

Reviewed By: bolinfest

Differential Revision: D4609906

fbshipit-source-id: 61ca6baabe4eebb033c48b742562558466a45104
2017-02-23 18:29:41 -08:00
Adam Simpkins
b766aba11c invalidate the FUSE cache properly during checkout
Summary:
Invalidate directory entries as they are modified during the checkout
operation.  We never need to invalidate inode contents, since we always update
files by replacing the file with a new inode.

Reviewed By: wez

Differential Revision: D4577942

fbshipit-source-id: afde3040960b076d2cd384301a89cd7bdfce5a6a
2017-02-22 18:37:42 -08:00
Adam Simpkins
82d8d57ea7 handle forced checkout of newly added files with conflicts
Summary:
This updates CheckoutAction to make the old TreeEntry object optional.
This is necessary to support situations where the entry did not exist in the
old source control tree, but does exist in the new tree and also exists locally
on the file system.  This situation is always a conflict, so it only applies
when a force checkout is being done.

This diff also refactors the TreeInode::computeCheckoutActions() logic to
combine the processNewEntry/processRemovedEntry/processEntry lambdas into a
single function, as suggested in the code review for D4538516.

Reviewed By: wez

Differential Revision: D4577924

fbshipit-source-id: 9435205b541a12c75a8b9bd2b2b599a339a2f6c8
2017-02-22 12:21:48 -08:00
Adam Simpkins
186867b8d2 remove the remaining calls to getPathBuggy()
Summary:
Fix the FileHandle code that was calling getPathBuggy() when writing journal
entries.  This fixes a crash when writing to an unlinked file.

Also remove an unused call to getPathBuggy() in TreeInodeDirHandle.

These were the last places calling getPathBuggy(), so I have now deleted this
method entirely.

Reviewed By: bolinfest

Differential Revision: D4570606

fbshipit-source-id: a1c4aab10df96e2aeee78fca6d5808db28ad0cbf
2017-02-17 18:44:32 -08:00
Adam Simpkins
0687431924 implement EdenMount::checkout()
Summary:
This is the initial code for implementing checkout.

This isn't quite 100% implemented yet, but I think it's worth checking in this
code as-is, and getting the remaining functionality done in separate diffs.
In particular, a few operations aren't implemented:
- Removing a directory that was deleted in the new revision
- Replacing a directory that was replaced with a file or symlink in the new
  revision
- When doing a forced update, replacing a file or directory that did not exist
  in the old revision, but that was created locally in the working directory,
  and also exists in the new revision.

Reviewed By: wez

Differential Revision: D4538516

fbshipit-source-id: 5bb4889b02f23ab2048fcae2c8b7614340181aa6
2017-02-15 20:33:31 -08:00
Adam Simpkins
fed342da30 store overlay files using inode numbers instead of paths
Summary:
Refactor the Overlay code to store data using inode numbers rather than the
affected file's path in the repository.  This simplifies the TreeInode code a
bit, as we no longer have to rename overlay files to stay in sync with the file
paths.  This also eliminates some crashes when trying to update overlay files
for inodes that have been unlinked (and hence no longer have a path).  This
also includes a few fixes to avoid writing journal entries for unlinked files
too.  Additionally this contains a few fixes to how mode bits are stored in the
overlay, and fixes a bug where create() was ignoring the mode argument.

Reviewed By: wez

Differential Revision: D4517578

fbshipit-source-id: c1e31497dcf62c322b0deff72b0a02675b0509ab
2017-02-10 14:17:52 -08:00
Adam Simpkins
6920577f4a remove TreeInode::getInode()
Summary:
InodeBase::getNodeId() already returns the inode number, so there is no need
for the TreeInode subclass to provide an alternatively-named method that does
the same thing.

Reviewed By: bolinfest

Differential Revision: D4500215

fbshipit-source-id: fbc595cf9e8f43efe44ed352a97e3a4974b5aed0
2017-02-10 13:36:52 -08:00
Adam Simpkins
8b4c984b28 always load affected inodes in rename(), and update lock ordering
Summary:
This updates the TreeInode::rename() code to handle concurrency better.
In particular:

- The code now ensures that both the source inode being renamed and destination
  inode (if it exists) are loaded.  This simplifies issues when an inode is
  being loaded at the same time a rename is in progress.  This ensures that any
  pending load is processed before the rename takes place.  (All promises for
  the load might not be fulfilled before the rename completes, but the relevant
  TreeInode and InodeMap data structures are updated before the rename occurs.)

  This does mean that the rename code potentially might have to retry several
  times if the inode it began loading is no longer the affected source or
  destination or child once the load completes.  However, this seems like a
  reasonable trade-off, compared to dealing with the complications that would
  arise with the load code having to handle renames occuring before load
  completion.

- The code now implements proper lock ordering, to avoid acquiring locks in
  conflicting orders that might cause deadlock with other threads also trying
  to acquire the same locks.  The InodeLocks.md document has been updated to
  clarify the TreeInode lock ordering requirements.

Reviewed By: wez

Differential Revision: D4493526

fbshipit-source-id: 627393fafad90eb551aea62be7762d59ed043abe
2017-02-03 18:35:03 -08:00
Adam Simpkins
19a1d3c6b6 make sure FileData always open the overlay file for materialized files
Summary:
Most of the FileData logic assumes that file_ is open if the file is
materialized.  Fix the FileData() constructor to actually open file_ if the
entry is marked materialized, so that this assumption is actually true.

Reviewed By: wez

Differential Revision: D4471365

fbshipit-source-id: b399e6e5e25eaf12f4204f5835db01baa5a6cd78
2017-01-31 13:33:57 -08:00
Adam Simpkins
4a6aaa5de4 load all materialized inodes when starting a mount point
Summary:
As part of the mount process, make sure we load InodeBase objects for all files
in the mount that are already materialized.

Other parts of the code assume that InodeBase objects are always loaded for
materialized files.  We never unload materialized inodes, but if the mount
point was unmounted then remounted we previously did not ensure to load the
materialized InodeBase objects.  This diff makes sure we load all materialized
inodes before starting the mount.

Reviewed By: bolinfest

Differential Revision: D4461193

fbshipit-source-id: 70d06fd01e2df333ce2816d5d7a392b0a5d6e1e6
2017-01-25 16:56:12 -08:00
Adam Simpkins
f8042c24d4 clean up some subtle issues with inode loading completion
Summary:
Fix two issues with inode load completion:

1) Make sure we release the parent's TreeInode lock before fulfilling promises
waiting on the inode load to complete.  Otherwise this can result in deadlock
if the promises have callbacks that then try to acquire the TreeInode lock.

2) Use unique_ptr<InodeBase> in the load completion code before we have
inserted the Inode into the InodeMap, rather than using InodePtr.  The new
InodePtr class relies on the InodeMap to handle ownership, and it cannot
destroy Inode objects unless they are in the InodeMap.  Using a unique_ptr
instead ensures that the InodeBase will be destroyed properly if an error
occurs between when we construct the InodeBase and when we insert it into the
map.

Reviewed By: bolinfest

Differential Revision: D4427889

fbshipit-source-id: 2627a4956735f4acebe5c259abd8de0430ff6177
2017-01-25 16:56:12 -08:00
Adam Simpkins
d1556c3601 implement Future-based recursive Inode lookup
Summary:
Rename the current EdenMount::getInodeBase() function to
EdenMount::getInodeBaseBlocking() and add a new getInodeBase() function that
performs the lookup asynchronously and returns a Future<InodePtr>.

This is implemented with a TreeInode::getChildRecursive() function that allows
asynchronous recursive lookups at any point in the tree.

Reviewed By: bolinfest

Differential Revision: D4427855

fbshipit-source-id: aca55e681a48c848b085b7fc6a13efe6cf0a4e3a
2017-01-25 16:56:12 -08:00
Adam Simpkins
20aaa1e2b8 Add InodeBase::getParent()
Summary:
Add methods to InodeBase to get the parent of the current Inode, and remove the
existing TreeInode::getParent() function.  The old TreeInode parent_ member was
never updated properly after rename or unlink operations, so it could return
incorrect information.

Reviewed By: bolinfest

Differential Revision: D4427103

fbshipit-source-id: cb66a014f745b4af31033e0a3c5405e29791b869
2017-01-25 15:06:05 -08:00
Wez Furlong
1e0397db50 raise the attribute TTL to maximum possible, add basic invalidation
Summary:
Thesis: Since we don't yet have `hg update` implemented, these attributes can be cached forever.

When we implement `hg update` we will explicitly inform the kernel to invalidate anyway.

... and it turns out that the `scmRemove` thrift call is making changes that
aren't visible to the kernel already so we need to hook up some basic
invalidation.

This diff includes the bare minimum code to facilitate this; I've added a
helper method to the fusell::RequestData class to test whether we are in the
context of a FUSE request.

In the EdenDispatcher::unlink method we need to explicitly invalidate if we are
not being called via FUSE.

I have mixed feelings about putting this code in here.  Given the initial
mental model I had in the prototype, this is the right place to put it, but it
does mean that all tree mutations must have via the Dispatcher in order for
invalidations to be routed to the correct places.  Do we want to move away from
this?

It wouldn't be the end of the world to expand this diff a bit to add
similar/appropriate invalidation calls to all the mutation methods in our
dispatcher implementations while we figure out if we want to keep this.

Reviewed By: simpkins

Differential Revision: D4452961

fbshipit-source-id: 9471f145242fce0620c6872b74b02c56c8d78af1
2017-01-24 09:39:06 -08:00
Adam Simpkins
251da81f36 update all copyright statements to "2016-present"
Summary:
Update copyright statements to "2016-present".  This makes our updated lint
rules happy and complies with the recommended license header statement.

Reviewed By: wez, bolinfest

Differential Revision: D4433594

fbshipit-source-id: e9ecb1c1fc66e4ec49c1f046c6a98d425b13bc27
2017-01-20 22:03:02 -08:00
Adam Simpkins
09e9aa0819 add a mountpoint-wide rename lock
Summary:
This lock protects all operations that change the location of existing inodes
(rename(), unlink(), and rmdir()).  This is needed to avoid race conditions
during rename operations.

I also included some FIXME comments about properly updating location
information for unloaded inodes.  These should be taken care of in a subsequent
diff.

Reviewed By: wez

Differential Revision: D4361197

fbshipit-source-id: 5aaa1b8250f196b23207be8f3c0fd7f2603e6ae8
2017-01-17 15:03:20 -08:00
Adam Simpkins
a598e8c334 implement Inode unloading
Summary:
This updates the InodePtr and InodeBase code to actually implement Inode
unloading and destruction.

At the moment we keep Inode objects as long as possible, and only unload them
during shutdown, or when the last reference to an unlinked inode goes away.
However, it should be straightforward to add on-demand unloading in the future
for Inodes that have not been accessed in a while.  The
TreeInode::unloadChildrenNow() function provides a template for what this would
look like (it would simply need to be changed to check an access time when
doing on-demand unloading).

Reviewed By: wez

Differential Revision: D4360765

fbshipit-source-id: a46b355f0ac0c25f873a156e62af5184317de735
2017-01-17 15:03:20 -08:00
Adam Simpkins
0237a0c56d add an EdenMount::destroy() function
Summary:
Update EdenMount so that it cannot be destroyed directly, and must be destroyed
through a special destroy() function.  This function is not implemented yet,
but it will delay actual destruction of the EdenMount until all Inode objects
in the mount have been destroyed.

This diff primarily updates the users of EdenMount to call destroy() properly.
I will send a subsequent diff that implements destroy() at the same time as
implementing Inode unloading.

Reviewed By: wez

Differential Revision: D4360558

fbshipit-source-id: 202826b63b75e1de2b73270806da094206108a47
2017-01-17 15:03:20 -08:00
Adam Simpkins
3a73253057 add new InodePtr classes
Summary:
This defines our own custom smart pointer type for Inode objects.  This will
provide us with more control over Inode lifetime, allowing us to decide if we
want to unload them immediately when they become unreferenced, or keep them
around for a while.

This will also allow us to fix some memory management issues around EdenMount
destruction.  Currently we destroy the EdenMount immediately when it is
unmounted.  This can cause issues if other parts of the code are still holding
references to Inode objects from this EdenMount.  Our custom InodePtr class
will also allow us to delay destroying the EdenMount until all of its Inodes
have been destroyed.

This diff adds the new pointer types and updates the code to use them, but does
not actually implement destroying unreferenced inodes yet.  The logic for that
has proven to be slightly subtle; I will split it out into its own separate
diff.

Reviewed By: wez

Differential Revision: D4351072

fbshipit-source-id: 7a9d81cbd226c9662a79a2f2ceda82fe2651f312
2017-01-17 15:03:20 -08:00
Andrew Gallagher
bd862c50e5 codemod: fixup more build targets in TARGETS
Summary:
Ran script from:
differential/diff/21475830/

Reviewed By: Gownta

Differential Revision: D4419263

fbshipit-source-id: 7631ea2c2cb3b6e27756ecc9da9e492b2a3b2dab
2017-01-14 01:44:01 -08:00
Nick Wolchko
0aa6855557 Remove folly::Future conversion constructor
Summary:
This constructor is unsafe. The check it uses before doing the comparison isn't a safe enough check to see if the cast is valid. For example, this is broken in the presence of multiple inheritance because it doesn't adjust the pointer offset to the correct vtable.

e.g.
  struct A {
    virtual ~A() {};
    virtual void doSomething() = 0;
  };
  struct B {
    virtual ~B() {}
    virtual void doSomethingElse() = 0;
  };
  struct C : public B, public A {
    virtual ~C() {}
    void doSomething() override {
      std::cout << "Something!" << std::endl;
    }
    void doSomethingElse() override {
      std::cout << "Something Else!" << std::endl;
    }
  };
  int main (int argc, char **argv) {
    auto c = folly::makeFuture<std::shared_ptr<C>>(std::make_shared<C>());
    folly::Future<std::shared_ptr<A>> a = std::move(c);
    a.get()->doSomething();
    return 0;
  }
This code will print "Something else!" when run.

Reviewed By: siyengar

Differential Revision: D3679673

fbshipit-source-id: dcbf40ca82d458f17ee11191591f8b8daf58c919
2017-01-09 09:21:57 -08:00
Adam Simpkins
a5a0563fd3 add log statements to EdenDispatcher
Summary:
Add VLOG() statements for every FUSE entry point.  Turning up the VLOG level in
EdenDispatcher now allows us to have a record of all FUSE calls made using
inode numbers.  (Calls involving file handles or directory handles currently go
directly to the handle in question and do not pass through the EdenDispatcher.
We should probably add log statements for those too, but that can wait for a
later diff.)

Reviewed By: bolinfest

Differential Revision: D4359066

fbshipit-source-id: b378d829c39fdb61faf63d2d400f3ff556c376e8
2016-12-22 18:13:02 -08:00
Adam Simpkins
3e41ecaa26 Remove FileInode::parentInode_
Summary:
This member variable was not updated properly when files were renamed.
InodeBase now tracks our parent properly, so we don't need our own copy.

This does still call getParentBuggy() (which does not perform proper locking)
in a couple places for performing overlay operations.  We'll need to fix this
later when addressing other overlay concurrency handling issues.

Reviewed By: bolinfest

Differential Revision: D4348481

fbshipit-source-id: 19c1ffced6f63e1ff041d0bab2363fecdb93d5a3
2016-12-22 15:36:29 -08:00
Adam Simpkins
9ba08b9d1e Update FileData to store a pointer to its FileInode
Summary:
Have FileData objects store a pointer to the FileInode that owns them, rather
than just to the EdenMount.

FileData objects still store a direct pointer to their FileInode's mutex_ and
entry_.  It's potentially worth just accessing these through inode_ in the
future.

Reviewed By: bolinfest

Differential Revision: D4348103

fbshipit-source-id: 1f8497979bfc89c6a192ca0195209335db0d911c
2016-12-22 15:36:29 -08:00
Adam Simpkins
0156f01d51 Update InodeBase to contain a pointer to its EdenMount
Summary:
Add an EdenMount* member variable to InodeBase.  Previously each TreeInode kept
a pointer to its EdenMount, and this moves that into the InodeBase class.

This is needed to support upcoming diffs that will change InodeBase memory
management.  InodeBase objects will be responsible for notifying the InodeMap
when they become unreferenced.

Reviewed By: bolinfest

Differential Revision: D4348079

fbshipit-source-id: 6bf7ea908c6096aa2bca5b21290c09cbd58d5af7
2016-12-22 15:36:29 -08:00
Adam Simpkins
5b346bbff2 update code to use InodeMap
Summary:
This updates all of the eden code to use the new InodeMap class.  This replaces
the InodeNameManager class and the unordered_map previously stored in the
EdenDispatcher.

Reviewed By: bolinfest

Differential Revision: D4325750

fbshipit-source-id: d80ae7581ba79ca2b63155e184995a3e83e85dc1
2016-12-22 15:36:29 -08:00
Adam Simpkins
435a0ca2a1 introduce a new InodeMap class
Summary:
This diff starts adding a new InodeMap class.  This class will eventually
consolidate the functionality of InodeNameMap plus the inode map stored in
EdenDispatcher.

This new class will bring several new benefits:

- All inode mapping logic consolidated into a single class, with a single lock
  protecting the maps.
- A well-defined model for loaded vs unloaded inodes.  InodeMap explicitly
  tracks inodes that have InodeBase objects created for them vs inodes that
  have an inode number allocated (for FUSE) but do not have an InodeBase object
  in memory.  This will make it possible to unload Inode objects on demand to
  reduce memory usage.
- Tracking of pending loads, and de-duplicating load requests.  This ensures
  that only one Inode object ever exists for a given inode number / path.  If a
  second request to load an Inode arrives when a previous load request is still
  in progress, InodeMap deals with this situation properly.
- Better support for using Inode objects without FUSE.  With the old code,
  attempts to interact with Inode objects without going through the FUSE
  dispatch (say, when processing a thrift call) could result in inconsistent
  state.  New inodes created would not be put into the EdenDispatcher map,
  which could result in problems.
- More convenient child inode access from TreeInode.  With this change, the
  TreeInode class can easily tell which of its children are loaded.  This makes
  it easier to do tasks which only need to operate on existing loaded inode
  state (for instance, dirstate computation).
- Support for saving and loading state, to implement graceful restart..
  InodeMap provides a central place to write out inode state on shutdown and
  restoring it on startup.  Saved inodes can easily be restored to an
  "unloaded" state on startup.  This code is not implemented yet as part of
  this diff, but it should be straightforward to add in future diffs.

Reviewed By: bolinfest

Differential Revision: D4318060

fbshipit-source-id: d9b16430fc8367e3516e788d1e991e5163aa6997
2016-12-22 15:36:29 -08:00
Michael Bolin
3f2f22d8fa Normalize build targets to always start with //.
Summary:
We can use `//` exclusively because we always build Eden with Buck and never
fbbuild, our legacy build system for fbcode.

This revision was initially created by running:

```
find eden -name TARGETS | xargs sed -i -e 's#@/#//#g'
```

And then manually updating the `DEFS` file now that we no longer need
some normalization code for an outdated pattern.

But then I got annoyed by other inconsistencies, so I went through and
alpha-sorted some lists, replaced all double quotes with single quotes,
and fixed indents to be two spaces.

Reviewed By: simpkins

Differential Revision: D4356724

fbshipit-source-id: ab07a48f12fa937c257213d12331efdf09e42da6
2016-12-21 16:28:02 -08:00
Michael Bolin
1ea4af26c5 Use the StatusCode from Thrift as the canonical representation.
Summary:
Most of the work for this diff was achieved via:

```
find eden -type f | xargs sed -i -e 's#ThriftHgStatusCode#StatusCode#g'
find eden -type f | xargs sed -i -e 's#HgStatusCode#StatusCode#g'
```

Reviewed By: simpkins

Differential Revision: D4237975

fbshipit-source-id: 2ee04a89101291c8972ac7bd3ff6cca92cbb0799
2016-12-16 17:49:05 -08:00
Michael Bolin
dfd1634170 Move batch processing of hg add <directory> to the server.
Summary:
This should make the common case of `hg add` or `hg add .` much more efficient
because it no longer performs a walk of the entire repository from the client
side.

Reviewed By: simpkins

Differential Revision: D4317871

fbshipit-source-id: 7061553fe0de0c4afa84b4f835316965088675e8
2016-12-15 13:02:38 -08:00
Adam Simpkins
0656a70c23 fix the build with gcc
Summary:
This code compiled fine with clang, but gcc apparently requires explicitly
specifying "this->" when referring to members inside a lambda body.

Reviewed By: bolinfest

Differential Revision: D4332357

fbshipit-source-id: 3919dad4fca0b6676731f21781331be73fde8e55
2016-12-15 10:38:30 -08:00
Adam Simpkins
f8930c5325 fix Dispatcher::symlink() API
Summary:
Fix Dispatcher::symlink() to accept the symlink contents as a StringPiece
rather than a PathComponentPiece.  symlink contents can be any arbitrary
string, and are not required to be a valid, normalized path name.

Reviewed By: wez

Differential Revision: D4325380

fbshipit-source-id: 88448bee50ea192c06442dc70042c7d17d49a12f
2016-12-14 15:36:11 -08:00
Adam Simpkins
007726931b add a new InodeError class
Summary:
InodeError is a subclass of std::system_error that accepts an InodePtr to the
inode that it refers to.  This makes it easier to construct error objects that
retain information about the inode they refer to.

InodeError also avoids computing the inode path until the error message is
actually needed.  This should make it less expensive in cases where errors are
thrown and handled internally without ever using the human-readable error
message.  It is possible that the file may have been renamed or unlinked by the
time the error message is computed.  However, this race condition might still
exist even if we computed the path at the time when the error is constructed.
getLogPath() will construct a usable human-readable string even if the file has
been unlinked.

Reviewed By: wez

Differential Revision: D4325043

fbshipit-source-id: c9683a80b022f281ca4583a9b7f73b15277335bb
2016-12-14 15:36:11 -08:00
Adam Simpkins
fc202f81e5 add new Future-based APIs to ObjectStore
Summary:
Update the ObjectStore and BackingStore classes to have APIs that return
folly::Future objects, rather than blocking until the requested data is loaded.

For now most users still call the blocking versions of getBlob() and getTree().
Furthermore, all of the Future-based implementations actually still block
until the data is ready.  I will update the code to use these new APIs in
future diffs, and then deprecate the non-future based versions.

Reviewed By: bolinfest

Differential Revision: D4318055

fbshipit-source-id: a250c23b418e69b597a4c6a95dbe80c56da5c53b
2016-12-13 18:12:21 -08:00
Michael Bolin
5e08c5e1a7 Introduce Dirstate::getStatusForDirectory().
Summary:
This will make it easier to implement `hg add <directory>` such that
`<directory>` is expanded on the server rather than on the client.

Reviewed By: simpkins

Differential Revision: D4318735

fbshipit-source-id: cf0e89bd95eb58304cd23e70beb77bc7151f2c5c
2016-12-13 12:00:22 -08:00
Michael Bolin
3196a05b86 Filter .hg directory on the server when computing getStatus().
Summary:
Previously, `.hg` entries were filtered when calling `hg status` on the client,
but this should be happening on the server. This updates the logic in
`Dirstate.cpp` to properly exclude `.hg` when traversing the overlay for
modified directories, so this will eliminate a bunch of unnecessary computation
and simplify the client.

I'm unsure of how best to implement the ownership relation for the set that
contains `.hg`. Please advise! I know that I could categorically exclude
`".hg"` in `getModifiedDirectoriesRecursive()`, but I haven't used it enough
scenarios yet to be sure that's the right thing to do. For example, if it were
a Git repo, arguably we should consider `.hg` and not `.git`, so I could also
require the set to be a parameter of `Dirstate`, but I want to make sure I get
the ownership stuff right.

Reviewed By: simpkins

Differential Revision: D4316531

fbshipit-source-id: a0f13ca1c3c620b686435c8aa6485ba4e850f043
2016-12-13 12:00:22 -08:00
Michael Bolin
1619acb2c7 Change getModifiedDirectoriesForMount() to return a vector instead of a unique_ptr.
Summary: Follow-up on a comment that came out of the review for D4249214.

Reviewed By: simpkins

Differential Revision: D4314979

fbshipit-source-id: 76384474092e6fd48394f6faf8b84ba6220c556a
2016-12-13 12:00:22 -08:00
Adam Simpkins
c81ee4c997 update getSha1ForBlob() to return the Hash by value
Summary:
Hash objects are small enough (20 bytes) that it isn't worth allocating them on
the heap.  This updates LocalStore::getSha1ForBlob() to return a
folly::Optional<Hash>, and ObjectStore::getSha1ForBlob() to return a plain
Hash.

Reviewed By: bolinfest

Differential Revision: D4298162

fbshipit-source-id: 9cf54f2997ba8c3b2346db315a2aca41e580b078
2016-12-12 17:50:36 -08:00
Adam Simpkins
89fb0f811b add InodePtr, TreeInodePtr, and FileInodePtr type names
Summary:
Define InodePtr, TreeInodePtr, and FileInodePtr as aliases for std::shared_ptr
of the underlying inode type.  This also updates all of the code to use these
new type names.

This will make it easier swap out std::shared_ptr with a custom pointer type in
the future.  (I believe we will need a custom type in the future so that we
can have more precise control of the reference counting so we can load and
unload Inode objects on demand.  std::shared_ptr::unique() doesn't quite
provide the flexibility we need, and is also being deprecated in C++17.)

Reviewed By: bolinfest

Differential Revision: D4297791

fbshipit-source-id: 1080945649290e676f62689592159f1166159b20
2016-12-12 17:50:35 -08:00
Adam Simpkins
e7b2e8bd52 update InodeBase to track its path
Summary:
This updates the InodeBase code to track its location in the filesystem.
Since we do not support hard links, each inode has a single path where it
exists.

Tracking this data allows us to implement getPath() as a method of InodeBase.

This code is not really complete yet, but it seems worth getting the current
code in as-is.  The location data is not updated properly on unlinks or
renames, but it looks like the existing InodeNameManager code does not get
updated either.  I am working on some additional refactoring of inode object
management, and it will be easier to come back and fix the unlink and rename
handling after this refactoring is further along.

Reviewed By: bolinfest

Differential Revision: D4297591

fbshipit-source-id: 82ceb326e4f9c376f627b1d8f49bb7db3cfc2b0b
2016-12-12 17:50:35 -08:00
Michael Bolin
309d0da769 Make it possible to make a commit from Eden.
Summary:
In this revision, we override `committablectx.markcommitted()` to make a Thrift
call to Eden to record the new commit. For now, this defers the need for us to
implement `edendirstate.normal()`, though we expect we will have to provide a
proper implementation at some point.

Because `hg update` is not implemented yet, this puts us in a funny state where
we have to restart eden after `hg commit` to ensure all of our `TreeEntry` and
other in-memory data structures are in the correct state.

Reviewed By: simpkins

Differential Revision: D4249214

fbshipit-source-id: 8ec06dfee67070f008dd93a0ee6c810ce75d2faa
2016-12-10 01:07:06 -08:00
Michael Bolin
d60888d210 Support hg remove <directory>.
Summary:
This refines the initial support for `hg remove` by adding support for
directories.

Reviewed By: simpkins

Differential Revision: D4270546

fbshipit-source-id: c97dfea555ad489ddda01ad2587f1856b1953e02
2016-12-09 19:36:17 -08:00
Michael Bolin
017b35bca6 Add support for hg remove for an individual file.
Summary:
This adds support for `hg remove <file>` in Eden and sets up some of the scaffolding
to support `hg remove <directory>`.

Note that the Thrift API for `scmRemove()` is slightly different than that of `scmAdd()`
in that it returns a list of error messages to display to the user rather than throwing
an exception. In practice, for batch operations, Mercurial will allow some operations
to succeed while others may fail, so it is possible to have multiple error messages to
return.

Unlike the current implementation of `hg add`, this does the directory traversal
on the server rather than on the client. Once we work out how to do this for
`hg remove`, we should figure out how to reuse the logic for `hg add`.

Reviewed By: simpkins

Differential Revision: D4263068

fbshipit-source-id: d084774d562c48c59664f313eba229d4197929fe
2016-12-09 19:36:17 -08:00
Michael Bolin
ab750945fe Fix an edge case in hg remove handling.
Summary:
The check on the type of an exception was inverted, which meant
`hg remove <path>` would throw an exception if the parent directory of `path`
did not exist. This is not correct because the user should be able to expect
to do:

```
mkdir -p /tmp/example
cd /tmp/example
hg init
mkdir mydir
touch mydir/a
hg add mydir/a
rm -rf mydir/a
hg rm mydir/a
```

In this scenario, `mydir` does not exist when `hg rm` is called, but the command
should succeed, making `mydir/a` no longer tracked.

Reviewed By: simpkins

Differential Revision: D4268451

fbshipit-source-id: 517d81252aa8e4b6bd1a32dece14776a9f7dd6f7
2016-12-09 16:11:59 -08:00
Michael Bolin
c58ab82952 Ignore "group" and "other" bits of mode_t when diff'ing tree entries.
Summary:
A `TreeEntry` reports a `mode_t` whose "group" and "other" bits are set in a way
that reflects the "owner" bits (so they are non-zero). By comparison, the `mode`
of a `TreeInode::Entry` will reflect the permissions on disk in the overlay (if
the file is materialized). In general, the overlay bits will probably be the
same as those in the `TreeEntry` since we expect the user will rarely mess
with the "group" and "other" bits, but we're seeing a difference more often
right now because of t14953681.

Reviewed By: simpkins

Differential Revision: D4298214

fbshipit-source-id: 2919be94c6bba61135838ee86bbc68aa4031af7c
2016-12-09 15:42:04 -08:00
Adam Simpkins
da04640287 move InodeBase from eden/fuse to eden/fs/inodes
Summary:
Move the InodeBase class from the lower-level fusell code up to the
eden/fs/inodes layer, now that everything else that uses it is in
eden/fs/inodes.

I plan to start changing the ownership model of inode objects a bit, and this
will allow the InodeBase class to interact with EdenDispatcher and other
classes in eden/fs/inodes.

Reviewed By: bolinfest

Differential Revision: D4283392

fbshipit-source-id: 9e1d6fb81dc223f905847cbe8d165a40ad0aca4d
2016-12-07 20:05:20 -08:00
Adam Simpkins
f9a99e0ba1 remove fusell::DirInode and fusell::FileInode
Summary:
Now that the EdenDispatcher class has been moved into eden/fs, we no longer
need the distinction between TreeInode and fusell::DirInode, and FileInode and
fusell::FileInode.

This diff deletes the fusell versions of these classes, and updates all of the
code to always directly use TreeInode and FileInode.  This allows us to get rid
of the remaining dynamic_casts between these pairs of classes.

Reviewed By: bolinfest

Differential Revision: D4257165

fbshipit-source-id: e2b6f328b9605ca0e2882f5cf7a3983fb4470cdf
2016-12-01 17:52:31 -08:00
Adam Simpkins
2a08798f88 move InodeDispatcher from eden/fuse to eden/fs
Summary:
Move the InodeDispatcher class out of the lower-level fusell namespace in
eden/fuse and into the higher-level eden code in eden/fs/inodes.  I also
renamed it from InodeDispatcher to EdenDispatcher, in anticipation of it
getting more eden-specific functionality in the future.

The fusell::MountPoint class is now independent of the Dispatcher type, and can
work with any Dispatcher subclass.  Previously the MountPoint class was
responsible for owning the InodeDispatcher object.  Now its caller (EdenMount
in our case) is responsible for supplying a Dispatcher object that is owned
externally.

Several parts of EdenDispatcher had to be updated as a result of the namespace
move, but I tried to keep this change somewhat minimal.  I did update it from
using fusell::DirInode and fusell::FileInode to eden's TreeInode and FileInode
classes directly.  However, there still remains more clean-up work to do.  I
will split remaining changes out into upcoming diffs.

Reviewed By: bolinfest

Differential Revision: D4257163

fbshipit-source-id: dc9c2526640798f9f924ae2531218ba2c45d1d0a
2016-12-01 17:52:31 -08:00
Adam Simpkins
bf252cb3e9 eliminate MountPoint::setRootInode()
Summary:
Drop the MountPoint::setRootInode() method, and have EdenMount perform the
operation directly on the InodeDispatcher.

Reviewed By: bolinfest

Differential Revision: D4257158

fbshipit-source-id: af4a696de2d36979c658972104361f225f482338
2016-12-01 17:52:31 -08:00
Adam Simpkins
fc29bccd78 move InodeNameManager access to EdenMount
Summary:
Update call sites in eden/fs to access the InodeNameManager through the
EdenMount object rather than the MountPoint.

It turns out that there was only one call site in TreeInode, and all other
callers in eden/fs get it indirectly via TreeInode::getNameMgr().

Reviewed By: bolinfest

Differential Revision: D4257156

fbshipit-source-id: 9f0212134b20c8dd8943827c17aa16ee7274bc36
2016-12-01 17:52:31 -08:00
Adam Simpkins
0af5d187c2 move MountPoint::getInode* methods into EdenMount
Summary:
Move getInodeBaseForPath(), getDirInodeForPath(), and getFileInodeForPath()
entirely into the EdenMount class, and make sure all call sites are using the
EdenMount methods rather than the MountPoint methods.

Reviewed By: bolinfest

Differential Revision: D4257153

fbshipit-source-id: d528cfad174757c3c9f23e62a0616f8bf1976da7
2016-12-01 17:52:31 -08:00
Adam Simpkins
f0082e9178 call EdenMount::getDispatcher() and EdenMount::getRootInode()
Summary:
Update all code in eden/fs to call EdenMount::getDispatcher() instead of
getting the underlying MountPoint from the EdenMount and then calling
getDispatcher() on it.  This will allow me to move the InodeDispatcher from
MountPoint to EdenMount in a subsequent diff.  This also simplifies many of the
callers of this method.

Additionally, add an EdenMount::getRootInode() method, and update call sites to
use this rather than having to look up the InodeDispatcher and call
getRootInode() or getDirInode(FUSE_ROOT_ID) on it.

Reviewed By: bolinfest

Differential Revision: D4257152

fbshipit-source-id: 33e6f6b8853db2a88f4f2c221122eea50e796390
2016-12-01 17:52:31 -08:00
Adam Simpkins
1d00843bb3 short-term code for checking ignore status
Summary:
This updates the Dirstate to also check if untracked files are ignored or not.

This is somewhat inefficient, as we have perform a separate check for each
untracked file we find.  Ideally we should perform all of the dirstate
computation in a single tree walk, and check ignore status as we go.  This
would allow us to skip ignored directories entirely, rather than potentially
having to check each file inside them.  I intend to work on cleaning this up in
the future, but it will require refactoring some of the inode code first.

Reviewed By: bolinfest

Differential Revision: D4225308

fbshipit-source-id: 49e444c85cbb6ede11cc6e19052fdd16cf8aab9f
2016-12-01 17:52:30 -08:00
Adam Simpkins
74fa63d0d1 store a pointer to the EdenMount in the Dirstate
Summary:
Update the Dirstate to store a pointer to the EdenMount object that owns it,
rather than storing pointers to the lower-level MountPoint and ObjectStore
objects.

This change is necessary in order for me to move more functionality from
MountPoint to EdenMount.  (In particular, I plan to move the InodeDispatcher to
the EdenMount.)

As part of this change I also started moving some APIs from MountPoint to
EdenMount.  For now the EdenMount versions are just thin wrappers on top of the
MountPoint APIs.  I will move the functionality directly into EdenMount in a
future diff.

Reviewed By: bolinfest

Differential Revision: D4255675

fbshipit-source-id: 93749c6516c3cea4b4ae93de4ca49ddf05f4d260
2016-12-01 17:52:30 -08:00
Adam Simpkins
87c2d46ce3 write dirstate file atomically
Summary:
Write the dirstate data using the new folly::writeFileAtomic() function.
This ensures that the dirstate file will always contain full, valid contents,
even if we crash or run out of disk space partway through writing out the data.

This diff also includes a couple other minor tweaks:
- Update Dirstate to store the DirstatePersistence object directly inline,
  rather than allocating it separately on the heap.
- Update the DirstatePersistenceTest code to prefix temporary directories with
  "eden_test".  This just makes it easier to tell if the tests fail to clean up
  after themselves for any reason.

Reviewed By: bolinfest

Differential Revision: D4254027

fbshipit-source-id: 6b6601b65aeacdee998a6c4260e972d5fb2426ac
2016-12-01 17:52:30 -08:00
Adam Simpkins
aaa3332644 simplify EdenMount and Dirstate construction
Summary:
This cleans up construction of the EdenMount and Dirstate objects:

- The EdenMount constructor is now responsible for creating the Overlay and
  Dirstate objects.
- The Dirstate constructor is now responsible for loading the
  DirstatePersistence file.
- The EdenMount now takes ownership of the ClientConfig object, and stores it
  for later use.
- The ClientConfig object now has a method to get the path to the
  DirstatePersistence file.
- I added a ClientConfig::createTestConfig() method, so that the TestMount code
  can now use the same EdenMount constructor as the normal code.

This simplifies the logic in EdenServiceHandler and TestMount, and makes some
of the initialization dependencies a little bit simpler.

This change is necessary in order for me to move some logic from
fusell::MountPoint into EdenMount.  The Dirstate object will need a pointer
back to its EdenMount object, and this diff enables that.

Reviewed By: bolinfest

Differential Revision: D4249393

fbshipit-source-id: 439786accbf48c8696dbc6ca4fe77a4c6bdeab65
2016-12-01 17:52:30 -08:00
Michael Bolin
1cd336846e Validate the value of a UserStatusDirective read from disk.
Summary: Follow-up work from D4181868.

Reviewed By: simpkins

Differential Revision: D4256227

fbshipit-source-id: 3e40a0cae4ab132046d96029d2881c2127ed4c83
2016-11-30 19:04:06 -08:00
Adam Simpkins
0e613bd96b rename TreeEntryFileInode to FileInode
Summary:
Rename TreeEntryFileInode to FileInode, and TreeEntryFileHandle to FileHandle.
These class names were long and awkward.

It's slightly unfortunate that we now have classes named both
eden::fuse::FileInode and eden::fuse::fusell::FileInode, but I don't believe
this should cause any major problems.  If we want to eliminate these name
collisions in the future I would advocate for renaming the fusell versions to
something like "FileInodeIface".

Reviewed By: bolinfest

Differential Revision: D4217909

fbshipit-source-id: 899672a318d7ae39595f2c18e171f8fd6cebedc6
2016-11-30 15:49:13 -08:00
Michael Bolin
7d79026f1a Use const auto& base to avoid doing a copy.
Reviewed By: simpkins

Differential Revision: D4244182

fbshipit-source-id: ffdb55f59af45b0675336d4b9450c8b9fb90af5a
2016-11-29 11:19:08 -08:00
Michael Bolin
8c19620e62 Support directories in Dirstate::computeDelta().
Summary:
Previous to this commit, the `Dirstate` logic only worked correctly when the
changes occurred in the root directory. Obviously that is very limiting, so this
adds support for changes in arbitrary directories at arbitrary depths.

This also introduces support for things like a file being replaced by a
directory of same name or vice versa. The tests have been updated to verify
these cases.

One interesting design change that fell out of this was the addition of the
`removedDirectories` field to the `DirectoryDelta` struct. As you can see,
all entries in a removed directory need to be processed by the new
`addDeletedEntries()` function. These require special handling because deleted
directories do not show up in the traversal of modified directories.

In contrast, new directories do show up in the traversal, so they require a
different type of special handling. Specifically, this call will return `NULL`:

```
auto tree = getTreeForDirectory(directory, rootTree.get(), objectStore);
```

When this happens, we must pass an empty vector of tree entries to
`computeDelta()` rather than `&tree->getTreeEntries()`. Admittedly, the special
case of new directories is much simpler than the special case of deleted ones.

Reviewed By: simpkins

Differential Revision: D4219478

fbshipit-source-id: 4c805ba3d7688c4d12ab2ced003a7f5c19ca07eb
2016-11-29 06:51:14 -08:00
Michael Bolin
98c56736cd Add some error messages for some DCHECKs.
Reviewed By: simpkins

Differential Revision: D4219453

fbshipit-source-id: 391dd5ec57e01b2f09154eb991eb3e8e2e969f62
2016-11-26 12:01:41 -08:00
Michael Bolin
9156794f06 Pass ClientConfig as a raw pointer rather than transferring ownership.
Summary:
This is a better fix for the quick fix introduced by D4198939.
It turns out that the `EdenMount` does not need to take ownership
of the `ClientConfig`, so removing the `std::move()` makes this code
much simpler because instead of declaring a bunch of variables
early in `mountImpl()` so that we can "hold on" to them before `EdenMount`
takes ownership of the `ClientConfig`, we can declare them closer to where they
are actually used.

Note that we may want `EdenMount` to actually take ownership of the
`ClientConfig` in the future, but we'll cross that bridge when we come to it.

Reviewed By: simpkins

Differential Revision: D4199000

fbshipit-source-id: 67411a9a5ef630a9d481aebc94631c79da4ab2c4
2016-11-26 12:01:41 -08:00
Michael Bolin
b078392a9c Add Thrift endpoints for Hg dirstate.
Summary:
This also introduces the change where the `EdenMount` creates
and takes ownership of the `Dirstate`.

To clean some of this up, I had to expose a `getEdenDir()` method on `EdenServer`
that returns an `AbsolutePathPiece`. This was previously stored internally as a
`std::string`, so I had to clean up a bunch of path construction that was using `edenDir_`.

Reviewed By: simpkins

Differential Revision: D4123763

fbshipit-source-id: 270b182521c1a84bb054832f4b5f92af849d67e4
2016-11-26 12:01:41 -08:00
Michael Bolin
0f834ea809 Flip Dirstate -> EdenMount dependency.
Summary:
Previously, `Dirstate` took a `std::shared_ptr<EdenMount>`, but now it takes
pointers to a `MountPoint` and an `ObjectStore` because it does not need the
entire `EdenMount`. Ultimately, this will enable us to have `EdenMount` create
the `Dirstate` itself, but that will be done in a follow-up commit.

Fortunately, it was pretty easy to remove the references to `edenMount_` in
`Dirstate.cpp` and rewrite them in terms of `mountPoint_` or `objectStore_`.
The one thing that I also decided to move was `getModifiedDirectoriesForMount()`
because I already needed to create an `EdenMounts` file (admittedly not a
great name) to collect some utility functions that use members of an `EdenMount`
while not having access to the `EdenMount` itself.

As part of this change, all of the code in `eden/fs/model/hg` has been moved to
`eden/fs/inodes` so that it is alongside `EdenMount`. We are going to change
the `Dirstate` from an Hg-specific concept to a more general concept.

`LocalDirstatePersistence` is no longer one of two implementations of
`DirstatePersistence`. (The other was `FakeDirstatePersistence`.) Now there is
just one concrete implementation called `DirstatePersistence` that takes its
implementation from `LocalDirstatePersistence`. Because there is no longer a
`FakeDirstatePersistence`, `TestMount` must create a `DirstatePersistence` that
uses a `TemporaryFile`.

Because `TestMount` now takes responsibility for creating the `Dirstate`, it
must also give callers the ability to specify the user directives. To that end,
`TestMountBuilder` got an `addUserDirectives()` method while `TestMount` got a
`getDirstate()` method. Surprisingly, `TestMountTest` did not need to be updated
as part of this revision, but `DirstateTest` needed quite a few updates
(which were generally mechanical).

Reviewed By: simpkins

Differential Revision: D4230154

fbshipit-source-id: 9b8cb52b45ef5d75bc8f5e62a58fcd1cddc32bfa
2016-11-26 12:01:41 -08:00
Michael Bolin
65e078dd1e Introduce TestMount::readFile().
Summary:
This is a utility that should be generally useful in creating test,
including the test of `TestMount` itself.

As you can see, this helped uncover a bug in the way we were
inserting blobs into `LocalStore`.

Reviewed By: simpkins

Differential Revision: D4073039

fbshipit-source-id: 42683fd0bfdb0a1e77df9324fcaa79091f45e83d
2016-10-28 14:58:24 -07:00
Michael Bolin
24d6612232 Make getRootInode() method available through the stack.
Summary: This is a follow-up revision from a comment on D4013464.

Reviewed By: wez

Differential Revision: D4050278

fbshipit-source-id: 1e46526f58a07e1eedd8ace1a6d84a919240d899
2016-10-21 14:17:33 -07:00
Michael Bolin
139c9dec3b Move getRootTree() helper from TestMount to EdenMount.
Summary:
This is not a one-liner and this is needed for the upcoming `Dirstate` class,
so moving this code to a place where it is more easily reusable.

Reviewed By: simpkins

Differential Revision: D4032001

fbshipit-source-id: 7d8d87802665ac2993ec0a3ac73c5f645fe4a1aa
2016-10-21 13:32:02 -07:00
Michael Bolin
4d4538edec Fix bug I introduced in D4034298.
Summary: facepalm

Reviewed By: wez

Differential Revision: D4048640

fbshipit-source-id: 7a1ff55b7152d781c317c8e7f55c1afe4541fc12
2016-10-19 17:11:42 -07:00
Michael Bolin
1953391b36 Introduce TreeEntry.getMode() because getOwnerPermissions() was not doing the expected thing.
Summary: This will make it easier to compare a `TreeEntry` with a `TreeInode::Entry`.

Reviewed By: simpkins

Differential Revision: D4034298

fbshipit-source-id: 29674e2902661bf46394ea71b81537b35bd4b107
2016-10-19 10:54:11 -07:00
Michael Bolin
7f20232d4b New EdenMount constructor.
Summary:
I need this for the upcoming test harness so I can avoid creating a
`ClientConfig`, which is currently a huge pain to do from a unit test.

Reviewed By: simpkins

Differential Revision: D4010842

fbshipit-source-id: 03d1e1de9c3047340a6f26202d4b432f4a8620b4
2016-10-18 12:19:31 -07:00
Wez Furlong
0f4132c35f ensure that we set materialized=true when loading overlay
Summary:
We were hitting an assertion in the case where we did a `mkdir`
followed by a `rename` followed by `getMaterializedEntries`.

The issue is that our in-memory representation has a boolean to indicate
whether a dir inode is materialized, but our serialization format does
not have this bit.  When we loaded the data we were not setting the
field to true and this was caught by the DCHECK.

If we have serialized data for a dir then it is, by definition, materialized
and we should just set that field to true.

Reviewed By: bolinfest

Differential Revision: D3900795

fbshipit-source-id: 62d8281e7a1009056d274888c9aff87664d2e09f
2016-09-26 13:54:14 -07:00
Wez Furlong
878ce3138a fix issue with renaming between different dirs
Summary:
simpkins spotted this; we were passing the wrong path down to the overlay saving dir.

This adds a test to prove that the source and destination directory contents
are correct both immediately after performing the rename and after remounting,
where we just read the serialized data.

Reviewed By: simpkins

Differential Revision: D3888694

fbshipit-source-id: 7f5fb5be417db5c693ac8a07b85abbffdbfe0fff
2016-09-26 13:52:25 -07:00
Wez Furlong
82c57b2bf8 implement getCurrentJournalPosition thrift API
Summary:
populate the position from the latest journal delta.

To facilitate this, we also define the mountGeneration value to be a
combination of the pid and the time at which we created the EdenMount object,
as well as a global counter that we bump for each mount.

The precise value and meaning of this bits really doesn't matter, just that we
are unlikely to pick the same value for this same mountPoint path again if we
were to remount in the future.

Since we are now in a position to report JournalPosition values to clients, now
is also a good time to fill out the `currentPosition` field for the
`getMaterializedEntries` thrift call, and to check that this value is
consistent with the value we return via `getCurrentJournalPosition`.

Reviewed By: simpkins

Differential Revision: D3872952

fbshipit-source-id: 2fbc25d2e9711035b66ab1bf5d746507b72de265
2016-09-26 13:52:25 -07:00
Wez Furlong
ca929bcfa5 hook up journal functions to filesytem change operations
Summary:
This is pretty simplistic: we just wlock and add a delta for the set
of file(s) that were changed in a given fuse operation (this is typically 1
file, but rename affects 2).

To reduce boilerplate very slightly, I've added an initializer_list constructor
for JournalDelta that makes it less cumbersome to create a JournalDelta for a
list of files.

Reviewed By: simpkins

Differential Revision: D3866053

fbshipit-source-id: cd918e2c98c022d5ef79430cd8ab4aef88875239
2016-09-26 13:52:25 -07:00
Wez Furlong
e54df2e422 add getMaterializedEntries thrift call
Summary:
Adds a thrift call that returns the list of materialized entries from the whole tree.

This is intended to be plugged into the mercurial dirstate extension.

Reviewed By: simpkins

Differential Revision: D3851805

fbshipit-source-id: 8429fdb4eeccc32928e8abc154d4e6fd49343556
2016-09-26 13:52:24 -07:00
Wez Furlong
c077dced83 eden: fix @mode/opt build
Summary:
Annoying that gcc and clang behave differently here.  The compilation
error is due to gcc not seeing the implicit this pointer for some of these
method calls, so we need to explicitly use it.

Reviewed By: simpkins

Differential Revision: D3846973

fbshipit-source-id: 3d5b8b8b8c9bbab1e7935cff0e65677f76d116fb
2016-09-12 19:26:05 -07:00
Michael Bolin
7a05213f34 New Thrift endpoint: getBindMounts(mountPoint).
Summary:
Buck needs this API so that it knows which paths under a project
root it should exclude when deciding whether it can ask Eden for its
SHA-1 or if it must compute it on its own.

Reviewed By: simpkins

Differential Revision: D3840658

fbshipit-source-id: 5eddc0bef423d3b3ee165d2a4b0bbf193f94f61a
2016-09-12 18:29:15 -07:00
Wez Furlong
9c79b74456 eden: re-do overlay serialization
Summary:
we now serialize the overlay data for each directory independently.

When we mount, we try to load the root overlay data.  The children are lazy
loaded as the inodes are instantiated.

Structural changes cause the overlay data for the impacted dirs to get saved out.

I need to make a pass over this to fixup comments and so on, I just wanted to get this diff out first.

I moved the overlay stuff from `eden/fs/overlay` -> `eden/fs/inodes` since most
of the overlay-ness is handled in `TreeInode` now; the `Overlay` class is
really just for carrying around the paths and providing the serialization
helpers.

Reviewed By: simpkins

Differential Revision: D3787108

fbshipit-source-id: f0e089a829defd953535b9d0a96b102ac729261b
2016-09-09 16:57:58 -07:00
Wez Furlong
e6239f63c4 eden: merge overlay into the inode objects
Summary:
It was starting to get pretty complex to manage locking across the
inodes, filedata, overlay and soon the journal, so as a simplifying step, this
folds data that was tracked by the overlay into the TreeInode itself.

This is the first diff in a short series for this.  This one:

1. Breaks the persistent overlay information, so shutting down eden and
   bringing it back up will lose your changes (to be restored in the
   following diff)
2. Allows deferring materialization of file data in more cases
3. Allows renaming dirs.

The approach here is now to keep just one source of information about the
directory contents; when we construct a TreeInode we import this data from the
Tree and then apply mutations to it locally.

Each inode can be mutated indepdently from others; we only need to lock the 1,
2 or 3 participating inodes in the various mutation operations.

I'll tackle persistence of the mutations in the following diff, but the high
level plan for that (to help understand this diff) is to always keep the
directory inodes for mutations alive as inode objects.  We make use of the
canForget functionality introduced by D3774269 to ensure that these don't
get evicted early.   On startup we'll load this information from the overlay
area.

This model simplifies some of the processing around reading dirs and looking up
children.

Since the overlay data now tracks the appropriate tree or content hash
we can be much more lazy at materializing data, especially in the rename
case.  For example, renaming "fbcode" to "fbcod" doesn't require us to
recursively materialize the "fbcode" tree.

Depends on D3653706

Reviewed By: simpkins

Differential Revision: D3657894

fbshipit-source-id: d4561639845ca93b93487dc84bf11ad795927b1f
2016-09-09 16:57:58 -07:00
Wez Furlong
174d0b9b0a eden: assign our own file handle numbers and track all file handles
Summary:
Previously we would simply report the raw pointer address to the kernel and
rely on it to return that same number to us as the file handle, and make sure
that it told us to shut down the handle when it was closed.

This meant that we had no real idea about which files were still open.

For our future live upgrade plans we need to be able to know this so that we
can transfer the appropriate information to our replacement process.

To facilitate this this diff implements a FileHandleMap class that will assign
file handle numbers and keep track of the instances.  The number assignment
strategy is the same as it used to be in the common case: we take the address
of the newly created instance and use that 64-bit number as the file handle
number.  However, in the future when we transfer the mapping to a new process,
we may experience a collision when subsequently opening a file handle.  To deal
with that, we have a bounded number of attempts to assign a random file handle
number.

We don't yet offer a means to iterate the map, but it would be trivial to
expose such an accessor when we're ready to use it.

Since we now keep track of these things via shared_ptr this changes the
appropriate portions of the fuse interface from unique_ptr to shared_ptr.

Reviewed By: simpkins

Differential Revision: D3602364

fbshipit-source-id: dd996339c2838225a2caeee9da16ef99a06c1e2b
2016-07-26 10:00:11 -07:00
Wez Furlong
c5540e446a eden: implement rename for files, add test for sed -i
Summary:
Implements basic rename(2) support.  We only do this for files at this
time as directory renames require that we recursively materialize a tree and
are a bit more complex.  I'll look at that in a follow-on diff; there's
potential for optimizing it to avoid eager materialization, but that depends on
the trie work that I'm tackling concurrently with this.

rename for files is the last piece needed to allow `sed -i` to operate correctly.

Reviewed By: bolinfest

Differential Revision: D3515361

fbshipit-source-id: 9c8cc5f9b8db6b5a9372ca9286336647f50490f8
2016-07-05 19:54:21 -07:00
Wez Furlong
bccda176d4 eden: implement O_EXCL open flags
Summary:
This enables O_EXCL to function by allowing the create routine to
move its folly::File instance down in to the underlying FileData instance.

Previously we would close and then re-open the file; this would discard
any of the natural gating for the open call that is performed by the kernel
for the underlying filesystem in the overlay.

Reviewed By: bolinfest

Differential Revision: D3513758

fbshipit-source-id: 85967a3b7affa1b1df46842be8ba21c8fbb843a6
2016-07-05 19:54:21 -07:00
Wez Furlong
59892c395f eden: implement unlink and rmdir
Summary:
Despite being handy things for filesystems in general, these are
needed to support the `sed -i` integration test.

Reviewed By: bolinfest

Differential Revision: D3513754

fbshipit-source-id: 505b4bd58b254141e2ef996f01e3347fc1a77584
2016-07-05 19:54:21 -07:00
Wez Furlong
798f4bda58 eden: introduce Tree::getEntryPtr(PathComponent)
Summary:
This eliminates a linear scan from TreeInode and replaces it with a
binary search, exploiting the sorted order of the entries vector.

Two new methods are introduced: getEntryPtr which returns a pointer to the
entry with the matching name, and getEntryAt() which returns a reference
(throwing a range error if there is no such entry).

I wanted to use the PathMap class here, but that would cause us to duplicate
the name string as both the key and value in the map.

Reviewed By: bolinfest

Differential Revision: D3515723

fbshipit-source-id: 4ee0371f3ec08cbcf110cf28f5c1e1529b120fb6
2016-07-05 17:42:14 -07:00
Wez Furlong
720f319e5c eden: implement setattr for file inodes
Summary:
setattr is a bit of a multi-purpose interface; depending on the flag
values, this is responsible for:

* ftruncate(2)
* fchmod(2)
* fchown(2)
* futimens(2)

In order to apply any of these things, we have to materialize the file.  In
the future we may want to allow setting the utimes without materializing the file.

We don't allow chown to actually chown anything.  We may want to relax that in
the future, but at the moment we will return an error if an attempt is made to
change the ownership of a file.

Reviewed By: bolinfest

Differential Revision: D3511011

fbshipit-source-id: 858d2c07686fcbe2dcdb60a07527f739a9726be3
2016-07-01 15:10:02 -07:00
Adam Simpkins
7d0cfe494e fix crash when built with gcc
Summary:
When running the integration tests when built with gcc, the tests would crash
in TreeInode::create().  It appears that the unique_ptr<FileHandle> object was
getting passed to the lambda before dereferencing it to call getattr().

Reviewed By: wez

Differential Revision: D3459605

fbshipit-source-id: 5e2ce98d268a85731acaf7d7f37f22c77fb571cf
2016-06-20 15:25:00 -07:00
Adam Simpkins
781936eba5 fix uninitialized inode numbers and other data in stat() responses
Summary:
This fixes inode number handling problems in TreeInode and TreeEntryFileInode.
Previosly these classes each had an ino_ member variable, despite deriving from
InodeBase which has its own (private) ino_ member.

TreeEntryFileInode never actually initialized its own local ino_ variable.
This was causing problems for many applications which use inode numbers to
cache file data.  TreeEntryFileInode returned garbage data in the inode field,
resulting in incorrect cache collisions.

This fixes the inode handling, and also fixes the stat data returned by
FileData.  It now sets the uid, gid, and inode fields correctly.  It 0s out
several other fields rather than leaving them uninitialized.

Reviewed By: bolinfest

Differential Revision: D3455126

fbshipit-source-id: 631276b01676733f96035bc153219ef84406dcc9
2016-06-20 13:40:02 -07:00
Adam Simpkins
1eed0364e3 always show tree contents for (non-opaque) directories in the overlay
Summary:
If a directory is present in the overlay, we still need to check if a TreeEntry
exists from the source control data structures.  Previously this was causing us
to incorrectly report directories as empty if they exist in the local overlay,
even when they had contents from the main Tree.

Reviewed By: wez

Differential Revision: D3434219

fbshipit-source-id: f872f90075602dfdc7b217f50eefcd7c248512e7
2016-06-15 14:24:12 -07:00
Adam Simpkins
32f4c458fe begin adding a new ObjectStore class
Summary:
Add a new ObjectStore class, which will eventually contain both a LocalStore
and a BackingStore.  The LocalStore will be a cache of data loaded from the
authoritative BackingStore.  The ObjectStore API will hide the work of querying
the BackingStore and updating the LocalStore when data is not already available
in the LocalStore.

For now ObjectStore only contains the LocalStore, but I will add BackingStore
functionality in subsequent diffs.  This diff simply updates all call sites to
use the ObjectStore instead of directly accessing the LocalStore.

Reviewed By: bolinfest

Differential Revision: D3403898

fbshipit-source-id: 47b8c51a7717a4c7c29911a7085b382521a8c0db
2016-06-08 19:01:13 -07:00
Michael Bolin
499f72a9f8 Introduce TreeEntryFileInode::getSHA1()
Summary:
This avoids translation from string->Hash in the common case
where the file is unmodified and its hash is read directly from
the store rather than computed from the overlay.

I'm guessing I should use `unique_ptr` as the return value throughout?

Reviewed By: simpkins

Differential Revision: D3355773

fbshipit-source-id: 50dff879a78b3d6ff49f86b856866ca28808c4f7
2016-05-27 18:17:07 -07:00
Wez Furlong
dde572cf5e eden: sha1 attributes on overlay [2/2]
Summary:
Add a function to compute the sha1 content hash for an overlay file.

We persist the computed hash in an extended attribute in the underlying overlay
file so that a subsequent read of the attribute doesn't require opening the
file to recompute it.

Each time the file is mutated, we blow the cached status of the file.
Each time the sha1 attribute is read, if the cache is blown, the content
hash will be recomputed and set in the overlay file.

Each time the file is flushed or sync'd, if the cache is blown, the content
hash will be computed and set in the overlay file.

Reviewed By: bolinfest

Differential Revision: D3302412

fbshipit-source-id: bd45c7a24b732bd0b7474b7f96e82936870b2117
2016-05-26 08:23:11 -07:00
Wez Furlong
056d08bbbe eden: sha1 attributes on overlay [1/2]
Summary:
This is part 1 of 2 diffs.  This one adds some plumbing to make it possible
to read the xattr attribute from an overlay.

It doesn't do anything to ensure that it is set; the next diff in this series will take care of that.

Reviewed By: bolinfest

Differential Revision: D3302410

fbshipit-source-id: 47406a9c75f29743691d396676c691bcb99c4760
2016-05-26 08:23:11 -07:00
Wez Furlong
ff4bc88da6 eden: remove InodeNamgeManager singleton
Summary:
We look this up via the mount point or eden mount object instead.

I've also removed the mercurial library stuff that was added to support the now defunct lamehg fuse we had in the earlier days.
simpkins' new importer doesn't use these and it resolves our CI mismatch issue.

Reviewed By: bolinfest

Differential Revision: D3349698

fbshipit-source-id: 5f4ec16b76042959cd1e3184f46bb3526fbaf74c
2016-05-25 19:34:16 -07:00
Adam Simpkins
53e821eb23 add an EdenMount class
Summary:
Add a new class to serve as a single location where we can store all
information about a single eden mount point.  Currently this contains the
MountPoint, LocalStore, and Overlay objects.  This allows the TreeInode class
to just store a single pointer to the EdenMount, rather than having to track
these three objects separately.

In the future we could consider also keeping a copy of the ClientConfig in the
EdenMount object, but I haven't done that for now.

Reviewed By: bolinfest

Differential Revision: D3321355

fbshipit-source-id: 8a39bb49822ca8e90c88b2a834b59230d2f91435
2016-05-20 10:34:07 -07:00
Wez Furlong
498a3b8aba eden: add mkdir support
Summary:
Enables mkdir in the overlay area.

I had to add some `lstat` calls in to the overlay dir reader because we depend
on knowing at least whether a node is a dir or not at the next level up.

When I run the test suite, the mounts are on my `/tmp` filesystem.  When I run
eden manually, they are on my `/data` filesystem.  The latter (xfs) does not
populate the type bits.  This meant that the test suite passed but manual
testing did not.

Adding the `lstat` calls is a little unfortunate.  On OS X there is a bulk
operation that combines `readdir` and `lstat` so that there are fewer syscalls.
We don't have an equivalent for Linux.

Reviewed By: bolinfest

Differential Revision: D3301532

fbshipit-source-id: e228f4a392f90aa491fec62e8b98471a8acecff2
2016-05-18 12:24:00 -07:00
Wez Furlong
103224b5df eden: remove naked pointers from FileInode::open and DirInode::opendir
Summary:
We still have naked pointers at the handoff to the kernel, but now
have a cleaner implementation at the level that we're going to be working at
day to day.

I also renamed `FileHandle::release` to `FileHandle::releasefile` so that it
isn't visually ambiguous with `std::unique_ptr::release` in the
`Dispatcher.cpp` code: `fh.release()` vs `fh->release()` look similar but are
dramatically different in behavior.

Reviewed By: bolinfest

Differential Revision: D3309455

fbshipit-source-id: f8cf055bcd51121048a20f0202988cf0aef1f085
2016-05-17 18:17:11 -07:00