Skip to content

Commit

Permalink
Fix sharing stuck because of a missing shared ref (#4309)
Browse files Browse the repository at this point in the history
It happens that the job for creating an io.cozy.shared has been lost
(stack restart for example), and we need to do something to avoid having
the sharing stuck. The most efficient way to do that is to check that
the file is actually in the sharing directory, and if it is the case, to
create the missing io.cozy.shared.
  • Loading branch information
nono committed Jan 31, 2024
2 parents 3070f1c + 101de60 commit 0638527
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 4 deletions.
32 changes: 32 additions & 0 deletions model/sharing/shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,38 @@ func extractDocReferenceFromID(id string) *couchdb.DocReference {
return &ref
}

func (s *Sharing) fixMissingShared(inst *instance.Instance, fileDoc *vfs.FileDoc) (SharedRef, error) {
var ref SharedRef
ref.SID = consts.Files + "/" + fileDoc.ID()
ref.Revisions = &RevsTree{Rev: fileDoc.Rev()}

rule, ruleIndex := s.findRuleForNewFile(fileDoc)
if rule == nil {
return ref, ErrSafety
}

sharingDir, err := s.GetSharingDir(inst)
if err != nil {
return ref, err
}
fs := inst.VFS()
pth, err := fileDoc.Path(fs)
if err != nil || !strings.HasPrefix(pth, sharingDir.Fullpath+"/") {
return ref, ErrSafety
}

ref.Infos = map[string]SharedInfo{
s.SID: {
Rule: ruleIndex,
Binary: true,
Removed: false,
},
}

err = couchdb.CreateNamedDoc(inst, &ref)
return ref, err
}

// CheckShared will scan all the io.cozy.shared documents and check their
// revision tree for inconsistencies.
func CheckShared(inst *instance.Instance) ([]*CheckSharedError, error) {
Expand Down
15 changes: 12 additions & 3 deletions model/sharing/upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ func (b *batchUpload) findNextFileToUpload() (map[string]interface{}, int, error
if len(results) == 0 {
b.Instance.Logger().WithNamespace("upload").
Warnf("missing results for bulk get %v", query)
return nil, 0, ErrInternalServerError
continue
}
if results[0]["_deleted"] == true {
b.Instance.Logger().WithNamespace("upload").
Expand Down Expand Up @@ -472,10 +472,19 @@ func (s *Sharing) SyncFile(inst *instance.Instance, target *FileDocWithRevisions

err = couchdb.GetDoc(inst, consts.Shared, sid, &ref)
if err != nil {
if couchdb.IsNotFoundError(err) {
if !couchdb.IsNotFoundError(err) {
return nil, err
}
// XXX It happens that the job for creating the io.cozy.shared has
// been lost (stack restart for example), and we need to do
// something to avoid having the sharing stuck. The most efficient
// way to do that is to check that the file is actually in the
// sharing directory, and if it is the case, to create the missing
// io.cozy.shared.
ref, err = s.fixMissingShared(inst, current)
if err != nil {
return nil, ErrSafety
}
return nil, err
}
if infos, ok := ref.Infos[s.SID]; !ok || (infos.Removed && !infos.Dissociated) {
return nil, ErrSafety
Expand Down
2 changes: 1 addition & 1 deletion tests/system/lib/couch.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def update_doc(domain, doctype, doc)
opts = {
content_type: "application/json"
}
id = doc["_id"]
id = doc["_id"].gsub("/", "%2F")
doctype = doctype.gsub(/\W/, '-')
@client["/#{prefix domain}%2F#{doctype}/#{id}"].put(doc.to_json, opts)
end
Expand Down
7 changes: 7 additions & 0 deletions tests/system/tests/multiple_sharings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,13 @@
child1_charlie = Folder.find inst_charlie, child1_charlie_id
assert_equal child1_charlie.name, child1_bob.name

# Check that the stack is not stuck when an io.cozy.shared has not been created
shared_bob = Helpers.couch.get_doc inst_bob.domain, "io.cozy.shared", "io.cozy.files%2f#{file_bob.couch_id}"
shared_bob["_deleted"] = true
Helpers.couch.update_doc inst_bob.domain, "io.cozy.shared", shared_bob
file.overwrite inst_alice
sleep 12

# Check that the files are the same on disk
da = File.join Helpers.current_dir, inst_alice.domain, folder.name
db = File.join Helpers.current_dir, inst_bob.domain,
Expand Down

0 comments on commit 0638527

Please sign in to comment.