Commit Graph

1828 Commits

Author SHA1 Message Date
Adam Simpkins
d0ba23f47a decrease the log level of globFiles() thrift calls
Summary:
D18820280 increased the log level for `globFiles()` calls from DBG3 to DBG2.
However, buck and other tools often end up huge numbers of glob calls, and
this ends up causing log spam.

This change reduces the log level of `globFiles()` back to DBG3.  In a
subsequent diff I will update the code to increase the log level for slow
calls.  This does mean that we will only get a log message for slow glob calls
after the call completes, but this is better than not getting a message at
all.

Reviewed By: pkaush

Differential Revision: D18924780

fbshipit-source-id: 86e83614f51424aca078e4de8a56c45018a6d286
2019-12-10 20:18:36 -08:00
Genevieve Helsel
8ff8d6217e setParentCommits after checkout while holding parentsLock_
Summary: was looking in this area and saw this TODO. moves the `setParentCommits()` call into `CheckoutConflict::finish()` so it is called while we are still holding the parents lock.

Reviewed By: chadaustin

Differential Revision: D18668329

fbshipit-source-id: 8415c792193e5b89737f15141f33c5a9799f527b
2019-12-10 18:13:26 -08:00
Chad Austin
d0ce25afba log to scuba upon automatic gc
Summary:
A spike in automatic GCs usually implies something has gone wrong. Log
an event for each one, recording the cache size prior to the GC and
the cache size after.

Reviewed By: simpkins

Differential Revision: D18902580

fbshipit-source-id: 158b2635733a415a9fcc7c412b2c0f44ed04aa01
2019-12-10 16:16:35 -08:00
Puneet Kaushik
eb17a5bde8 Enable getScmStatusBetweenRevisions
Summary: Enabling getScmStatusBetweenRevisions to work on Windows and its tests.

Reviewed By: simpkins

Differential Revision: D18431271

fbshipit-source-id: eee82538e2fc3d7e371c96fc271cd9662ea6d737
2019-12-10 14:07:26 -08:00
Puneet Kaushik
4c720d12c1 hg status tests for Eden Windows
Summary: This diff contains the tests for hg status. This is not comprehensive list of tests but the tests that we have working at this time. More tests will be added as we test and fix issues.

Reviewed By: simpkins

Differential Revision: D18454851

fbshipit-source-id: 80e3ff4d24873016dc420f202fbfe53fcffc24f2
2019-12-10 14:07:26 -08:00
Puneet Kaushik
8b0feed6fd Move EdenDispatcher under PrjfsChannel
Summary: The current implementation of EdenDispatcher is projectedfs specific and was linking against its dll. This was adding the need to add Prjfs dll for running our tests. Moving it to prjfs channel should fix that.

Reviewed By: simpkins

Differential Revision: D18462171

fbshipit-source-id: ff7bfcdd14d19552d49b61ff03cdd770badfcd68
2019-12-10 14:07:26 -08:00
Puneet Kaushik
35accc34bc Add TestMount class to test EdenMount
Summary: This class provides an interface to create an EdenMount for testing and use it through the APIs. It's similar to TestMount for Eden on Posix.

Reviewed By: simpkins

Differential Revision: D18454852

fbshipit-source-id: 91d64b2c535060979ef634fe4e7779f50f169fc5
2019-12-10 14:07:25 -08:00
Puneet Kaushik
f54831e526 Teach WinStore to work with std::wstring_view to avoid unnecessary copy
Summary: WinStore interface was taking wstring for path and we were converting wchar pointers to wstring which were later converted to RelativePath. In this diff we pass the path as is and save one copy per operation.

Reviewed By: simpkins

Differential Revision: D18444773

fbshipit-source-id: fa6a3efb6a7e91cf9b0dca919e80870e1bcf0804
2019-12-10 14:07:25 -08:00
Puneet Kaushik
abfdda5447 Create TestFsChannel class
Summary: Moved the current FsChannel implementation in to PrjfsChannel and converted the FsChannel.h into an abstract class. Created a TestFsChannel class for testing.

Reviewed By: simpkins

Differential Revision: D18440401

fbshipit-source-id: 30d6742cd18b4b76b664e3af7ed1a528cf876046
2019-12-10 14:07:25 -08:00
Puneet Kaushik
e19f84aa65 Add resetParents to enable hg commit
Summary:
A successful run of hg commit ends in call to resetParents() to reset the current parent commit.

We also need resetParent to run the Status tests.

Reviewed By: genevievehelsel

Differential Revision: D18439954

fbshipit-source-id: 44f7a009e050bd5e2130d8c4fc3a85a8ec3bfad1
2019-12-10 14:07:24 -08:00
Puneet Kaushik
86f5c839d1 Add EdenMount diff to generate the ScmStatus
Summary: This implements diff() inside EdenMount which uses GenerateStatus to compute the ScmStatus.

Reviewed By: simpkins

Differential Revision: D18195574

fbshipit-source-id: 16cfbda35796d1cfd4e13e6566b7ac222163aea4
2019-12-10 14:07:24 -08:00
Puneet Kaushik
7e2de5609a Add GenerateStatus to compute the status change
Summary:
GenerateStatus will parse the CurrentState and compute the status. The algorithm here is little different than of Eden with FUSE, Eden with Prjfs will loop over the CurrentState and only compare the entries present in it. CurrentState has the list of all the entries modified and a complete status could be generated from it.

This doesn't solve all the scenarios. I have few unit tests running at the top of this stack and those cases are working. I need to test the other cases and make them work. One case that I already know doesn't work is when a user resets the parent and doesn't make any change. I will work on fixing the other cases and put up diffs for that.

Reviewed By: simpkins

Differential Revision: D18195573

fbshipit-source-id: 3650f26387f1a5f8d467fd81148c266fa1307a3c
2019-12-10 14:07:24 -08:00
Zeyi (Rice) Fan
ae1dae6b96 eden: add experimental:use-edenapi for optionally turn on EdenApi importing
Summary:
Add an option `experimental:use-edenapi` to `EdenConfig`.

See the next diff for usage.

Reviewed By: chadaustin

Differential Revision: D18605549

fbshipit-source-id: 2786c21bb38a76229078662cc5c1ddf906d1be4a
2019-12-10 13:40:55 -08:00
Zeyi (Rice) Fan
ed9e7abca2 eden: add FakeEdenConfig for testing
Summary:
I think we need to make `EdenConfig` available for testing as more things are using `EdenConfig` to configure behaviors.

Right now it does not do much things other than just construct an `EdenConfig` instance without manually providing these parameters.

Reviewed By: chadaustin

Differential Revision: D18798484

fbshipit-source-id: b4a85d966a9b4f425c547bef9eb6e7570d7e2170
2019-12-10 13:40:55 -08:00
Chad Austin
b47bf0289e ensure fuse capability flags survive graceful restart
Summary:
Two bugs conspired to cause edenfs after a graceful restart to think
the kernel supported FUSE_NO_OPENDIR_SUPPORT when it didn't: the
connection info struct wasn't zeroed, and FUSE connection capabilities
weren't properly mirrored into the Dispatcher upon graceful
restart. Fix both and add an integration test.

Reviewed By: simpkins

Differential Revision: D18903761

fbshipit-source-id: 23f4db3e240ee7d035f707820072c606a45f1138
2019-12-10 10:25:30 -08:00
Chad Austin
40e6e4bde2 enable eden debug logging in open source and macOS builds
Summary:
Register the logging and logging_full option handlers in the open
source and macOS builds of Eden.

Reviewed By: simpkins

Differential Revision: D18870545

fbshipit-source-id: 140debe77be071a9fa2d628ad305517273e095e3
2019-12-09 19:41:18 -08:00
Genevieve Helsel
504a255355 add getTreeForManifest
Summary: Adds a function which takes both the manifestID and the commitID to get a Tree. This will be used in `checkOutRevision()` and this allows us to skip looking up the manifestID since the caller can just pass it in themselves.

Reviewed By: wez

Differential Revision: D18719405

fbshipit-source-id: 919f0a7c84bff4a2f0bc20110c45bd272f9e9107
2019-12-09 16:25:27 -08:00
Chad Austin
4963352d64 temporarily mark trees persistent
Summary:
It is very painful for Eden's automatic GC to delete trees from the
local store. An unfortunate number of programs scan the entire repo,
causing every tree to be loaded. If Eden's automatic GC kicks in, it
causes all trees to be downloaded again, blocking both FUSE and Thrift
requests.

Temporarily mark trees as persistent.

Reviewed By: fanzeyi

Differential Revision: D18842066

fbshipit-source-id: 4a22defcb1151912337d4167ac49852519c7789d
2019-12-09 16:11:36 -08:00
Genevieve Helsel
0907d3adda save loadFileFromPath in DiffContext
Summary: Saves loadFileFromPath in the DiffContext. This allows the source control differ ( at `eden/fs/store/Diff.cpp`) to call this function while it is trying to load gitIgnores and resolve symlinks.

Reviewed By: simpkins

Differential Revision: D18647088

fbshipit-source-id: bddff0158130f0c96ac263bcce81dc51fc017800
2019-12-09 11:33:23 -08:00
Genevieve Helsel
c8bdf32bc9 introduce EdenMount::loadFileContentsFromPath
Summary: Adds a helper function that can take a path to an Inode and load a file by simply getting the Inode then calling the existing `loadFile()` function

Reviewed By: simpkins

Differential Revision: D18647090

fbshipit-source-id: 89c25bef10a7a0d0ffd660293f85479ac0e9f9a9
2019-12-09 11:33:23 -08:00
Genevieve Helsel
32fb62cedf move gitignore loading to EdenMount as EdenMount::loadFileContents
Summary: Move the bulk of the gitignore loading to EdenMount, this is needed later in the stack to pass this function as a callback through the DiffContext to enable gitignore loading from the source control tree differ.

Reviewed By: simpkins

Differential Revision: D18565265

fbshipit-source-id: 062349d81bbfb78235ccb34d6ec72ad445a6e2b0
2019-12-09 11:33:23 -08:00
Adam Simpkins
cf4ef20aaa increase the log level for globFiles() thrift calls
Summary:
Increase the log level for messages about `globFiles()` thrift calls so that
they are enabled by default in our normal production configuration.

`globFiles()` calls can potentially cause EdenFS to fetch a lot of data, so it
is useful to be able to see them in the logs when investigating performance
issues.

Reviewed By: genevievehelsel

Differential Revision: D18820280

fbshipit-source-id: e351a9541e420f5eb47ca14d6620366437773ce4
2019-12-04 16:29:12 -08:00
Adam Simpkins
e6de5c6c3e drop the log level of a debug message in LocalStore.cpp
Summary:
This message is pretty noisy when running EdenFS with an increased debug
logging level.  Bump the debug level down so it doesn't spam the logs when
running at a slightly elevated debug level.  Also fix a minor typo.

Reviewed By: fanzeyi

Differential Revision: D18820281

fbshipit-source-id: 668367337f4a8cf2a38003c8e0034969d335c2c0
2019-12-04 16:29:12 -08:00
Genevieve Helsel
ff441bf0a6 clean up DiffTrees code
Summary: There are a couple of functions in `store/Diff.h` which are not used elsewhere except for testing. These functions are tested by `diffCommitsForStatus()` anyways so these standalone functions are not needed.

Reviewed By: chadaustin

Differential Revision: D18690006

fbshipit-source-id: f2b24575c17403d7241896f35f4e0e16bb03b7ce
2019-12-04 16:01:48 -08:00
Chad Austin
be9ea834ca remove the redundant inode number from UnloadedInode
Summary:
Each entry in InodeMap::unloadedInodes_ stored the InodeNumber
twice. Remove one of them.

Reviewed By: wez

Differential Revision: D18651007

fbshipit-source-id: be85c34cb2b38fc0b2875d0874cecd1ef274aca4
2019-12-04 13:30:19 -08:00
Chad Austin
6b168708d9 readability improvements to diff code
Summary: Small readability improvements I noticed while reading the diff algorithm.

Reviewed By: genevievehelsel

Differential Revision: D18650987

fbshipit-source-id: 19346362711455ae87d6770812e647544a4576bf
2019-12-04 13:30:18 -08:00
Chad Austin
f930a40434 make PathComponentPiece and RelativePathPiece constexpr
Summary: Allow creation of PathComponentPiece and RelativePathPiece values at compile-time.

Reviewed By: wez

Differential Revision: D18642594

fbshipit-source-id: 209e5c27e8fab1e877ccee8558fa757b68078e66
2019-12-04 13:30:18 -08:00
Chad Austin
3a625fda68 build cleanly with -Wextra-semi
Summary: Remove unnecessary semicolons in preparation for adding -Wextra-semi.

Reviewed By: wez

Differential Revision: D18784373

fbshipit-source-id: 2fe8366defc2b8d79a4585a4e961a6fe84b91c67
2019-12-03 15:04:27 -08:00
Chad Austin
edd7a8f5c8 enable -Wmismatched-tags
Summary:
On Windows, structs and classes mangle differently. Detect mismatches
on Linux too.

Reviewed By: simpkins

Differential Revision: D18774928

fbshipit-source-id: 6962076902c8363550625eb30a7c348b092cb090
2019-12-03 14:43:12 -08:00
Chad Austin
918d153789 enable -Wunreachable-code
Summary: We build unreachable-clean, so enable the warning.

Reviewed By: fanzeyi

Differential Revision: D18668374

fbshipit-source-id: e356c75c5090aa08b5cfb7c267efd0452c0aa228
2019-12-03 14:43:12 -08:00
Zeyi (Rice) Fan
6ae87b04f6 eden: remove hg_import_helper.py
Reviewed By: simpkins

Differential Revision: D18602771

fbshipit-source-id: bf004911251b7380d1c4c21c07241c7d0a853c61
2019-12-03 09:30:09 -08:00
Adam Simpkins
54afe77b5a fix some warnings about functions returning without a value
Summary:
Add default case handling for some switch statements that do not handle the
case of an enum variable being set to something outside of one of the defined
values.

Reviewed By: fanzeyi

Differential Revision: D18652102

fbshipit-source-id: abcb3f9dc1f6b0dc761170c7115ddd9ad5145bc4
2019-11-22 15:38:34 -08:00
Adam Simpkins
e07f8bd7b6 refactor the EDEN_BUG() macro
Summary:
This splits `EDEN_BUG()` into three separate version.  All three crash in
debug mode builds, but in release builds they behave differently:

- `EDEN_BUG()` throws an exception
- `EDEN_BUG_FUTURE(Type)` returns a `folly::Future<Type>` that has been
  fulfilled with an exception.
- `EDEN_BUG_EXCEPTION()` returns a `folly::exception_wrapper`.

The main advantage of this is that this allows the compiler to detect that
`EDEN_BUG()` can never return.  Previously `EDEN_BUG()` was used for all 3 of
these different cases, and its behavior depended on whether `toException()`
was ever called.  As a result we could not easily get the compiler to identify
code paths where we know at compile time that it will never return.

Reviewed By: chadaustin

Differential Revision: D18652103

fbshipit-source-id: 070107c7520f51b05696905fa243de5f8df15958
2019-11-22 15:38:33 -08:00
Adam Simpkins
2442b46ee8 cmake: always build support for the EdenSCM backing store
Summary:
Now that the fb-mercurial sources are available in the Eden repository, update
our CMake build files to always build them.  This moves the build logic from
the centralized `FBMercurialFeatures.cmake` file into `CMakeLists.txt` files
in the appropriate subdirectories.

Reviewed By: chadaustin

Differential Revision: D18588011

fbshipit-source-id: ded9decde5c2ec766aae0bb0f4f5b021d1044a98
2019-11-22 13:00:07 -08:00
Adam Simpkins
aef2dbce95 cmake: unconditionally build the Rust datapack library code
Summary:
Update the CMake build to always build the Rust datapack libraries, even on
Windows.  This allows us to completely eliminate the `EDEN_HAVE_RUST_DATAPACK`
checks.

Note that I did leave the `EDEN_HAVE_RUST_DATAPACK` macro in place, as we
still do not build the Rust datapack code on Mac when building with Buck.

Reviewed By: fanzeyi

Differential Revision: D18588008

fbshipit-source-id: 1a4c9ceec5372d0e6a7313d2eb87edabd1e60a96
2019-11-22 13:00:06 -08:00
Adam Simpkins
cd9a1e0e88 cmake: directly build the rust datapack libraries
Summary:
Update Eden's top-level CMakeLists.txt file to build the Rust datapack
libraries.  Previously these were built by invoking CMake separately inside th
`eden/scm` subdirectory.  Now that the code has been combined into a single
location we can use a single CMake invocation to drive the build of both these
components.

The old code did not build the Rust datapack code on Windows, and this diff
does not change that behavior.  I'm not aware of any reason to skip building
this on Windows, so I plan to enable building this code on Windows in a
subsequent diff.

Reviewed By: pkaush

Differential Revision: D18588006

fbshipit-source-id: 20f4f0ea9fef8595a9dd35a21115952b2808c824
2019-11-22 13:00:06 -08:00
Genevieve Helsel
aae83490c9 compare blob contents sha1 in Diff.cpp
Summary: Even if blobs have different hashes, they could have the same contents. For example, if between the two revisions being compared, if a file was changed and then later reverted. In that case, the contents would be the same but the blobs would have different hashes. Currently, `getScmStatusBetweenRevisions()` would report false positives in this case. This is also needed so we do not report false positives in `getScmStatus()` when hit this code path

Reviewed By: simpkins

Differential Revision: D18647086

fbshipit-source-id: 66e12648a24fd7e5612eee5e599a5b81c7c5f2d1
2019-11-22 08:09:37 -08:00
Adam Simpkins
306a429bd6 mark manual imports in hg_import_helper.py
Summary:
Annotate some import statements so autodeps won't complain about them, since
it doesn't know where they come from in the build.

Note that `hg_import_helper.py` isn't used any more by the current code, and
should ideally be killed off soon.  However, just annotating these import
statements for now in the short term is the easiest way to make autodeps
happy.

Reviewed By: fanzeyi

Differential Revision: D18652104

fbshipit-source-id: 310bc5c63447e3bf4dfd081d7b3930eed4d0498b
2019-11-21 21:43:54 -08:00
Adam Simpkins
2f075880c8 fix a missing dependency in a CMakeLists.txt file
Summary:
The `eden/fs/sqlite` code uses `eden/fs/utils/PathFuncs.h`, so add a proper
dependency on the `eden_utils` library.

Reviewed By: pkaush

Differential Revision: D18652105

fbshipit-source-id: b8dffd93971ab5efb71d7bc3c2dcb62249b3915b
2019-11-21 21:43:54 -08:00
Chad Austin
516e84d705 record the durations of the various phases of checkout
Summary:
Record the durations of each phase of checkout so it can be logged to
scribe in a future diff.

Reviewed By: simpkins

Differential Revision: D18632258

fbshipit-source-id: e447976af22cf25cffd640e79b95da2989b07448
2019-11-21 17:16:10 -08:00
Zeyi (Rice) Fan
dee0478903 eden: add experimental:enable-blob-caching
Summary: Adding an experimental option to EdenFS so we can disable blob caching if we need.

Reviewed By: chadaustin

Differential Revision: D18441665

fbshipit-source-id: 56751c0199d6658bfbf7ec3865f746a7279324ab
2019-11-21 12:05:29 -08:00
Chad Austin
46b25acec8 introduce CheckoutResult struct
Summary:
We're about to return more information from checkout, so
introduce a CheckoutResult struct.

Reviewed By: genevievehelsel

Differential Revision: D18630820

fbshipit-source-id: 78b68ef3551ca8c9e9968631de554084c333b4b9
2019-11-21 11:50:46 -08:00
Genevieve Helsel
a47b831d54 stop processing getScmStatusV2() calls if the thrift connection is closed
Summary: make `future_getScmStatusV2` into `async_tm_getScmStatusV2` so we can short circut the status call if the request is no longer active.

Reviewed By: simpkins

Differential Revision: D18378212

fbshipit-source-id: b2bca014a37d99f7a92478c3e23bde0b874dd13c
2019-11-20 18:06:33 -08:00
Genevieve Helsel
3807e751ca make enforceParents configurable for getScmStatusV2
Summary: This reads `enforceParents` from a config instead of always assuming true for `getScmStatusV2()`. This will allow a easy kill switch in case throwing errors from this thrift call causes issues with something that calls hg status

Reviewed By: simpkins

Differential Revision: D18258164

fbshipit-source-id: 1ae421a941c01a678d25d5453c771262b03558d0
2019-11-20 17:51:21 -08:00
Zeyi (Rice) Fan
c7546996e9 eden: switch to using Rust code parse manifest
Reviewed By: chadaustin

Differential Revision: D18365537

fbshipit-source-id: ef4d2fc5af01ab86f50df44b7a98f7b6f2884587
2019-11-19 18:01:24 -08:00
Zeyi (Rice) Fan
34c255890d eden: implement conversion functions from Rust Tree to EdenFS Tree
Summary:
This diff adds the C++ conversation methods that converts the Rust struct introduced in the previous Diff into EdenFS's `Tree`.

We have to keep the RocksDB write batch in for storing proxy hashes.

Reviewed By: wez

Differential Revision: D18365504

fbshipit-source-id: 2a2cd2cfebd9f0ae4e279db608becc5890c5ccdf
2019-11-19 18:01:24 -08:00
Puneet Kaushik
a88d4eff1f Add template function to convert different string input types
Summary: Create a template functions to convert strings with a wide variety of input types like folly::StringPiece, std::string, folly::fbstring and std::string_view to wide char string.

Reviewed By: wez

Differential Revision: D18071832

fbshipit-source-id: 147af97dff929766db83c9477117ec82da42b03e
2019-11-18 11:31:17 -08:00
Puneet Kaushik
e9dbb85b8d Fix FileUtilsTest and enable them.
Summary: We had linking issues with the Boost while compiling with getdeps. I have moved the tests to use std::filesystem instead.

Reviewed By: wez

Differential Revision: D18195608

fbshipit-source-id: 32213a9b22105869eef78724bb3e583c3fd8e708
2019-11-18 11:31:16 -08:00
Victor Zverovich
3285a8f909 Replace Folly Format with fmt in logger to reduce binary size
Summary:
Now that fmt is available in Folly builds (D14813810), use it to reduce binary code size in Folly Logger. This is done by moving most of the formatting logic behind the type-erased `vformat` API. Previously it was instantiated for all combinations of formatting argument types used in calls to `FB_LOGF` and `XLOGF` in a program.

The effect of this change can be illustrated by looking at symbol sizes as given by `nm -S -td` for the following test function:

```
void test_log() {
  FB_LOGF(logger, WARN, "num events: {:06d}, duration: {:6.3f}", 1234, 5.6789);
}
```
compiled in `opt` mode.

`nm` before:

```
0000000004236736 0000000000000231 T test_log()
0000000004236992 0000000000001002 W std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > folly::LogStreamProcessor::formatLogString<int, double>(folly::Range<char const*>, int const&, double const&)
```

`nm` after:

```
0000000004237536 0000000000000231 T test_log()
0000000004237792 0000000000000251 W std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > folly::LogStreamProcessor::formatLogString<int, double>(folly::Range<char const*>, int const&, double const&)
0000000004238048 0000000000000740 W folly::LogStreamProcessor::vformatLogString[abi:cxx11](folly::Range<char const*>, fmt::v5::format_args, bool&)
```

Before we had one 1002 byte instantiation of `formatLogString<int, double>`. With this change it was reduced 4x to 251 bytes and non-template function `vformatLogString` was added which is shared among all logging calls. The size of `test_log` remained unchanged. There are even bigger savings from Folly Formatter instantiations which are no longer needed, e.g.

```
0000000004238032 0000000000001363 W _ZNK5folly13BaseFormatterINS_9FormatterILb0EJRKiRKdEEELb0EJS3_S5_EEclIZNKS7_8appendToINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEENSt9enable_ifIXsr12IsSomeStringIT_EE5valueEvE4typeERSH_EUlNS_5RangeIPKcEEE_EEvSK_
```

So in total this change results in ~5x per-call/instantiation binary size. It is possible to reduce binary size even further but it is not done in the current diff to keep it manageable.

In addition to binary size improvements, switching to fmt will potentially

* allow catching errors in format strings at compile time,
* simplify future migration to C++20 [`std::format`](http://eel.is/c++draft/format).

Reviewed By: simpkins

Differential Revision: D15485589

fbshipit-source-id: 06db4436839f11c2c3dbed7b36658e2193343411
2019-11-18 05:53:08 -08:00
Genevieve Helsel
5d2c5ae60a more helpful error message when calling status with out of date parent.
Summary: make the error message returned in the case of out of date parents during a new status call more user friendly and provide possible remediation instructions

Reviewed By: simpkins

Differential Revision: D18328835

fbshipit-source-id: b214f45bb055d008db8b233ddd2a1843332db838
2019-11-14 16:46:15 -08:00