From c4a7b0524e2c89f5c67d074ea20fb92e0f638b20 Mon Sep 17 00:00:00 2001 From: Cory Slep Date: Fri, 15 Feb 2019 22:04:08 +0100 Subject: [PATCH] Always acquire db lock before calling Owns --- pub/database.go | 4 +--- pub/side_effect_actor.go | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/pub/database.go b/pub/database.go index 7f46a6c..a6dff4f 100644 --- a/pub/database.go +++ b/pub/database.go @@ -43,9 +43,7 @@ type Database interface { // Owns returns true if the database has an entry for the IRI and it // exists in the database. // - // TODO: Acquire a lock - // - // Owns is called without acquiring a lock. + // The library makes this call only after acquiring a lock first. Owns(c context.Context, id *url.URL) (owns bool, err error) // ActorForOutbox fetches the actor's IRI for the given outbox IRI. // diff --git a/pub/side_effect_actor.go b/pub/side_effect_actor.go index ebfb7f4..e6b2c15 100644 --- a/pub/side_effect_actor.go +++ b/pub/side_effect_actor.go @@ -175,11 +175,20 @@ func (a *sideEffectActor) InboxForwarding(c context.Context, inboxIRI *url.URL, if err != nil { return err } + err = a.db.Lock(c, iri) + if err != nil { + return err + } + // WARNING: Unlock is not deferred if owns, err := a.db.Owns(c, iri); err != nil { + a.db.Unlock(c, iri) return err } else if !owns { + a.db.Unlock(c, iri) continue } + a.db.Unlock(c, iri) + // Unlock by this point and in every branch above. myIRIs = append(myIRIs, iri) } // Finally, load our IRIs to determine if they are a Collection or @@ -483,21 +492,41 @@ func (a *sideEffectActor) hasInboxForwardingValues(c context.Context, inboxIRI * if err != nil { return false, err } + err = a.db.Lock(c, id) + if err != nil { + return false, err + } + // WARNING: Unlock is not deferred if owns, err := a.db.Owns(c, id); err != nil { + a.db.Unlock(c, id) return false, err } else if owns { + a.db.Unlock(c, id) return true, nil } + a.db.Unlock(c, id) + // Unlock by this point and in every branch above + // // Determine if we own the 'id' of any values on the properties we care // about. types, iris := getInboxForwardingValues(val) // For IRIs, simply check if we own them. for _, iri := range iris { + err = a.db.Lock(c, iri) + if err != nil { + return false, err + } + // WARNING: Unlock is not deferred if owns, err := a.db.Owns(c, iri); err != nil { + a.db.Unlock(c, iri) return false, err } else if owns { + a.db.Unlock(c, iri) return true, nil } + a.db.Unlock(c, iri) + // Unlock by this point and in every branch above + // // Attempt to dereference the IRI instead, and add it to the // types we need to examine. tport, err := a.common.NewTransport(c, inboxIRI, goFedUserAgent())