[Modularization] add possibility to extend or overwrite RPC calls #5744

pull jonasschnelli wants to merge 4 commits into bitcoin:master from jonasschnelli:2015/02/rpc_flex_1 changing 5 files +82 −2
  1. jonasschnelli commented at 7:46 pm on February 3, 2015: contributor

    This will allow a upcomming modularization of the wallet or other components. Currently there is no use of the flexible RPC dispatch table.

    Because #5686 is getting to big, it might be a better approach to slice out independent changes which can be easily reviewed and tested.

  2. jonasschnelli force-pushed on Feb 3, 2015
  3. laanwj added the label RPC on Feb 4, 2015
  4. jonasschnelli referenced this in commit 6828277076 on Feb 4, 2015
  5. jonasschnelli referenced this in commit 7bd633c39a on Feb 4, 2015
  6. jtimon commented at 7:55 pm on February 13, 2015: contributor
    ut ACK
  7. in src/rpcserver.cpp: in ea66fb4ac6 outdated
    367@@ -368,6 +368,16 @@ const CRPCCommand *CRPCTable::operator[](string name) const
    368     return (*it).second;
    369 }
    370 
    371+void CRPCTable::AddOrReplaceCommand(const CRPCCommand command)
    372+{
    373+    // search after existing key in hashmap and remove it
    374+    map<string, const CRPCCommand*>::iterator it = mapCommands.find(command.name);
    


    sipa commented at 7:57 pm on February 13, 2015:
    Why is this lookup needed? You can just overwrite using the line you have below?

    jonasschnelli commented at 8:04 pm on February 13, 2015:
    Hmm… yes. Should be sufficient to just overwrite. Will change this.
  8. in src/rpcserver.cpp: in ea66fb4ac6 outdated
    367@@ -368,6 +368,16 @@ const CRPCCommand *CRPCTable::operator[](string name) const
    368     return (*it).second;
    369 }
    370 
    371+void CRPCTable::AddOrReplaceCommand(const CRPCCommand command)
    372+{
    373+    // search after existing key in hashmap and remove it
    


    sipa commented at 8:00 pm on February 13, 2015:
    map is also not a hashmap, but a treemap (but that shouldn’t really matter).
  9. dexX7 commented at 10:07 pm on March 4, 2015: contributor

    Hey @jonasschnelli,

    this is a very interesting idea. I faced some issues (segfaults and std::bad_alloc exceptions), probably related to object lifetime, and ended up passing const CRPCCommand* command, where the pointer is maintaned externally, which seemed more intuitive.

    From a practical perspective, value conversion is also a relevant topic, and editing vRPCConvertParams in rpcclient.cpp fails the goal of modularity, so I created json_conversion.h, to skip conversion tables and it can be used directly on Value objects with Cast<bool>(param[0]), Cast<int16_t>(param[1]), …

  10. jonasschnelli commented at 8:14 am on March 5, 2015: contributor
    @dexX7 Indeed. The vRPCConvertParams needs also modularization. I’ll check your implementation approach and will try to update this PR.
  11. jonasschnelli commented at 10:03 am on March 6, 2015: contributor

    @dexX7 i played around with your json_conversion.h implementation and it seems to be useful. How would you solution to the call RPCTypeCheck look like? I assume when skipping the vRPCConvertParams conversion the type check no longer works?

    We could get rid of the conversion via vRPCConvertParams but this would generate some changes (problem of testing/reviewing). Maybe the json_conversion.h should only be used for new calls.

  12. dexX7 commented at 9:51 am on March 7, 2015: contributor

    Good point, I didn’t really intend to replace the old system, but it was more like a quick workaround-ish solution, although I have to admit, I don’t like having a conversion table and still be required specify data types (e.g. get_str(), get_int(), …).

    I pushed three more conservative and similar, but slightly different each, approaches:

    As you may see, I’m a bit lost and undecided, design wise, but I hope it helps to push this further. :)

  13. jonasschnelli commented at 3:53 pm on March 13, 2015: contributor

    pulled in @dexX7 conversion table work. Fixed code nits mentioned by @sipa .

    A flexible RPC interface is required if we like to add capability to switch on/off certain modules. It’s also totally required to factor out/decouple the wallet from the rest of the code. It could be a intermediate stop in case of a new RPC implementation. But for now i think this is a feasible way. Reviewing this means helping bitcoind to get a new wallet-implenentation while a legacy wallet could still be enabled.

  14. [Modularization] add possibility to extend or overwrite RPC calls
    - this will allow a upcomming modularization of the wallet or other components
    3c3711e91c
  15. [Modularization] allow to add entries to the JSON conversion table
    - add method to insert custom conversion entries
    
    Conflicts:
    	src/test/rpc_tests.cpp
    5537c08c0b
  16. [Modularization] flexible RPC table overhaul bbee2ebdd5
  17. jonasschnelli force-pushed on Mar 13, 2015
  18. dexX7 commented at 7:14 pm on March 13, 2015: contributor
    Adding new commands is still an issue for me, if the scope is left. For example: https://gist.github.com/dexX7/32accc4b04cb2e7dd496
  19. jonasschnelli commented at 9:03 pm on March 13, 2015: contributor
    @dexX7 Thanks for the response. Yes. Bad memory management. Will have a look at it.
  20. jonasschnelli commented at 8:25 am on March 14, 2015: contributor

    @dexX7 i reviewed you gist https://gist.github.com/dexX7/32accc4b04cb2e7dd496. I would say the PR is acting correct. When adding a rpc command over the new call AddOrReplaceCommand() you have to make sure that your CRPCCommand struct stays in memory. In your gist you create your CRPCCommand within your function void addTestCommand() but then test it in another block. const CRPCCommand newCmd get freed after exiting void addTestCommand().

    I think one need to take the same approach to add commands to the vRPCCommands[] table as we do it for the standard rpc calls: static const CRPCCommand vRPCCommands[] = ....

    This is not perfect but would give a RPC flexibility with a diff-size of +82/−2.

  21. [Modularization] use pointers when adding or replacing RPC commands
    Using pointers signals the responsibility of managing object lifetime is in the hand of the caller.
    dac9278963
  22. in src/rpcserver.h: in bbee2ebdd5 outdated
    113@@ -114,6 +114,12 @@ class CRPCTable
    114     std::string help(std::string name) const;
    115 
    116     /**
    117+     * add or replace a CRPCCommand to the dispatch table
    118+     * @param command rpc command to add or replace
    119+     */ 
    120+    void AddOrReplaceCommand(const CRPCCommand command);
    


    dexX7 commented at 11:49 am on March 14, 2015:

    The devil is in the details here, I think. :) const CRPCCommand command creates copy of the original command, and the caller can maintain the original for the whole execution lifetime, but it would still break (try: the updated gist).

    It’s a slightly different story with RPCAddConversion(const std::string& method, int idx), because the lifetime the method name seems to be extended, where Temporary object lifetime, note 1 appears to apply to my understanding.

    Upfront: using const CRPCCommand& command works, but the caller must still take care of the lifetime, which is not very intuitive imho, as one might be tempted to believe it’s behavior is similar to the const std::string& s case, thus my comment about passing a pointer const CRPCCommand* instead, which makes it very clear that it’s the caller’s responsibility (in code: https://github.com/dexX7/bitcoin/commit/57b252e4c7665542dd6ff92b7e9aafab77d8811a).

    Messing around with object lifetime and pointers is a bit cumbersome and error prone in general in my opinion, so it might be worth to overthink the whole approach of storing pointers in mapCommands, but on the other hand, keeping changes minimal and doing it step by step probably yields results more quickly.


    jonasschnelli commented at 12:05 pm on March 14, 2015:
    You are totally right. It must be const CRPCCommand& command (passing pointers). I just pulled in your commit. I’m also aware that this pointer-passing-approche is not intuitive. But i’m still trying to keep the changeset-size at minimum. I also think a rpc calls will be added when the app starts (modules get loaded) then they stay alive until the app detects a shutdown so the lifetime management tend to be not so complex.
  23. jonasschnelli referenced this in commit d26edc1b5a on Mar 21, 2015
  24. jonasschnelli referenced this in commit 394e6a49df on Mar 21, 2015
  25. jonasschnelli referenced this in commit 674fc82c4a on Mar 21, 2015
  26. jonasschnelli referenced this in commit 07c3027982 on Mar 21, 2015
  27. jonasschnelli referenced this in commit d41f25a585 on Apr 12, 2015
  28. sipa commented at 3:05 pm on June 16, 2015: member
    Needs rebase.
  29. jonasschnelli commented at 3:23 pm on June 16, 2015: contributor
    @sipa: i think this solution is more flexible (and also less risky): #6006. Closing this.
  30. jonasschnelli closed this on Jun 16, 2015

  31. jonasschnelli referenced this in commit a6b659a6b0 on Jun 24, 2015
  32. MarcoFalke locked this on Sep 8, 2021

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-10-04 19:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me