@ -16,8 +16,16 @@
# include <common/utils.h>
# include <common/utils.h>
struct invoice_waiter {
struct invoice_waiter {
/* Is this waiter already triggered? */
bool triggered ;
bool triggered ;
/* Is this waiting for any invoice to resolve? */
bool any ;
/* If !any, the specific invoice this is waiting on */
u64 id ;
struct list_node list ;
struct list_node list ;
/* The callback to use */
void ( * cb ) ( const struct invoice * , void * ) ;
void ( * cb ) ( const struct invoice * , void * ) ;
void * cbarg ;
void * cbarg ;
} ;
} ;
@ -31,17 +39,55 @@ struct invoices {
struct timers * timers ;
struct timers * timers ;
/* The invoice list. */
/* The invoice list. */
struct list_head invlist ;
struct list_head invlist ;
/* Waiters waiting for any new invoice to be paid. */
/* Waiters waiting for invoices to be paid, expired, or delete d. */
struct list_head waitany_wait ers ;
struct list_head waiters ;
} ;
} ;
static void trigger_invoice_waiter ( struct invoice_waiter * w ,
static void trigger_invoice_waiter ( struct invoice_waiter * w ,
struct invoice * invoice )
const struct invoice * invoice )
{
{
w - > triggered = true ;
w - > triggered = true ;
w - > cb ( invoice , w - > cbarg ) ;
w - > cb ( invoice , w - > cbarg ) ;
}
}
static void trigger_invoice_waiter_resolve ( struct invoices * invoices ,
u64 id ,
const struct invoice * invoice )
{
const tal_t * tmpctx = tal_tmpctx ( invoices ) ;
struct invoice_waiter * w ;
struct invoice_waiter * n ;
list_for_each_safe ( & invoices - > waiters , w , n , list ) {
if ( ! w - > any & & w - > id ! = id )
continue ;
list_del_from ( & invoices - > waiters , & w - > list ) ;
tal_steal ( tmpctx , w ) ;
trigger_invoice_waiter ( w , invoice ) ;
}
tal_free ( tmpctx ) ;
}
static void
trigger_invoice_waiter_expire_or_delete ( struct invoices * invoices ,
u64 id ,
const struct invoice * invoice )
{
const tal_t * tmpctx = tal_tmpctx ( invoices ) ;
struct invoice_waiter * w ;
struct invoice_waiter * n ;
list_for_each_safe ( & invoices - > waiters , w , n , list ) {
if ( w - > any | | w - > id ! = id )
continue ;
list_del_from ( & invoices - > waiters , & w - > list ) ;
tal_steal ( tmpctx , w ) ;
trigger_invoice_waiter ( w , invoice ) ;
}
tal_free ( tmpctx ) ;
}
static bool wallet_stmt2invoice_details ( sqlite3_stmt * stmt ,
static bool wallet_stmt2invoice_details ( sqlite3_stmt * stmt ,
struct invoice * invoice ,
struct invoice * invoice ,
struct invoice_details * dtl )
struct invoice_details * dtl )
@ -72,7 +118,6 @@ static bool wallet_stmt2invoice_details(sqlite3_stmt *stmt,
dtl - > paid_timestamp = sqlite3_column_int64 ( stmt , 9 ) ;
dtl - > paid_timestamp = sqlite3_column_int64 ( stmt , 9 ) ;
}
}
list_head_init ( & invoice - > waitone_waiters ) ;
invoice - > expiration_timer = NULL ;
invoice - > expiration_timer = NULL ;
return true ;
return true ;
@ -90,7 +135,7 @@ struct invoices *invoices_new(const tal_t *ctx,
invs - > timers = timers ;
invs - > timers = timers ;
list_head_init ( & invs - > invlist ) ;
list_head_init ( & invs - > invlist ) ;
list_head_init ( & invs - > waitany_wait ers ) ;
list_head_init ( & invs - > waiters ) ;
return invs ;
return invs ;
}
}
@ -102,7 +147,6 @@ static void trigger_expiration(struct invoice *i)
struct invoices * invoices = i - > owner ;
struct invoices * invoices = i - > owner ;
u64 now = time_now ( ) . ts . tv_sec ;
u64 now = time_now ( ) . ts . tv_sec ;
sqlite3_stmt * stmt ;
sqlite3_stmt * stmt ;
struct invoice_waiter * w ;
assert ( i - > details - > state = = UNPAID ) ;
assert ( i - > details - > state = = UNPAID ) ;
@ -126,12 +170,7 @@ static void trigger_expiration(struct invoice *i)
sqlite3_bind_int64 ( stmt , 2 , i - > id ) ;
sqlite3_bind_int64 ( stmt , 2 , i - > id ) ;
db_exec_prepared ( invoices - > db , stmt ) ;
db_exec_prepared ( invoices - > db , stmt ) ;
/* Wake up all waiters. */
/* Wake up all waiters. */
while ( ( w = list_pop ( & i - > waitone_waiters ,
trigger_invoice_waiter_expire_or_delete ( invoices , i - > id , i ) ;
struct invoice_waiter ,
list ) ) ! = NULL ) {
tal_steal ( tmpctx , w ) ;
trigger_invoice_waiter ( w , i ) ;
}
tal_free ( tmpctx ) ;
tal_free ( tmpctx ) ;
} else
} else
@ -282,7 +321,6 @@ const struct invoice *invoices_create(struct invoices *invoices,
memcpy ( & invoice - > details - > r , & r , sizeof ( invoice - > details - > r ) ) ;
memcpy ( & invoice - > details - > r , & r , sizeof ( invoice - > details - > r ) ) ;
memcpy ( & invoice - > details - > rhash , & rhash , sizeof ( invoice - > details - > rhash ) ) ;
memcpy ( & invoice - > details - > rhash , & rhash , sizeof ( invoice - > details - > rhash ) ) ;
invoice - > details - > expiry_time = expiry_time ;
invoice - > details - > expiry_time = expiry_time ;
list_head_init ( & invoice - > waitone_waiters ) ;
invoice - > expiration_timer = NULL ;
invoice - > expiration_timer = NULL ;
/* Add to invoices object. */
/* Add to invoices object. */
@ -328,34 +366,24 @@ bool invoices_delete(struct invoices *invoices,
const struct invoice * cinvoice )
const struct invoice * cinvoice )
{
{
sqlite3_stmt * stmt ;
sqlite3_stmt * stmt ;
struct invoice_waiter * w ;
struct invoice * invoice = ( struct invoice * ) cinvoice ;
struct invoice * invoice = ( struct invoice * ) cinvoice ;
const tal_t * tmpctx = tal_tmpctx ( NULL ) ;
/* Delete from database. */
/* Delete from database. */
stmt = db_prepare ( invoices - > db , " DELETE FROM invoices WHERE id=?; " ) ;
stmt = db_prepare ( invoices - > db , " DELETE FROM invoices WHERE id=?; " ) ;
sqlite3_bind_int64 ( stmt , 1 , invoice - > id ) ;
sqlite3_bind_int64 ( stmt , 1 , invoice - > id ) ;
db_exec_prepared ( invoices - > db , stmt ) ;
db_exec_prepared ( invoices - > db , stmt ) ;
if ( sqlite3_changes ( invoices - > db - > sql ) ! = 1 ) {
if ( sqlite3_changes ( invoices - > db - > sql ) ! = 1 )
tal_free ( tmpctx ) ;
return false ;
return false ;
}
/* Delete from invoices object. */
/* Delete from invoices object. */
list_del_from ( & invoices - > invlist , & invoice - > list ) ;
list_del_from ( & invoices - > invlist , & invoice - > list ) ;
/* Tell all the waiters about the fact that it was deleted. */
/* Tell all the waiters about the fact that it was deleted. */
while ( ( w = list_pop ( & invoice - > waitone_waiters ,
trigger_invoice_waiter_expire_or_delete ( invoices ,
struct invoice_waiter ,
invoice - > id , NULL ) ;
list ) ) ! = NULL ) {
/* Acquire the watcher for ourself first. */
tal_steal ( tmpctx , w ) ;
trigger_invoice_waiter ( w , NULL ) ;
}
/* Free all watchers and the invoice. */
/* Free all watchers and the invoice. */
tal_free ( tmpctx ) ;
tal_free ( invoice ) ;
tal_free ( invoice ) ;
return true ;
return true ;
}
}
@ -386,7 +414,6 @@ void invoices_resolve(struct invoices *invoices,
u64 msatoshi_received )
u64 msatoshi_received )
{
{
sqlite3_stmt * stmt ;
sqlite3_stmt * stmt ;
struct invoice_waiter * w ;
struct invoice * invoice = ( struct invoice * ) cinvoice ;
struct invoice * invoice = ( struct invoice * ) cinvoice ;
s64 pay_index ;
s64 pay_index ;
u64 paid_timestamp ;
u64 paid_timestamp ;
@ -418,21 +445,8 @@ void invoices_resolve(struct invoices *invoices,
invoice - > details - > paid_timestamp = paid_timestamp ;
invoice - > details - > paid_timestamp = paid_timestamp ;
invoice - > expiration_timer = tal_free ( invoice - > expiration_timer ) ;
invoice - > expiration_timer = tal_free ( invoice - > expiration_timer ) ;
/* Tell all the waitany waiters about the new paid invoice. */
/* Tell all the waiters about the paid invoice. */
while ( ( w = list_pop ( & invoices - > waitany_waiters ,
trigger_invoice_waiter_resolve ( invoices , invoice - > id , invoice ) ;
struct invoice_waiter ,
list ) ) ! = NULL ) {
tal_steal ( tmpctx , w ) ;
trigger_invoice_waiter ( w , invoice ) ;
}
/* Tell any waitinvoice waiters about the specific invoice
* getting paid . */
while ( ( w = list_pop ( & invoice - > waitone_waiters ,
struct invoice_waiter ,
list ) ) ! = NULL ) {
tal_steal ( tmpctx , w ) ;
trigger_invoice_waiter ( w , invoice ) ;
}
/* Free all watchers. */
/* Free all watchers. */
tal_free ( tmpctx ) ;
tal_free ( tmpctx ) ;
@ -450,11 +464,15 @@ static void destroy_invoice_waiter(struct invoice_waiter *w)
/* Add an invoice waiter to the specified list of invoice waiters. */
/* Add an invoice waiter to the specified list of invoice waiters. */
static void add_invoice_waiter ( const tal_t * ctx ,
static void add_invoice_waiter ( const tal_t * ctx ,
struct list_head * waiters ,
struct list_head * waiters ,
bool any ,
u64 id ,
void ( * cb ) ( const struct invoice * , void * ) ,
void ( * cb ) ( const struct invoice * , void * ) ,
void * cbarg )
void * cbarg )
{
{
struct invoice_waiter * w = tal ( ctx , struct invoice_waiter ) ;
struct invoice_waiter * w = tal ( ctx , struct invoice_waiter ) ;
w - > triggered = false ;
w - > triggered = false ;
w - > any = any ;
w - > id = id ;
list_add_tail ( waiters , & w - > list ) ;
list_add_tail ( waiters , & w - > list ) ;
w - > cb = cb ;
w - > cb = cb ;
w - > cbarg = cbarg ;
w - > cbarg = cbarg ;
@ -500,7 +518,8 @@ void invoices_waitany(const tal_t *ctx,
sqlite3_finalize ( stmt ) ;
sqlite3_finalize ( stmt ) ;
/* None found. */
/* None found. */
add_invoice_waiter ( ctx , & invoices - > waitany_waiters , cb , cbarg ) ;
add_invoice_waiter ( ctx , & invoices - > waiters ,
true , 0 , cb , cbarg ) ;
}
}
@ -517,7 +536,8 @@ void invoices_waitone(const tal_t *ctx,
}
}
/* Not yet paid. */
/* Not yet paid. */
add_invoice_waiter ( ctx , & invoice - > waitone_waiters , cb , cbarg ) ;
add_invoice_waiter ( ctx , & invoices - > waiters ,
false , invoice - > id , cb , cbarg ) ;
}
}
void invoices_get_details ( const tal_t * ctx ,
void invoices_get_details ( const tal_t * ctx ,