Skip to content
New issue

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

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

db-write hook #2421

Merged
merged 12 commits into from Apr 8, 2019
Merged

Conversation

rustyrussell
Copy link
Contributor

@rustyrussell rustyrussell commented Mar 1, 2019

It's a bit limited (see final commits for caveats) but it works.

See #2400

@rustyrussell
Copy link
Contributor Author

Hmm, needs sqlite3 v3.14 or above. Not sure what that would break if we include it, might have to make hook optional? Yech...

@cdecker
Copy link
Member

cdecker commented Mar 4, 2019

I was expecting to see an implementation of sqlite3_expanded_sql took me while to figure out that it is actually a native sqlite3 function. Maybe we can shim this? This hook seems far too useful not to exist. Notice though that it makes switching DBs even harder since plugins now may depend on the sqlite3 dialect being used.

Copy link
Collaborator

@niftynei niftynei left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

really like the db_select_step improvements.

may be worth noting that in theory, your 'backup' copy may be one command set ahead of the actual on disk database if it crashes/fails during write... tho i guess that's actually the point eh. :)

i should note that i didn't review the io_loop_exclusive additions very carefully because it looked like a straight ccan update.

wallet/db.h Outdated
/**
* db_select_step -- iterate through db results.
*
* Returns false and frees stmt if we've we've reached end, otherwise
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Returns false and frees stmt if we've we've reached end, otherwise
* Returns false and frees stmt if we've reached end, otherwise

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


1. a plugin registering for this hook should not perform anything that may cause
a db operation in response (pretty much, anything but logging).
2. a plugin registering for this hook should not register for other hooks or
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we canonize this by returning an error if this is broken?

*
* This allows you to temporarily service only one (or several) fds.
* For example, you might want to flush out one io_conn and not
* receive any new connections or read any otherninput.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* receive any new connections or read any otherninput.
* receive any new connections or read any other input.

* For example, you might want to flush out one io_conn and not
* receive any new connections or read any otherninput.
*
* Returns true of there any exclusive io_conn remain, otherwise false.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Returns true of there any exclusive io_conn remain, otherwise false.
* Returns true if any exclusive io_conn remain, otherwise false.

Replace with an explicit test for existence.  This simplifies our db interface.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
I was tempted to create a new db_select_stmt wrapper type, but that means
a lot of boilerplate around binding, which expects to work with db_prepare
*and* db_select_prepare.

This lets us clearly differentiate between db queries (which don't need to
go to a plugin) and db changes (which do).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
@rustyrussell
Copy link
Contributor Author

I was expecting to see an implementation of sqlite3_expanded_sql took me while to figure out that it is actually a native sqlite3 function. Maybe we can shim this? This hook seems far too useful not to exist. Notice though that it makes switching DBs even harder since plugins now may depend on the sqlite3 dialect being used.

I think we can try to use the (now obsolete) sqlite3 tracing feature to simulate this in older sqlite3. Let me try.

@rustyrussell
Copy link
Contributor Author

really like the db_select_step improvements.

may be worth noting that in theory, your 'backup' copy may be one command set ahead of the actual on disk database if it crashes/fails during write... tho i guess that's actually the point eh. :)

Yes, but in this case both dbs are "valid". You could naively copy the whole db in the plugin every startup, but better would be a separate "db_init" hook, which would use https://www.sqlite.org/c3ref/c_fcntl_begin_atomic_write.html#sqlitefcntldataversion, and give plugin the version startup time.

If the plugin also has an sqlite3 db, that's a trivial check, and if not, it can fall back to copy.

@rustyrussell
Copy link
Contributor Author

OK, put in backwards compat shim, rebased.

@rustyrussell rustyrussell force-pushed the guilt/db-hook branch 4 times, most recently from 4b5124c to 4395d9e Compare March 17, 2019 03:00
For the moment we just dump them to stderr, but later this will go to a hook.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
…sly.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
I started by trying to change the current infrastructure, but this is
really the only completely sync hook which makes sense; it needs to avoid
doing the db_transation, as well as waiting, and using a callback is just
overkill.

So with some regret, I open coded it.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
In theory we could allow a db_write-using plugin to have other
hooks/commands by embargoing their other responses until the exclusive
period is over.  That would be nice for a 'dbmirrorinfo' command, for
example.

The other option would be to *always* go exclusive on a db_write-using
plugin, so responses can never get intermingled.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
We didn't include stdlib, so these tests "failed" due to implicit
declaration of exit().

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
…-08-08)

Our Travis, for example, doesn't have 3.14.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Suggested-by: @niftynei
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
@rustyrussell
Copy link
Contributor Author

Ack 1d776eb

Let's get it in so we can make progress :)

@rustyrussell rustyrussell merged commit f4d44d8 into ElementsProject:master Apr 8, 2019
@Coinomatron
Copy link

Updated to the latest commits, it's not clear to me how this backup function works. Can someone give a brief explanation?

@cdecker
Copy link
Member

cdecker commented Apr 11, 2019

Updated to the latest commits, it's not clear to me how this backup function works. Can someone give a brief explanation?

It's not a backup mechanism on its own, it is the infrastructure necessary to write backup plugins on top.

@Coinomatron
Copy link

Ah, thanks.

@cdecker
Copy link
Member

cdecker commented Apr 11, 2019

No problem, we'll get a move on and get some example implementations soon :-)

@Coinomatron
Copy link

Any updates on this?

@ZmnSCPxj
Copy link
Collaborator

ZmnSCPxj commented Dec 17, 2019

My last information is that @jb55 was working on some backup system that utilizes this.

@jb55
Copy link
Collaborator

jb55 commented Dec 17, 2019

oh yeah I should start that

@jb55
Copy link
Collaborator

jb55 commented Dec 17, 2019

hmm now that you reminded me, I didn't go that route as I was going to see how the postgresql backend played out. if you could use a postgresql backend that replicates offsite, that perhaps could solve the problem as well? cc @cdecker

although that's not very user friendly, so perhaps a plugin is still in order...

that makes me wonder how this interacts with the multi-db abstraction now... 🤔 I haven't looked at the code in either case yet

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants