Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

[rpc] getblockchaininfo: add size_on_disk, prune_target_size #11367

Merged
merged 1 commit into from Oct 9, 2017

Conversation

Projects
None yet
10 participants
Contributor

esotericnonsense commented Sep 19, 2017

No description provided.

Contributor

esotericnonsense commented Sep 19, 2017

If #11359 gets in it might be nice to have the prune hwm in there too, but I didn't want to add the dependency.

concept ACK. One nit inline.

Consider adding an explicit test for the getblockchaininfo RPC method to test/functional/blockchain.py.

src/rpc/blockchain.cpp
@@ -1137,6 +1137,8 @@ UniValue getblockchaininfo(const JSONRPCRequest& request)
" \"chainwork\": \"xxxx\" (string) total amount of work in active chain, in hexadecimal\n"
" \"pruned\": xx, (boolean) if the blocks are subject to pruning\n"
" \"pruneheight\": xxxxxx, (numeric) lowest-height complete block stored\n"
+ " \"disk_size\": xxxxxx, (numeric) the estimated size of the block and undo files on disk\n"
@jnewbery

jnewbery Sep 19, 2017

Member

nit: perhaps disk_usage or size_on_disk?

Also consider placing this above pruned so all of the pruning-related fields are grouped.

@promag

promag Sep 19, 2017

Contributor

Also align description.

@promag

promag Sep 19, 2017

Contributor

IMO we should test the response result. In this case, at least, check that the key exists and value is a number. cc @jnewbery

@promag

promag Sep 19, 2017

Contributor

Ah, @jnewbery already recommended a test! 👍

src/rpc/blockchain.cpp
@@ -1180,6 +1182,7 @@ UniValue getblockchaininfo(const JSONRPCRequest& request)
obj.push_back(Pair("verificationprogress", GuessVerificationProgress(Params().TxData(), chainActive.Tip())));
obj.push_back(Pair("chainwork", chainActive.Tip()->nChainWork.GetHex()));
obj.push_back(Pair("pruned", fPruneMode));
+ obj.push_back(Pair("disk_size", CalculateCurrentUsage()));
@promag

promag Sep 19, 2017

Contributor

Missing lock of cs_LastBlockFile.

Contributor

promag commented Sep 20, 2017

Test for getblockchaininfo added in #11370.

@esotericnonsense esotericnonsense changed the title from RPC: getblockchaininfo: Add disk_size, prune_target_size to [rpc] getblockchaininfo: add size_on_disk, prune_target_size Sep 20, 2017

Contributor

esotericnonsense commented Sep 20, 2017

A few mishaps with the commit message there, sorry.

I have merged this with #11366 and closed #11366.

one more documentation nit. Otherwise looks good to me

src/rpc/blockchain.cpp
@@ -1135,8 +1135,10 @@ UniValue getblockchaininfo(const JSONRPCRequest& request)
" \"mediantime\": xxxxxx, (numeric) median time for the current best block\n"
" \"verificationprogress\": xxxx, (numeric) estimate of verification progress [0..1]\n"
" \"chainwork\": \"xxxx\" (string) total amount of work in active chain, in hexadecimal\n"
+ " \"size_on_disk\": xxxxxx, (numeric) the estimated size of the block and undo files on disk\n"
" \"pruned\": xx, (boolean) if the blocks are subject to pruning\n"
" \"pruneheight\": xxxxxx, (numeric) lowest-height complete block stored\n"
@jnewbery

jnewbery Sep 20, 2017

Member

The help text for pruneheight should also include "(only present if pruning is enabled)"

src/validation.h
@@ -156,6 +156,7 @@ struct BlockHasher
extern CScript COINBASE_FLAGS;
extern CCriticalSection cs_main;
+extern CCriticalSection cs_LastBlockFile;
@sipa

sipa Sep 21, 2017

Owner

I'd rather not expose more variables that are private to validation to the outside world.

Perhaps you can instead create a wrapper around CalculateCurrentUsage, which just grabs cs_LastBlockFile and calls the internal one, and expose that? That way the RPC code wouldn't need to know about the existence of that lock eve.

@promag

promag Sep 21, 2017

Contributor

Why not just lock cs_LastBlockFile in CalculateCurrentUsage? It's a recursive mutex and IMO should be locked where it's needed (BTW the same for remaining locks...).

src/rpc/blockchain.cpp
obj.push_back(Pair("pruned", fPruneMode));
+ if (fPruneMode) {
+ CBlockIndex *block = chainActive.Tip();
@promag

promag Sep 21, 2017

Contributor

CBlockIndex* block = ...;

src/validation.h
@@ -156,6 +156,7 @@ struct BlockHasher
extern CScript COINBASE_FLAGS;
extern CCriticalSection cs_main;
+extern CCriticalSection cs_LastBlockFile;
@promag

promag Sep 21, 2017

Contributor

Why not just lock cs_LastBlockFile in CalculateCurrentUsage? It's a recursive mutex and IMO should be locked where it's needed (BTW the same for remaining locks...).

src/rpc/blockchain.cpp
@@ -1168,7 +1170,7 @@ UniValue getblockchaininfo(const JSONRPCRequest& request)
+ HelpExampleRpc("getblockchaininfo", "")
);
- LOCK(cs_main);
+ LOCK2(cs_main, cs_LastBlockFile); // cs_LastBlockFile for CalculateCurrentUsage()
@jonasschnelli

jonasschnelli Sep 22, 2017

Member

As @sipa already commented, CalculateCurrentUsage() should be responsible for concurrency locking (not the calling code part).

src/rpc/blockchain.cpp
" \"pruned\": xx, (boolean) if the blocks are subject to pruning\n"
- " \"pruneheight\": xxxxxx, (numeric) lowest-height complete block stored\n"
+ " \"pruneheight\": xxxxxx, (numeric) lowest-height complete block stored (only present if pruning is enabled)\n"
+ " \"prune_target_size\": xxxxxx, (numeric) the target size used by pruning (only present if pruning is enabled)\n"
@jonasschnelli

jonasschnelli Sep 22, 2017

Member

Indentation seems wrong (others need to space-up).

@esotericnonsense

esotericnonsense Sep 22, 2017

Contributor

I followed the example of 'verificationprogress'; can indent the others further if you think that makes sense.

Member

jonasschnelli commented Sep 22, 2017

Concept ACK

Contributor

esotericnonsense commented Sep 22, 2017

Rebased on master, moved the lock into CalculateCurrentUsage, CBlockIndex *block => CBlockIndex* block.

Travis failed on one platform (iirc linux64) on a timeout in p2p-segwit last time. Not sure why. We'll see how it goes. edit: looks good.

Owner

sipa commented Sep 22, 2017

utACK 071879a

Member

jnewbery commented Sep 22, 2017

I've just tested this with -prune=1 and I get the bizarre result:

→ bitcoin-cli getblockchaininfo
{
...
  "prune_target_size": 18446744073709551615,

That's because of this section in init.cpp:

    nPruneTarget = (uint64_t) nPruneArg * 1024 * 1024;
    if (nPruneArg == 1) {  // manual pruning: -prune=1
        LogPrintf("Block pruning enabled.  Use RPC call pruneblockchain(height) to manually prune block and undo files.\n");
        nPruneTarget = std::numeric_limits<uint64_t>::max();
        fPruneMode = true;
...

Returning the max int for prune_target_size is meaningless and confusing. I recommend you don't return prune_target_size if bitcoind is configured for manual pruning (ie if -prune=1) (and perhaps also add another field pruning_mode that returns whether pruning is automatic or manual).

Contributor

esotericnonsense commented Sep 22, 2017

Hmmm. Yes, that isn't desirable behaviour.

Options I can see:
a) nPruneArg is exposed from init.cpp, or an fPruneManualMode (in which case it could be explicitly checked for in FindFilesToPrune)
or
b) the RPC checks for int_max to determine whether automatic pruning is disabled

b) fixes the RPC without having to touch pruning code but otherwise seems a bit messy to me.

Member

MeshCollider commented Sep 23, 2017

Or instead of b) just see if gArgs.GetArg("-prune", 0) is 1?
But yeah maybe adding a manual prune bool to validation.cpp would be more sensible

Member

jnewbery commented Sep 23, 2017

I think just testing the value of gArgs.GetArg("-prune", 0) is appropriate for this pr. No need to touch the init or validation code.

Contributor

esotericnonsense commented Sep 24, 2017

$ grep "prune" ~/.bitcoin/bitcoin.conf
prune=550
$ ./bitcoin-cli getblockchaininfo | grep "prune"
  "pruned": true,
  "pruneheight": 0,
  "pruneauto": true,
  "prune_target_size": 576716800,

$ grep "prune" ~/.bitcoin/bitcoin.conf
prune=1
$ ./bitcoin-cli getblockchaininfo | grep "prune"
  "pruned": true,
  "pruneheight": 0,
  "pruneauto": false,

$ grep "prune" ~/.bitcoin/bitcoin.conf
prune=0
$ ./bitcoin-cli getblockchaininfo | grep "prune"
  "pruned": false,
Contributor

promag commented Sep 24, 2017

Please rebase with #11370.

Contributor

esotericnonsense commented Sep 25, 2017

Rebased on master and added tests for the relevant fields in test/functional/blockchain.py.

My box:

...
blockchain.py                  | ✓ Passed  | 13 s
...
ALL                            | ✓ Passed  | 695 s (accumulated) 
Runtime: 180 s
src/rpc/blockchain.cpp
+
+ obj.push_back(Pair("pruneheight", block->nHeight));
+
+ bool fPruneAuto = (gArgs.GetArg("-prune", 0) > 1);
@jnewbery

jnewbery Sep 26, 2017

Member

current code style is snake_case for variables (https://github.com/bitcoin/bitcoin/blob/master/doc/developer-notes.md#developer-notes). prune_auto or auto_prune should be fine.

@jnewbery

jnewbery Sep 26, 2017

Member

nit: Since 1 is a magic number meaning manual pruning, I think it's clearer to use equality like in init.cpp, rather than greater-than:

        bool fPruneAuto = (gArgs.GetArg("-prune", 0) != 1);
@esotericnonsense

esotericnonsense Sep 26, 2017

Contributor

I was torn there, because that actually gives True in the case prune=0, but that case can never happen because execution would skip over the if (fPruneMode) block. I'll change it.

src/rpc/blockchain.cpp
+ obj.push_back(Pair("pruneheight", block->nHeight));
+
+ bool fPruneAuto = (gArgs.GetArg("-prune", 0) > 1);
+ obj.push_back(Pair("pruneauto", fPruneAuto));
@jnewbery

jnewbery Sep 26, 2017

Member

Please also use snake_case for RPC fields. I think automatic_pruning is appropriate here.

Implementation looks good. I've slightly tested and it works well.

A few style nits inline.

src/rpc/blockchain.cpp
+
+ obj.push_back(Pair("pruneheight", block->nHeight));
+
+ bool fPruneAuto = (gArgs.GetArg("-prune", 0) > 1);
@jnewbery

jnewbery Sep 26, 2017

Member

nit: Since 1 is a magic number meaning manual pruning, I think it's clearer to use equality like in init.cpp, rather than greater-than:

        bool fPruneAuto = (gArgs.GetArg("-prune", 0) != 1);
test/functional/blockchain.py
+ assert_equal(sorted(res.keys()), sorted(['pruneheight', 'pruneauto'] + keys))
+
+ # size_on_disk should be >= 0
+ assert res['size_on_disk'] >= 0
@jnewbery

jnewbery Sep 26, 2017

Member

assert_greater_than_or_equal() is better here (since it will print out the value of res['size_on_disk'] if the assert fails)

@esotericnonsense

esotericnonsense Sep 26, 2017

Contributor

As below I've dropped the 'equal to' because I don't see why it should ever be 0 unless there's some caching going on.

test/functional/blockchain.py
# pruneheight should be greater or equal to 0
assert res['pruneheight'] >= 0
+ # check other pruning fields given that prune=1
+ assert_equal(res['pruned'], True)
@jnewbery

jnewbery Sep 26, 2017

Member

No need for assert_equal when comparing a value to True or False. The following is fine:

assert res['pruned']
assert not res['pruneauto']
test/functional/blockchain.py
+ assert_equal(res['pruneheight'], 0)
+ assert_equal(res['pruneauto'], True)
+ assert_equal(res['prune_target_size'], 576716800)
+ assert_equal(res['size_on_disk'], 55550)
@jnewbery

jnewbery Sep 26, 2017

Member

suggest that you change this to assert that size_on_disk is greater than zero. This test would fail unnecessarily if a change in the implementation changed the size on disk.

Contributor

esotericnonsense commented Sep 26, 2017

Changes made and rebased on master (second push, first was a mistake).

Member

jnewbery commented Sep 26, 2017

Tested ACK 2b73ece

{
+ LOCK(cs_LastBlockFile);
@TheBlueMatt

TheBlueMatt Sep 27, 2017

Contributor

While you're at it can you add this lock to PruneOneBlockFile and GetBlockFileInfo (both of which are only called without lock during testing, so its not an actual issue, just annoying).

Member

MarcoFalke commented Sep 29, 2017

Needs rebase™

[rpc] getblockchaininfo: add size_on_disk, prune_target_size, automat…
…ic_pruning

Fix pruneheight help text.
Move fPruneMode block to match output ordering with help text.
Add functional tests for new fields in getblockchaininfo.
Contributor

esotericnonsense commented Sep 29, 2017

®ebased

Member

MarcoFalke commented Sep 30, 2017

utA©K b7dfc6c

Contributor

TheBlueMatt commented Oct 2, 2017

re-utACK b7dfc6c. In the future, can you avoid rebasing when squashing unless you need to? Avoiding rebasing onto latest master makes it easier for reviewers to identify what changed between reviews.

Contributor

esotericnonsense commented Oct 2, 2017

Yes, I can do that in the future. I hadn't considered that.
Do you prefer for each change to be made in an individual commit (with a squash before the PR is implemented)?

Member

MarcoFalke commented Oct 3, 2017

@laanwj laanwj merged commit b7dfc6c into bitcoin:master Oct 9, 2017

1 check passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details

laanwj added a commit that referenced this pull request Oct 9, 2017

Merge #11367: [rpc] getblockchaininfo: add size_on_disk, prune_target…
…_size


b7dfc6c [rpc] getblockchaininfo: add size_on_disk, prune_target_size, automatic_pruning (Daniel Edgecumbe)

Pull request description:

Tree-SHA512: c255c27d6c922434d203ffdefda0dd3dddbd765b6a9cce5f80f5af5cb0b1c11c8aff6f4d00e96a326701d0bc81aace2f216fd1985675aa979f76c16f564a6cf6

luke-jr added a commit to bitcoinknots/bitcoin that referenced this pull request Nov 11, 2017

[rpc] getblockchaininfo: add size_on_disk, prune_target_size, automat…
…ic_pruning

Fix pruneheight help text.
Move fPruneMode block to match output ordering with help text.
Add functional tests for new fields in getblockchaininfo.

Github-Pull: #11367
Rebased-From: b7dfc6c

luke-jr added a commit to bitcoinknots/bitcoin that referenced this pull request Nov 11, 2017

[rpc] getblockchaininfo: add size_on_disk, prune_target_size, automat…
…ic_pruning

Fix pruneheight help text.
Move fPruneMode block to match output ordering with help text.
Add functional tests for new fields in getblockchaininfo.

Github-Pull: #11367
Rebased-From: b7dfc6c
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment