Commit Graph

485 Commits

Author SHA1 Message Date
Katie Mancini
d850667e19 expose live FUSE requests
Summary:
This exposes metrics for the live FUSE requests (the duration
of the longest outstanding request and the number of outstanding
requests).

Because FUSE is the interface through which the user mostly interacts
with the file system they provide good metrics to judge if the perfomance
of eden is normal, or there may be an issue.

Exposing these counters this way will send them to ods, so it will not only
allow for debuging current issues, but can be used to look back at previous
problems. This data could also be used for alerting or more proactive
remediation.

Metrics are exposed per checkout to allow seeing which checkout was
having issues. This data will aggregated in `eden top` to be used as
an overall health indicator, but should more information be needed it
will be logged in ods.

Reviewed By: chadaustin

Differential Revision: D20922194

fbshipit-source-id: 16208883417acb77b62bf712cfdd9068c5420303
2020-04-22 12:33:34 -07:00
Zeyi (Rice) Fan
5758b21cde make HgProxyHash::getBatch return HgProxyHash instead of pair
Summary: It's a little weird to have get batch returns a pair of `RelativePath` and `Hash`.

Reviewed By: chadaustin

Differential Revision: D20844545

fbshipit-source-id: c0c823e0aca6ea2326cb637226dc0de43fd4f3cd
2020-04-14 20:30:33 -07:00
Zeyi (Rice) Fan
81eb3a1549 make HgProxyHash copyable & moveable
Summary: This diff makes `HgProxyHash` moveable & copyable so we can return it from `getBatch` method instead returning a pair of `RelativePath` & `Hash`. See next diff for usage.

Reviewed By: chadaustin

Differential Revision: D20841434

fbshipit-source-id: c082c217f75d53bcbfb4853e2055d1458a040188
2020-04-14 20:30:33 -07:00
Adam Simpkins
8ccbba9608 fix a couple compiler warnings about unhandled return code paths
Summary: gcc warned that these functions did not return with a value on all code paths.

Reviewed By: genevievehelsel

Differential Revision: D21004224

fbshipit-source-id: 3ccd38b19bb4f4c0dbe0b75b4d11f351b6690591
2020-04-13 16:54:10 -07:00
Zeyi (Rice) Fan
412131346e disable reading blob from union store
Summary:
This code isn't really working and is giving out corrupted file content. Let's remove it for reading blobs.

We still cannot remove the C++ mercurial code entirely as we rely on it to import manifests. I tested on switching to the Rust manifest implementation but it wasn't working due to new pack file scanning.

Reviewed By: chadaustin

Differential Revision: D20938001

fbshipit-source-id: 9cc7b1ed9cd8228afd6fc5374cda001d1309a379
2020-04-10 11:19:27 -07:00
Katie Mancini
7e58206c30 Explicitly track current/pending Imports -- fix pending imports
Summary:
Since imports are now queued in `HgQueuedBackingStore`
the metrics for queued imports were broken

the queueing use to happen in `HgBackingStore`, but
 now the queue happens before the imports get here,
 in `HgQueuedBackingStore`, thus these metrics were
only measuring live imports
=> this moves the metrics for queued imports into
`HgQueuedBackingStore` so that they capture both
live and queued imports

**note**: since prefetching in `HgQueuedBackingStore`
is in progress, these metrics are only set-up for when
prefetching this is finished

Reviewed By: chadaustin

Differential Revision: D20714494

fbshipit-source-id: 392337aaa60b44b75184889e6c92cb5d2c2577cc
2020-04-09 12:35:22 -07:00
Katie Mancini
e299b71988 Explicitly track current/pending imports -- refactor and expose current metrics
Summary:
As mentioned in D20629833, adding metrics for live
imports in `eden top` gives more transparency to the
imports process and makes identifying import related
issues easier. This is set up to expose metrics for live
imports like those for pending imports in `eden top`.

Similar to D20611728 exposing this via these counters
will log this data. Having this data persisted will allow
tracking the performance of imports, and does the set
up for more pro-active fixing of issues. Further we can
look back to see issues that are no longer occurring, but
still of interest.

This also refactors the registration code so that it requires
no copy pasting to add a new counter. Avoiding copy paste
errors when adding more counters and making it easier to
maintain.

Reviewed By: chadaustin

Differential Revision: D20630813

fbshipit-source-id: 8a7a2a0135c7b7a5cde960b84dcb434c6c99eaeb
2020-04-09 12:35:22 -07:00
Genevieve Helsel
959d1ef523 add remotenames extension to HgPrefetchTest
Reviewed By: simpkins

Differential Revision: D20875402

fbshipit-source-id: 7aa5828f27cc55ad9c9efeca421b64885584743f
2020-04-08 15:22:54 -07:00
Zeyi (Rice) Fan
bcc69fc668 implement prefetch for HgQueuedBackingStore
Summary: This is actually missing from `HgQueuedBackingStore`. This diff fixes this and assign low priority to these prefetch requests.

Reviewed By: chadaustin

Differential Revision: D20655681

fbshipit-source-id: f3c92b358e16e980390ac7adcae27d41ae5a7277
2020-04-06 19:12:42 -07:00
Zeyi (Rice) Fan
e32ec4398c make HgImportRequest more extensible and type safer
Summary: Ergonomics improvements. This allows us to have type safety instead of dynamically check for types at runtime.

Reviewed By: chadaustin

Differential Revision: D20740318

fbshipit-source-id: d0a3255105bef22dd236695be9fc9c4220547b83
2020-04-06 19:12:42 -07:00
Katie Mancini
0137a8ccb4 Explicitly track current/pending imports -- add current metrics
Summary:
Previously `eden top` shows metrics for imports that are queued
and fetching data (though there is a bug here fixed above), we
want to provide more granularity to help with debugging:

This explicitly separates "current" and "pending" imports:
- "live": The import is live, ie it is currently importing data
  - having this metric allows debugging the case that there
is a problem fetching data
- "pending": The import is queued, live, or getting data from the
cache
  - having this metric allows debugging the case that there is a
problem initiating the request, for example a request is being
starved on the queue

**note**: I moved the watches closer to the import function call
instead of renaming the currently broken pending import watches
to make it more clear in the code what these are suppose to be
timing

Reviewed By: chadaustin

Differential Revision: D20629833

fbshipit-source-id: 84ef75057149a648a51418a5cc93be87e3b3d6b5
2020-04-06 11:45:58 -07:00
Lee Howes
dead099771 Rename collectXSemiFuture to collectX
Summary:
Migration from Future-returning executor-erasing collectX forms to
SemiFuture-returning forms, that are less risky in particular with coroutines.

Earlier changes added collectXSemiFuture and collectXUnsafe as a migration
path. We then migrated collectX callsites to collectXSemiFuture or
collectXUnsafe and switched the implementation of collectX to the SemiFuture
form.

This diff renames uses of collectXSemiFuture to collectX, as the two are
identical.

Reviewed By: simpkins

Differential Revision: D20833464

fbshipit-source-id: c14aa40f8cce121632ff922300ef271721c1d695
2020-04-03 17:15:08 -07:00
Katie Mancini
944a471065 expose the longest outstanding import
Summary:
The primary purpose of exposing counters for the maximum length of duration is to add this to `eden top`.

As discussed in D20611704, the duration of time that imports are queued for is a strong indicator of the health of the import process. Adding it to `eden top` will help give users insight into what eden is doing when it hangs for a long time or when there is an issue, indicate whether that issue is due to the import process.

Additionally we choose to use these counters to expose this data because we want to log this data. This data can be used to measure performance of the queueing and import process. In the future this data could be used to set up alerting for regressions and allow more proactive fixes.

Reviewed By: chadaustin

Differential Revision: D20611728

fbshipit-source-id: 9307c1ad749ac5fe356ba9eaf868de41b1a8a3a7
2020-04-01 09:54:30 -07:00
Katie Mancini
69cd603aeb Track the duration of outstanding imports
Summary:
Here we are tracking the duration of each of the current imports in `HgBackingStore`. This changes is setup to display the duration of the longest outstanding import in `eden top`.

Displaying the duration of the longest import in eden top will help debug where the problem is when eden hangs. These specifically help determine if eden is hanging because of a queueing issue or not being able to fetch an object from the server.

This is a stronger signal to the user that there is an issue in importing over just a count of imports (the previous addition) because many pending imports is not always abnormal. For example a program may prefetch a big batch of files to read, and this could cause a large number of pending imports. A single import should not hang due to a big prefetch and other normal uses.

Thus we want to display this in addition to the number of imports and use this as our warning indicator. (i.e. a high duration of import will mark the metrics as yellow or red in `eden top` to give a warning to the user)

*code changes*:
- adding lists to store watches to time the duration of each of the imports in `HgBackingStore`
- removing the counters previously used to count the number of imports in `HgBackingStore` in favor of using the size of these lists as this is constant time, so there is no benefit to tracking this value ourselves

Reviewed By: chadaustin

Differential Revision: D20611704

fbshipit-source-id: 8bbe0aed8d10688f7bfb7ecfa2fa5ac181945a76
2020-04-01 09:54:29 -07:00
Wez Furlong
afe479ff4d eden: accomodate narrowing warnings on windows
Summary:
fixes up some functions to avoid narrowing warnings
and others to adopt `folly::to_narrow` to accept them.

This reduces the number of warnings in the windows build.

Reviewed By: chadaustin

Differential Revision: D20562026

fbshipit-source-id: f18ba50f914e142415d1efefebc6297e8c68d38e
2020-03-26 10:30:21 -07:00
Wez Furlong
0a6aa21d77 eden: fix multiply defined symbols issue with ImportPriority
Summary:
This is a rough pass that resolves a linker issue on MSVC by
switching to inline static member functions.

Reviewed By: chadaustin

Differential Revision: D20529163

fbshipit-source-id: 578ed440758c685091d3e039e261638e027db17a
2020-03-20 10:56:08 -07:00
Pádraig Brady
2fc5cacddc mononoke: adjust test to newer curl error code
Summary:
s/CURLE_SSL_CONNECT_ERROR/CURLE_RECV_ERROR/.
Note CURLE_SSL_CONNECT_ERROR is not explicitly checked in
code in the eden hierarchy (or anywhere else significant in fbcode).

Reviewed By: meyering

Differential Revision: D20490844

fbshipit-source-id: be4a66f49eb4a9eabaf73785f9a203f0aa6905a4
2020-03-17 08:59:27 -07:00
Zeyi (Rice) Fan
fff1c76996 make open calls from fuse high priority
Summary: This diff bumps the open call from FUSE to High priority (which is higher than any other blob open request atm). This has shown improvement on the user experience of EdenFS when it's importing many other things from other channels (thrift, etc.)

Reviewed By: chadaustin

Differential Revision: D20287389

fbshipit-source-id: 319bc44ef8be5c904d7cf0db7cc2f8be28b4760a
2020-03-17 02:31:25 -07:00
Zeyi (Rice) Fan
1bcaac2f19 eden: add HgQueuedBackingStore that implements a naive queue & worker
Summary: This diff implements `HgQueuedBackingStore` that uses `HgImportRequestQueue` to provide SCM data importing with priorities. This can allow us to customize how we import things and batch importing.

Reviewed By: chadaustin

Differential Revision: D19184826

fbshipit-source-id: da579b5bbff0b1449e9689e2c0159d4a3a475a83
2020-03-17 02:31:24 -07:00
Zeyi (Rice) Fan
0521a41147 add HgImportRequestQueue
Summary: This diff adds `HgImportRequestQueue` that is responsible for managing incoming requests by their priorities. This queue is later used in the `HgQueuedBackingStore` to prioritize works to the workers of the backing store.

Reviewed By: chadaustin

Differential Revision: D20197069

fbshipit-source-id: 246bbc086054a8021226e9ba6ab26d3bf0cfb7a3
2020-03-17 02:31:24 -07:00
Zeyi (Rice) Fan
7f0b3a77d4 eden: add HgImportRequest to represent an Hg import request
Summary:
This class is used to represent an import request that will be used later in the queue implementation.

When the EdenFS needs to import a blob, it creates an instance of this request and send it to the worker. Then it waits for the promise associated with the request.

In the future, we should be able to change the owned `Promise` into a non-owned `SemiFuture` to a `Promise` somewhere else for merging repetitive import requests.

Reviewed By: chadaustin

Differential Revision: D19184824

fbshipit-source-id: 823aabbed1156acf6306b7aefc76580a540d310d
2020-03-17 02:31:23 -07:00
Zeyi (Rice) Fan
2da686d315 add priority to BackingStore interface
Summary: This diff adds `Priority` added in the previous diff to the `BackingStore` interface with the default value set to `Priority::Normal`.

Reviewed By: chadaustin

Differential Revision: D20197071

fbshipit-source-id: a92f1b49bb82e3478042e5e3b79b047d834755ea
2020-03-17 02:31:23 -07:00
Zeyi (Rice) Fan
2fad7731c1 introduce ImportPriority
Summary:
This diff introduces a `Priority` type for EdenFS. This type is used to pass along the priority of a request.

The priority class itself contains two parts, `kind` and `offset`. `kind` uses the first 4-bytes and the reset 12-bytes are used to store offset. The idea is that we can roughly assign a priority kind to most of the requests and offset is used to dynamically tweak the priority of some particular requests. For example, when we saw a process is generate millions of requests we can use this to express "normal priority but less important than other process's normal priority".

Reviewed By: chadaustin

Differential Revision: D20287652

fbshipit-source-id: 9a849fb6cc6ba5e443fea978d5b4dc3ab8ca906a
2020-03-17 02:31:22 -07:00
Puneet Kaushik
ef671b4e4e Add BlobCache to Windows EdenMount
Reviewed By: simpkins

Differential Revision: D19956271

fbshipit-source-id: d5a88ea8570421a1c61900fbad8a0f9d3e311458
2020-03-10 12:27:50 -07:00
Lee Howes
f15fdeec84 collectX to collectUnsafe
Summary:
Migration from Future-returning executor-erasing collectX forms to
SemiFuture-returning forms, that are less risky in particular with coroutines.

Earlier diffs added SemiFuture and Unsafe versions. This codemod migrates
collect versions to the Unsafe versions to allow the basic collect versions to
be made safe.

Reviewed By: simpkins

Differential Revision: D20331206

fbshipit-source-id: efc8dff487d45f7d53ee55e8c4696bd3eed0e6da
2020-03-10 11:36:09 -07:00
Katie Mancini
b0a5ffb100 Expose number of imports queued
Summary: expose the counters for number of pending imports (blobs, trees, prefetches) to allow use in tooling

Reviewed By: chadaustin

Differential Revision: D20269853

fbshipit-source-id: d2b7e2110520290751699c4a891d41ebd5b374cf
2020-03-06 09:28:55 -08:00
Katie Mancini
4f0c4a1b04 Track number of imports queued
Summary:
adds a counter to track the imports queued to enable more statistics exposure.

- Add a counters to track the number of blob, tree, prefetch  imports that are in the pending

- have the counters increment (increment in constructor of wrapper struct) when the import is about to be queued

- have counters decrement once the load has completed (decrement in destructor of wrapper struct)

Reviewed By: chadaustin

Differential Revision: D20256410

fbshipit-source-id: 5536b46307b30fc19dc5747414727a86961c78e1
2020-03-05 09:03:06 -08:00
Katie Mancini
3a035094f8 Record Mercurial tree import time
Summary: - added logging only around the import tree call to capture non-queue related wait time

Reviewed By: chadaustin, fanzeyi

Differential Revision: D20207472

fbshipit-source-id: d88bb34ce224a26ff2be100d7789ddeff608006d
2020-03-03 11:44:28 -08:00
Katie Mancini
52e211fe8e Record Mercurial file import time
Summary:
- added logging only around the import blob call to capture non-queue related wait time
- added to `test_reading_file_gets_file_from_hg` in `integration.stats_test.HgBackingStoreStatsTest`  to test import blob logging in addition to the get blob loging

(not yet done for importing trees, will do in next diff)

Reviewed By: chadaustin

Differential Revision: D20201215

fbshipit-source-id: c89281fe7d3d6e89d111ac8cce9014adff44ac40
2020-03-03 11:44:27 -08:00
Shai Szulanski
42456710dd Add some missing transitive dependencies
Summary:
A bunch of files include folly/executors/GlobalExecutors.h transitively through thrift/lib/cpp2/async/Stream.h, which is going away. Explicitly include the header (and add dependency to target) in preparation for deleting Stream.h
drop-conflicts

Reviewed By: vitaut

Differential Revision: D20141838

fbshipit-source-id: 21c58cf82136287fc2d84ba5badec6b872106015
2020-03-02 08:54:49 -08:00
Zeyi (Rice) Fan
2222dbc1a5 fix HgPrefetchTest
Summary:
The problem is that the datapack files are not flushed to disk when it is prefetched. By having a pair of brackets around the `HgBackingStore`, it will ensure the `HgImporter` is closed by the time when we verify the prefetch with `hg cat` since it will terminate the `debugedenimporthelper` process in its destructor, which flushes the datapack files.

The real cause of the test failure is still unclear but I believe this is the correct way of doing this test.

Reviewed By: xavierd

Differential Revision: D20090249

fbshipit-source-id: 8e3966936a402c92311919433282027846d065e8
2020-02-25 10:14:29 -08:00
Luca Niccolini
3e92ce9f77 move AsyncSocket::OptionMap into SocketOptionMap (codemod)
Summary: so that it can be shared more easily with AsyncUDPSocket

Reviewed By: yangchi

Differential Revision: D19851480

fbshipit-source-id: ec8cdb852519724db6f89cf70c4a4169de5028b6
2020-02-21 17:25:23 -08:00
Lukasz Piatkowski
542d1f93d3 Manual synchronization of fbcode/eden and facebookexperimental/eden
Summary:
This commit manually synchronizes the internal move of
fbcode/scm/mononoke under fbcode/eden/mononoke which couldn't be
performed by ShipIt automatically.

Reviewed By: StanislavGlebik

Differential Revision: D19722832

fbshipit-source-id: 52fbc8bc42a8940b39872dfb8b00ce9c0f6b0800
2020-02-11 11:42:43 +01:00
Chad Austin
4e1f60fc24 log checkout type and fetch counts to scuba
Summary: In addition to duration and success, log object fetch counts and checkout type to Scuba.

Reviewed By: fanzeyi

Differential Revision: D19334276

fbshipit-source-id: dabf52427f2ebda2b58df93194df39d52f4fcb4f
2020-02-05 16:05:30 -08:00
Chad Austin
cb1c0b45f3 log fetch statistics after checkout
Summary: Log the number of object lookups and cache hit rates for a checkout operation.

Reviewed By: simpkins

Differential Revision: D19191201

fbshipit-source-id: 5e9ad501e704810f072dabcda3fce86d027c452e
2020-02-05 16:05:30 -08:00
Chad Austin
58f352b807 count fetch statistics during diff and checkout
Summary:
During checkout and stats, count every object fetch and which level of
cache it was served from.

Reviewed By: simpkins

Differential Revision: D19186333

fbshipit-source-id: fc0a74db297b9c723682e245996a7befd762f933
2020-02-05 16:05:29 -08:00
Chad Austin
fc07c3b6e6 add an ObjectFetchContext interface
Summary:
Add a fetch context interface to ObjectStore that allows tracing cache
hits, backing store fetches, and fetch durations in the context of a
diff or checkout operation.

Reviewed By: simpkins

Differential Revision: D19135625

fbshipit-source-id: d0d8f134b1c89f7ba4971a404a46a69a1704ba5c
2020-02-05 13:15:01 -08:00
Chad Austin
49102f1925 switch unsafe folly::collect calls to collectSafe
Summary:
There were some unsafe uses of folly::collect, especially in
the diff code. Switch to collectSafe.

Reviewed By: simpkins

Differential Revision: D19529784

fbshipit-source-id: e0ac920a2d2b44767a453f2c41a9166e72246ab6
2020-02-03 11:30:50 -08:00
Genevieve Helsel
946a517887 allow getScmStatus to be cancelled if it calls into source control tree differ
Summary: the request will be passed with the context, so simply check the context at all three "looping" points to see if the request was cancelled. I split this into its own diff due to its unique test plan.

Reviewed By: chadaustin

Differential Revision: D18647091

fbshipit-source-id: ccb7ac765f8f3b0a60e936779cc27b658b9fd8b9
2020-01-29 11:17:57 -08:00
Genevieve Helsel
4dc48ec7fa use gitignore in tree differ
Summary: Pass a GitIgnoreStack* and isIgnored flag through the diff operation. It is used later in the stack when we go down this code path in the TreeInode diffing code. When context->loadFileContentsFromPath() is null, the gitignore loading code will be ignored, used when we do not want to honor a gitignore file. For example, during `getScmStatusBetweenRevisions()`.

Reviewed By: chadaustin

Differential Revision: D18647089

fbshipit-source-id: 20d2abd2ef61669465e134165da5a0ac5e987cca
2020-01-29 11:17:55 -08:00
Chad Austin
600da9aef0 bump the assertKeySpaceInvariants to a newer MSVC
Summary: I reproduced the KeySpace.cpp ICE on my Windows 10 VM, so bump the MSVC version check. I have not confirmed it does not ICE on MSVC 2019.

Reviewed By: pkaush

Differential Revision: D19562325

fbshipit-source-id: 03cf84e95c709bb2ebe7c3e0055a4f290eb17f8a
2020-01-24 22:34:24 -08:00
Chad Austin
83bdc4120b when the import helper fails to start, indicate how to view the log
Summary:
It's not often obvious to people where edenfs.log is located on the
filesystem, so redirect people to `eden debug log` instead.

Reviewed By: simpkins

Differential Revision: D19560709

fbshipit-source-id: 6b031c80bab2c21dfddba4d7ec37d4e70218ea08
2020-01-24 13:22:18 -08:00
Chad Austin
68595a14a1 fix some macOS build warnings
Reviewed By: fanzeyi

Differential Revision: D19548525

fbshipit-source-id: 0f137dab2f5af659842cbbc120e2e12f91d18276
2020-01-23 17:37:39 -08:00
Chad Austin
f35f921d5d allow garbage collection of cached tree objects again
Summary:
Now that loading too many blobs only GCs the blob cache, treat cached
trees as ephemeral again.

Reviewed By: simpkins

Differential Revision: D19358375

fbshipit-source-id: 191427f46276f0f5d024b5bc923a68f7a42044da
2020-01-23 17:33:43 -08:00
Chad Austin
f7491f7741 add independent cache size limits per object type
Summary:
Instead of clearing every single cached object when the total size
exceeds the ephemeral storage limit, keep a limit per object type and
only clear those that exceed their quota.

Reviewed By: simpkins

Differential Revision: D19358312

fbshipit-source-id: 6918d6f4cc2931aed79a9025d0e0f357ede515e0
2020-01-21 19:41:47 -08:00
Chad Austin
e5e9d8cf69 clear the deprecated blobsize keyspace at startup
Summary:
EdenFS no longer uses the blobsize keyspace. To avoid wasting space,
clear and campact it on startup, along with any keyspaces we
deprecated in the future.

Reviewed By: fanzeyi

Differential Revision: D19354881

fbshipit-source-id: 5285757a0e44ab1080c5f940283e06b17bec811d
2020-01-21 10:33:11 -08:00
Chad Austin
d23773e9b0 restructure KeySpace and move it into KeySpace.h
Summary: Simplify the definition and use of KeySpace and move it into its own header.

Reviewed By: simpkins

Differential Revision: D19353441

fbshipit-source-id: ef07677d927a48839b709711388abeb3c1ed9679
2020-01-21 10:33:10 -08:00
Zeyi (Rice) Fan
1dcd227ccd eden: refresh union datapack store as well
Summary: This diff addresses the unreleased mapped pack files in the old datapack code.

Reviewed By: chadaustin

Differential Revision: D19399737

fbshipit-source-id: 86a6254a2939fd69e1ce2b25b8bfcb36b0deb16b
2020-01-17 15:00:01 -08:00
Zeyi (Rice) Fan
a431e64e4e eden: periodically refresh content store to give it chances to release mapped files
Summary:
As reported by JT, EdenFS may hold the file descriptor of mapped pack files too long even when it is deleted by external processes, thus taking more disk spaces.

This diff fixes this problem by making EdenFS periodically rescan the pack files.

Reviewed By: chadaustin

Differential Revision: D19395439

fbshipit-source-id: 4bfd6a7ac13dceb3099d2704d62b3825433aff4b
2020-01-17 15:00:01 -08:00
Zeyi (Rice) Fan
59c2cb7aff eden: make HgImporter safer
Summary:
We want to have a shared pool of `HgImporter` across different threads, but that would require `HgImporter` is safe to be *passed* between threads. (This is not making `HgImporter` entirely thread safe.)

However, `HgImporter` currently holds a pointer to the thread local fb303 counter. This diff pushes down `EdenStats` so we only access the thread local stats variable when we need to add counters. This might be a little slower but it does make it safer.

Reviewed By: chadaustin

Differential Revision: D19053250

fbshipit-source-id: 44a897acc90c6042ae22a0417eece39e099ee13f
2020-01-16 12:45:37 -08:00