When reading data from bitcoind, we can assume the hex data it gives us
is good and there is no need to validate on a per-character basis.
Thus, we use ParseHexFast to shave off cpu cycles (it's like 6x faster
than Qt's fromHex()).
This, along with the Util::ToHexFast() (which is 60% faster than
QByteArray::toHex()), will be used in performance critical code.
This hex parser is 5-6x faster than what we were using before, although
it does no real verification that the input is hex digits. Usable with
results returned from bitcoind, which is never going to be
malicious/malformed and thus we can rely on this non-checking hex
parser for the performance it offers (at the expense of verification).
This is more complex than what we had before -- but is more concurrent
and is more production-ready -- it can deal with failures better and now
we also poll bitcoind for new headers.
Still probably can be optimized somehwat -- but getting there!
Controller will manage BitcoinD and perhaps synching to bitcoind. It can
"see" all the servers as well as bitcoind.
Also refactored things a little bit and added some more startup sanity
checks.
It works! I still haven't figured out how to provoke the dreaded
"Workdepth exceeded" error .. but we pretty much drop the connection
anyway on anything too unexpected from bitcoind.
When the bitcoind manager class is written it will back off and try
again if too many disconnects happen.
For now though, the code we have is fast and works well against
bitcoind.
I restricted the possible underlying types it can contain down to
qint64, QString, and nullptr_t. This should make it more type safe since
we don't want it to inadvertently end up holding lists or maps
(previously it was a straight up QVariant).
It has a conversion to QVariant so it should work nicely.
- It's still a little more restrictive than the spec allows -- doesn't
like non-positive-int 'id'
- We not made the shuffle.spec status report back 'notifications' to the
client rather than repeated 'result' messages (as those would be out of
spec). The first response to a 'shuffle.spec' request is either
result="pending", result="accepted", or an error response
- Subsequent shuffle.spec status changes come as a method notification
for "shuffle.spec" with params=["accepted"] or params=["some error
message"]
Overall I think our bare bones JSON-RPC will at least not break now as
interop with other impls.
On Windows it still prints to console, however (without timestamps).
Note that syslog mode doesn't produce any debug output even if -d is
specified (at least on macOS) -- probably the sysadmin needs to
enable debug logging.
- Util::RunInThread to run a lambda in a thread
- App exit handling cleanup
- EXMgr uses an id for clients now
- EXMgr keeps track of lagging clients
- EXMgr more aggressive with reconnects if no valid exclients
- Nits and refactorings and misc. cleanup
- Already supports listening on as many sockets as you wish
- Each listening server has its own thread
- Will implement later: SSL server
Also refactored code a bit, created the generic "Controller" class, made
EXMgr and SrvMgr inherit from it.
ToDo: Figure out workflow for connections and clients, model client
sessions, etc.
- Only send server.ping on idle >1min (previously we sent
unconditionally once a minute)
- Added __attrubute__ format stuff to the printf-like log functions
- Small nit