| 941 | } |
| 942 | |
| 943 | func (cs *copyStatus) setError(err error) { |
| 944 | now := time.Now() |
| 945 | sh := cs.sh |
| 946 | br := cs.sb.Ref |
| 947 | if err == nil { |
| 948 | // This is somewhat slow, so do it before we acquire the lock. |
| 949 | // The queue is thread-safe. |
| 950 | if derr := sh.queue.Delete(br.String()); derr != nil { |
| 951 | sh.logf("queue delete of %v error: %v", cs.sb.Ref, derr) |
| 952 | } |
| 953 | } |
| 954 | |
| 955 | sh.mu.Lock() |
| 956 | defer sh.mu.Unlock() |
| 957 | if _, needCopy := sh.needCopy[br]; !needCopy { |
| 958 | sh.logf("IGNORING DUPLICATE UPLOAD of %v = %v", br, err) |
| 959 | return |
| 960 | } |
| 961 | delete(sh.copying, br) |
| 962 | if err == nil { |
| 963 | delete(sh.needCopy, br) |
| 964 | delete(sh.lastFail, br) |
| 965 | sh.recentCopyTime = now |
| 966 | sh.totalCopies++ |
| 967 | sh.totalCopyBytes += int64(cs.sb.Size) |
| 968 | sh.bytesRemain -= int64(cs.sb.Size) |
| 969 | return |
| 970 | } |
| 971 | |
| 972 | sh.totalErrors++ |
| 973 | sh.logf("error copying %v: %v", br, err) |
| 974 | sh.lastFail[br] = failDetail{ |
| 975 | when: now, |
| 976 | err: err, |
| 977 | } |
| 978 | |
| 979 | // Kinda lame. TODO: use a ring buffer or container/list instead. |
| 980 | if len(sh.recentErrors) == maxRecentErrors { |
| 981 | copy(sh.recentErrors, sh.recentErrors[1:]) |
| 982 | sh.recentErrors = sh.recentErrors[:maxRecentErrors-1] |
| 983 | } |
| 984 | sh.recentErrors = append(sh.recentErrors, br) |
| 985 | } |
| 986 | |
| 987 | func (cs *copyStatus) String() string { |
| 988 | var buf bytes.Buffer |