Commit Graph

332 Commits

Author SHA1 Message Date
Stanislau Hlebik
4265e1bc7a mononoke: remove local_instances option from cmdlib
Summary:
`local_instances` option was used to create fileblobstore or sqlite blobstore.
Now we use mononoke config for this purpose. Since this option is no longer
useful let's delete it

Reviewed By: krallin

Differential Revision: D16120065

fbshipit-source-id: 375a168b27e7f2cf1a6a77f487c5e013f9004546
2019-07-04 08:03:51 -07:00
Simon Farnsworth
d804d9cc82 Introduce a "Scrub" blobstore
Summary:
`MultiplexedBlobstore` can hide errors up until we suddenly lose availabilty of the wrong blobstore. Introduce an opt-in `ScrubBlobstore`, which functions as a `MultiplexedBlobstore` but checks that the combination of blobstores and healer queue should result in no data loss.

Use this new blobstore in the blobrepo checker, so that we can be confident that data is safe.

Later, this blobstore should trigger the healer to fix "obvious" problems.

Reviewed By: krallin

Differential Revision: D15353422

fbshipit-source-id: 83bb73261f8ae291285890324473f5fc078a4a87
2019-07-02 05:32:02 -07:00
George-Catalin Tintareanu
f71269ddbd enable/disable censoring
Summary:
Added an option to control for which repositories should censoring be
enabled or disabled. The option is added in `server.toml` as `censoring` and it
is set to true or false. If `censoring` is not specified, then the default
option is set to true ( censoring is enabled).

By disabling `censoring` the verification if the key is blacklisted or not is
omitted, therefor all the files are fetchable.

Reviewed By: ikostia

Differential Revision: D16029509

fbshipit-source-id: e9822c917fbcec3b3683d0e3619d0ef340a44926
2019-07-02 05:04:34 -07:00
George-Catalin Tintareanu
cda81dea7d blacklist multiple files
Summary:
Subcommand `blacklist` to censor multiple files. It stores the censored keys of the blacklisted files in table censored_contents.
The subcommand takes as arguments
- list of files
- commit hash
- string, representing the task ID for censoring the files (the task should contain the reason why the files is censored)

Reviewed By: ikostia

Differential Revision: D15939450

fbshipit-source-id: 7261ab2358cc4905d61a14f354de2949a2a94e7c
2019-07-02 05:04:34 -07:00
George-Catalin Tintareanu
2128a3e507 CensoredBlob on top of PrefixBlobstore
Summary:
CensoredBlob was placed between Blobstore and PrefixBlobstore. I moved CensoredBlob, so that now it is a wrapper for PrefixBlobstore. This means the key is compared before appending the `repoid` to the key.

By moving CensoredBlob on top of PrefixBlobstore, it provides better isolation for the existing blobstores. This way CensoredBlob does not interact with the underlaying layers and future changes of those layers will, most probably, not impact CensoredBlob's implementation.

Reviewed By: ikostia

Differential Revision: D15900610

fbshipit-source-id: 391594355d766f43638f3152b56d4e9acf49af32
2019-07-02 04:18:48 -07:00
Pavel Aslanov
7c7e084825 Convert MPathElement to a newtype around Bytes
Summary: We are copying `MPath` a lot, this change should reduce amount of allocations and memory reuse for `MPath`

Reviewed By: farnz

Differential Revision: D15939495

fbshipit-source-id: 8da8f2c38f7b46f27d0df661210c9964aed52101
2019-06-21 15:40:55 -07:00
Kostia Balytskyi
f760f87a87 mononoke: make admin tool support bookmark deletion
Reviewed By: StanislavGlebik

Differential Revision: D15931177

fbshipit-source-id: cdc1e7f63c4bec486fe16729607089f36ae31c76
2019-06-21 02:35:27 -07:00
Thomas Orozco
7fa5666acf mononoke: admin: add bookmarks list command
Summary: This adds a command in Mononoke Admin to list all bookmarks.

Reviewed By: ikostia

Differential Revision: D15737660

fbshipit-source-id: 5d4e649adf09c5f601b149a87515707f3d88b203
2019-06-11 02:11:21 -07:00
Simon Farnsworth
65d5f79d78 Factor repetition in checker tasks
Summary: We have the same pattern 3 times, and I have at least two more instances of this pattern to add. Factor it out.

Reviewed By: StanislavGlebik

Differential Revision: D15202663

fbshipit-source-id: 9c0de8ccef71964e65389e0bf0f2b0fc383f7c1d
2019-05-30 08:02:45 -07:00
Thomas Orozco
5c5453af41 mononoke: fix bad help text
Summary: This help text was wrong. This fixes it.

Reviewed By: HarveyHunt

Differential Revision: D15555767

fbshipit-source-id: 5202d46a8527c9e44c5588d52f7425d3efb38898
2019-05-30 06:53:22 -07:00
Jeremy Fitzhardinge
820395cb2a Convert scm/mononoke to Rust 2018
Summary:
Rust 2018 updates to:
  //scm/mononoke:admin-rust-build-info-lib
  //scm/mononoke:aliasverify
  //scm/mononoke:aliasverify-rust-build-info-lib
  //scm/mononoke:aliasverify-unittest
  //scm/mononoke:blobimport
  //scm/mononoke:blobimport-rust-build-info-lib
  //scm/mononoke:blobimport-unittest
  //scm/mononoke:blobstore_healer-rust-build-info-lib
  //scm/mononoke:bonsai_verify
  //scm/mononoke:bonsai_verify-rust-build-info-lib
  //scm/mononoke:configlint-rust-build-info-lib
  //scm/mononoke:dumprev
  //scm/mononoke:dumprev-rust-build-info-lib
  //scm/mononoke:idxdump
  //scm/mononoke:idxdump-rust-build-info-lib
  //scm/mononoke:mononoke-rust-build-info-lib
  //scm/mononoke:populate_healer-rust-build-info-lib
  //scm/mononoke:revlogrepo
  //scm/mononoke:revlogrepo-rust-build-info-lib
  //scm/mononoke:revlogrepo-unittest

Reviewed By: fanzeyi

Differential Revision: D15465530

fbshipit-source-id: 616db5cc0a8584ccb05f4c3c446b1b3ffd343695
2019-05-23 11:14:19 -07:00
Thomas Orozco
77ba80ebd8 mononoke: Rename Bookmark to BookmarkName
Summary:
As part of adding support for infinitepush in Mononoke, we'll include additional server-side metadata on Bookmarks (specifically, whether they are publishing and pull-default).

However, we do use the name `Bookmark` right now to just reference a Bookmark name. This patch updates all reference to `Bookmark` to `BookmarkName` in order to free up `Bookmark`.

Reviewed By: StanislavGlebik

Differential Revision: D15364674

fbshipit-source-id: 126142e24e4361c19d1a6e20daa28bc793fb8686
2019-05-21 12:26:02 -07:00
Pavel Aslanov
39599a866d simplify phases API
Summary:
`Phases` currently have very ugly API, which is constant source of confusion. I've made following changes
- only return/cache public phases
- do not require `public_heads`  and always request them from `BlobRepo::get_bonsai_heads_maybe_stale`
- consolidated `HintPhases` and `SqlPhases`
- removed  `Hint` from types which does not carry any meaning
-  fixed all effected callsites

Reviewed By: StanislavGlebik

Differential Revision: D15344092

fbshipit-source-id: 848245a58a4e34e481706dbcea23450f3c43810b
2019-05-21 12:26:01 -07:00
Kostia Balytskyi
a4599001be mononoke: refactor the admin tool into components
Summary: Let's make it a bit more manageable.

Reviewed By: StanislavGlebik

Differential Revision: D15407978

fbshipit-source-id: 490e4d48c36349cf65171f38df0ef0372883281d
2019-05-21 12:25:59 -07:00
Simon Farnsworth
66d3219858 Assume repo is valid to increase concurrency
Summary: Exploit the fact that database parents are faster than blobstore reads to get more concurrency.

Reviewed By: aslpavel

Differential Revision: D15202668

fbshipit-source-id: e2f35f80531e4a558b40b969cb6d7b9434919a9f
2019-05-21 12:25:58 -07:00
Simon Farnsworth
ea84101a3c Refactor checker to make it easier to add more checking queues
Summary: I have three similar chunks of boilerplate code; there's two more that I plan to write. Factor it out.

Reviewed By: aslpavel

Differential Revision: D15202667

fbshipit-source-id: 16b7b2d44852679d33b44da57c003e7833539f00
2019-05-21 12:25:58 -07:00
Simon Farnsworth
85122c6876 Check HgChangesets in the checker
Summary: We can't recreate HgChangesets from Bonsai cleanly - we have imported with broken hashes created by Mercurial. Make sure that they're not lost in the checker.

Reviewed By: StanislavGlebik

Differential Revision: D15120894

fbshipit-source-id: 0eab8ad3924e961f3603dd465d87702f456be36f
2019-05-21 12:25:57 -07:00
Simon Farnsworth
d5cc10bc0e Blobrepo checker should validate database parents
Summary: When you ask a repo for parents, it goes to a database in preference to the blobstore. Compare the blobstore and database parents, to ensure they match

Reviewed By: aslpavel

Differential Revision: D15120890

fbshipit-source-id: 1123fba8c97865affe86c06965c78d70d61e3d7a
2019-05-21 12:25:57 -07:00
Simon Farnsworth
8421fb2080 Initial blobrepo checker
Summary:
When underlying storage layers give us trouble, we want to be able to validate that nothing is broken.

Use `BlobRepo` to fetch all the data for history of a given bookmark, so that we can be confident that we have sufficient data to not lose history.

Later diffs will add support for checking the saved Mercurial changesets, too

Reviewed By: StanislavGlebik

Differential Revision: D15084862

fbshipit-source-id: 8c7184cf1cd0d52ca2ca9c8ce1d7e97b1e51db6d
2019-05-21 12:25:57 -07:00
George-Catalin Tintareanu
19a8d1e711 mononoke: Add a noop admin subcommand for blacklisting
Summary: Practice commit. The behaviour will be implemented in the future

Reviewed By: ikostia

Differential Revision: D15372554

fbshipit-source-id: c9b3de81fcd2d79d34b8f8c898e28de2564cd887
2019-05-21 12:25:56 -07:00
Thomas Orozco
a728d3d8d3 mononoke: rustfmt cmds/admin/main.rs
Summary: I'm going to be doing some work on this file, but it's not up-to-date with rustfmt. To minimize merge conflicts and simplify diff reviews, I ran that earlier.

Reviewed By: StanislavGlebik

Differential Revision: D15364673

fbshipit-source-id: 32658629cc7ee29cdfc21be8dd526766d2dcbb0e
2019-05-21 12:25:55 -07:00
Thomas Orozco
119dab68af mononoke: rustfmt cmds/admin/bookmarks_manager.rs
Summary: I'm going to be doing some work on this file, but it's not up-to-date with rustfmt. To minimize merge conflicts and simplify diff reviews, I ran that earlier.

Reviewed By: StanislavGlebik

Differential Revision: D15364672

fbshipit-source-id: dd420ed8fc625142b686d08f6459148c73891a20
2019-05-21 12:25:55 -07:00
Stanislau Hlebik
0fe404988e mononoke: print bundle id to replay
Summary:
Printint id will make it easier to debug sync job problems (for example,
rewiding the latest replayed id counter)

Reviewed By: krallin

Differential Revision: D15322624

fbshipit-source-id: 5c94be9cc0dcced9df51162adb598b6498f1c749
2019-05-21 12:25:54 -07:00
Jeremy Fitzhardinge
48fc142093 mononoke/configlint: check locality
Reviewed By: StanislavGlebik

Differential Revision: D15167592

fbshipit-source-id: 474e1864468ec05ad0d974160deff29f099063ff
2019-05-21 12:25:45 -07:00
Jeremy Fitzhardinge
9b54d0f85b mononoke: move storage configuration to a common file
Summary:
This change has two goals:
- Put storage configuration that's common to multiple repos in a common place,
  rather than replicating it in each server.toml
- Allow tools that only operate on the blobstore level - like blobstore healing
  - to be configured directly in terms of the blobstore, rather than indirectly
    by using a representative repo config.

This change makes several changes to repo configuration:
1. There's a separate common/storage.toml which defines named storage
configurations (ie, a combination of a blobstore and metadata DB)
2. server.toml files can also define local storage configurations (mostly
useful for testing)
3. server.toml files now reference which storage they're using with
`storage_config = "name"`.
4. Configuration of multiplex blobstores is now explicit. Previously if a
server.toml defined multiple blobstores, it was assumed that it was a
multiplex. Now storage configuration only accepts a single blobstore config,
but that config can be explicitly a multiplexed blobstore, which has the
sub-blobstores defined within it, in the `components` field. (This is
recursive, so it could be nested, but I'm not sure if this has much value in
practice.)
5. Makes configuration parsing more strict - unknown fields will be treated as
an error rather than ignored. This helps flag problems in refactoring/updating
configs.

I've updated all the configs to the new format, both production and in
integration tests. Please review to make sure I haven't broken anything.

Reviewed By: StanislavGlebik

Differential Revision: D15065423

fbshipit-source-id: b7ce58e46e91877f4e15518c014496fb826fe03c
2019-05-21 12:25:44 -07:00
Jeremy Fitzhardinge
e56d695cec mononoke: use SqlConstructors label for local db names
Summary:
Seems redundant to also require callers to open_ssl to also pass a
(mostly) identical string.

Also make open_ssl special-case filenodes with sharding (though filenodes
aren't currently opened through it).

Reviewed By: StanislavGlebik

Differential Revision: D15157834

fbshipit-source-id: 0df45307f17bdb2c021673b3153606031008bee2
2019-05-21 12:25:44 -07:00
Jeremy Fitzhardinge
046abb21ad mononoke: Migrate to new config structures, leaving config files unchanged
Summary:
This migrates the internal structures representing the repo and storage config,
while retaining the existing config file format.

The `RepoType` type has been replaced by `BlobConfig`, an enum containing all
the config information for all the supported blobstores. In addition there's
the `StorageConfig` type which includes `BlobConfig`, and also
`MetadataDBConfig` for the local or remote SQL database for metadata.

Reviewed By: StanislavGlebik

Differential Revision: D15065421

fbshipit-source-id: 47636074fceb6a7e35524f667376a5bb05bd8612
2019-05-21 12:25:43 -07:00
Jeremy Fitzhardinge
4074965fdc mononoke/admin: refactor subcommands into their own functions
Summary: main() was getting ungainly

Reviewed By: aslpavel

Differential Revision: D15046903

fbshipit-source-id: 50d1ad8cb44f84f00247dc6435bac7cc8a194ca1
2019-05-21 12:25:42 -07:00
Stanislau Hlebik
79c14ef818 mononoke: print hg hashes of next log entries to replay
Summary:
Reads current replay counter, and where a bookmark would point to after this
bundle is replayed. That can be useful for debugging

Reviewed By: aslpavel

Differential Revision: D15216378

fbshipit-source-id: fd250e27c2a6d7ee407510561a36b820cc5a1d2b
2019-05-21 12:25:41 -07:00
Stanislau Hlebik
e5cdd1a5da mononoke: do not return boolean in BlobstoreSyncQueue interface
Summary:
In the later diff we'll add batching of BlobstoreSyncQueue writes. It would be
much harder to add the batching if we also have to return this boolean.

And since noboby uses it, let's just remove it

Reviewed By: farnz

Differential Revision: D15248290

fbshipit-source-id: 72c64770c1b023e9de23a5dfccd8b4482302fe96
2019-05-21 12:25:40 -07:00
Thomas Orozco
feba12ad67 mononoke: admin: make tests (actually) more deterministic
Summary:
The mononoke admin integration tests can be flaky when there is logging and an error, because those are respectively sent to stdout and stderr, which means they're not ordered relative to one another.

I attempted to fix this with minimal changes in D15146392, but that didn't solve the issue: StanislavGlebik reported that he still ran into a flaky test.

The reason for this is presumably that even though we write to stderr first then to stdout, there's no guarantee that the `.t` test runner will read whetever we output to stderr before it reads what we output to stdout.

I noted in that earlier diff that a more proper fix would be to write errors to stderr so they are indeed ordered relative to logging. That is what this diff does.

For consistency, I updated other fatal outcomes (bad arguments) to also log to stderr.

Reviewed By: StanislavGlebik

Differential Revision: D15181944

fbshipit-source-id: 3ca48870c39f11a7dcc57f1341f25ce61ccae360
2019-05-21 12:25:38 -07:00
Stanislau Hlebik
493fbc9557 mononoke: remove runhook
Summary:
1) I don't think anybody uses it
2) Hook tailer has the same functionality

Reviewed By: farnz

Differential Revision: D15216418

fbshipit-source-id: 698fc7d998475fe77ff7bf1ac55068ee75a34acc
2019-05-21 12:25:35 -07:00
Lukas Piatkowski
a7d5f76635 mononoke: using raw connection to xdb when myrouter_port is not provided
Summary:
In the case of mononoke's admin tool it's annoying for users to be required to run myrouter in the background and provide myrouter port to every command.
Thanks to this change it is no longer necessary to run admin commands through myrouter - the tool will simply use a direct connection to XDB using the sql crate.

It is important to note that the raw XDB connection via sql crate doesn't have connection pooling and doesn't handle XDB failover so it is crucial that it is never used for long-lived or request heavy use cases like running mononoke server or blobimport

Reviewed By: jsgf

Differential Revision: D15174538

fbshipit-source-id: 299d3d7941ae6aec31961149f926c2a4965ed970
2019-05-21 12:25:35 -07:00
Jeremy Fitzhardinge
4b35684cb7 mononoke/cmdlib: make get_repo_id return a proper error
Reviewed By: lukaspiatkowski

Differential Revision: D15046901

fbshipit-source-id: 603b4bc66e199e0ae12d000b6d7803b7e4bb72cb
2019-05-21 12:25:34 -07:00
Jeremy Fitzhardinge
dc7842f569 mononoke: make config parsing stricter
Summary:
Disallow unknown fields. They're generally the result of a mis-editing
a file and putting the config in the wrong place, or some incomplete refactor.

Reviewed By: StanislavGlebik

Differential Revision: D15168963

fbshipit-source-id: a9c9658378cda4866e44daf6e2c6bfbdfcdb9f84
2019-05-21 12:25:30 -07:00
Jeremy Fitzhardinge
dd5de99cc3 mononoke: add configlint to check Mononoke config sanity
Summary:
Currently this checks for:
- all referenced files are present
- they're well-formed toml
- all the required config keys are set, and no unknown ones are set
- blob storage and metadata db are both remote or local
- repo ids are not duplicated

Reviewed By: farnz

Differential Revision: D15068649

fbshipit-source-id: ace0e7bc52bf853ac42384c4346c3b73591312e4
2019-05-21 12:25:30 -07:00
Thomas Orozco
477670a03c make tests more deterministic
Summary:
One of the tests for mononoke admin (which I introduced recently) appears to be flaky. Sometimes, output from stdout (the error that terminates the program) and stderr (logs emitted while the program runs) is flipped.

I suspect this is caused by buffering, so this patch flushes all output before writing the error (if there was one).

An alternative approach here might be to write the final error to stderr instead of stdosut (so everything goes to stderr). That feels cleaner, but it does change the interface a little bit, so I didn't take that approach just yet. That said, if nobody objects, I'm happy to pick that approach instead.

Reviewed By: farnz

Differential Revision: D15146392

fbshipit-source-id: 67481afd4802cb48d24d19052988be4a83433efd
2019-05-21 12:25:28 -07:00
Thomas Orozco
c224058b2e Support hg-sync-bundle remains --without-blobimport
Summary: This adds the ability to exclude blobimport entries when querying the count of remaining entries in the HG sync replay log.

Reviewed By: ikostia

Differential Revision: D15097549

fbshipit-source-id: ae1a9a31f51a044924fdebbdd219fff1e2b3d46a
2019-05-21 12:25:25 -07:00
Thomas Orozco
8daba8e8c3 Support hg-sync-bundle last-processed --skip-blobimport
Summary:
This introduces a new `--skip` flag in Mononoke admin under `hg-sync-bundle last-processed`. This will update the last-synced counter to the last blobimport that preceeds a log entry that is no a blobimport.

In other words, it makes it so that the last change to be processed is *not* a blobimport.

It will fail if:

- There is no valid log entry to jump ahead to (e.g. all the further log entries are blobimports).
- The current change to be processed is not a blobimport.
- The mutable counter was changed by someone else in the meantime.

Reviewed By: ikostia

Differential Revision: D15081759

fbshipit-source-id: 8465321b08d9c7b5bc97526400518bcf3ac77f13
2019-05-21 12:25:24 -07:00
Thomas Orozco
1a05aaa1b2 Support hg-sync-bundle verify
Summary: This adds a command in mononoke admin to verify the consistency of remaining bundles to sync -- i.e. whether all bundles are blobimports or all of them are not blobimports.

Reviewed By: ikostia

Differential Revision: D15097935

fbshipit-source-id: a0df221c38e84897213edf232972ba420977e9d3
2019-05-21 12:25:24 -07:00
Thomas Orozco
ac4afd1f0b Fix SQLBookmarks name
Summary:
The code in admin/main.rs passes `bookmarks` as the name of the SQLBookmarks database, but other pieces of code (the server which writes this data, and the hg sync job that normally consumes it) use `books`.

This hasn't been a problem until now since no integration tests exist for the admin tool. This path mismatch was never exposed since in production we don't actually care about this name.

Reviewed By: ikostia, StanislavGlebik

Differential Revision: D15081757

fbshipit-source-id: c4fcd328568160023f3c15fa2ab7d77accf2ad68
2019-05-21 12:25:23 -07:00
Pavel Aslanov
3b6081a6f5 make it possible to enable bookmark cache from configs
Summary: Now it is possible to configure and enable/disable bookmark cache from configs

Reviewed By: StanislavGlebik

Differential Revision: D14952840

fbshipit-source-id: 3080f7ca4639da00d413a949547705ad480772f7
2019-05-21 12:25:22 -07:00
Zeyi (Rice) Fan
6bc1af095d update to Rust 1.34.0
Reviewed By: jsgf

Differential Revision: D14963608

fbshipit-source-id: 550d63cd10c52e8bcbb25137bc29811955da0b20
2019-05-21 12:25:14 -07:00
Jeremy Fitzhardinge
9fa31e9145 mononoke: runhook: convert to Rust 2018
Reviewed By: StanislavGlebik

Differential Revision: D14862997

fbshipit-source-id: 58a29c4d626edf61bcbb066f3082e90ff2bac289
2019-05-21 12:25:12 -07:00
Stanislau Hlebik
c3f991e0ed mononoke: allow fetching multiple entries
Summary: We'll do batching to save time on the sync job. We need to sync faster

Reviewed By: ikostia, farnz

Differential Revision: D14929027

fbshipit-source-id: 3139d0ece07f344cdafa5e39b698bc3b02625f0a
2019-05-21 12:25:09 -07:00
Stanislau Hlebik
43a96a4f52 mononoke: add a command to fetch a recorded bundle
Summary: It'll make investigation of failed syncs much easier.

Reviewed By: aslpavel

Differential Revision: D14747615

fbshipit-source-id: 1f9a7af58d065bc60d29e7deccbd51b89bf86dec
2019-05-21 12:25:00 -07:00
Stanislau Hlebik
0e5cca95b2 mononoke: prevent blobstore healer from overloading db
Differential Revision: D14699735

fbshipit-source-id: 1b62c1cfe5792462f0d705e8de2b11bac6b90cfe
2019-05-21 12:24:59 -07:00
Pavel Aslanov
a5ecb01926 tool to manually populate public phases
Summary: Tool to populate public commits

Reviewed By: HarveyHunt

Differential Revision: D14686428

fbshipit-source-id: 98457596c273ca2561bc457d35275bb15e5415e0
2019-05-21 12:24:58 -07:00
Kostia Balytskyi
27f73632e3 mononoke: add --quiet to the hg-sync-byndle remains admin subcommand
Summary: Easier to parse, per StanislavGlebik's request.

Reviewed By: StanislavGlebik

Differential Revision: D14707713

fbshipit-source-id: 6c9850d59fbf0204ad61cd72479df985219103ee
2019-05-21 12:24:54 -07:00
Igor Abramov
1bb5f676e4 add a command to mononoke_admin to list bookmark moves log
Summary:
Add a functionality to show the log of a bookmark i.e. show previous positions of the bookmark. It should look like

mononoke_admin bookmarks log master
2d0e180d7fbec1fd9825cfb246e1fecde31d8c35 push March 18, 15:03
9740f4b7f09a8958c90dc66cbb2c79d1d7da0555 push March 17, 15:03
b05aafb29abb61f59f12fea13a907164e54ff683 manual move March 17, 15:03
...

Reviewed By: StanislavGlebik

Differential Revision: D14639245

fbshipit-source-id: 59d6a559a7ba9f9537735fa2e36fbd0f3f9db77c
2019-05-21 12:24:54 -07:00