check and log errors more often in deferred cleanup calls, and log remote-induced errors at lower priority

We normally check errors for all operations. But for some cleanup calls, eg
"defer file.Close()", we didn't. Now we also check and log most of those.
Partially because those errors can point to some mishandling or unexpected code
paths (eg file unexpected already closed). And in part to make it easier to use
"errcheck" to find the real missing error checks, there is too much noise now.

The log.Check function can now be used unconditionally for checking and logging
about errors. It adjusts the log level if the error is caused by a network
connection being closed, or a context is canceled or its deadline reached, or a
socket deadline is reached.
This commit is contained in:
Mechiel Lukkien
2025-03-24 13:46:08 +01:00
parent 15a8ce8c0b
commit a2c79e25c1
38 changed files with 337 additions and 161 deletions

View File

@ -5,6 +5,8 @@ import (
"os"
"golang.org/x/crypto/blake2b"
"github.com/mjl-/mox/mlog"
)
// see https://en.wikipedia.org/wiki/Bloom_filter
@ -18,6 +20,8 @@ type Bloom struct {
k int // Number of bits we store/lookup in the bloom filter per value.
w int // Number of bits needed to address a single bit position.
modified bool
log mlog.Log // For cid logging.
}
func bloomWidth(fileSize int) int {
@ -55,7 +59,7 @@ func bloomValid(fileSize, k int) (int, error) {
// For each value stored/looked up, a hash over the value is calculated. The hash
// is split into "k" values that are "width" bits wide, each used to lookup a bit.
// K * width must not exceed 256.
func NewBloom(data []byte, k int) (*Bloom, error) {
func NewBloom(log mlog.Log, data []byte, k int) (*Bloom, error) {
w, err := bloomValid(len(data), k)
if err != nil {
return nil, err
@ -65,6 +69,7 @@ func NewBloom(data []byte, k int) (*Bloom, error) {
data: data,
k: k,
w: w,
log: log,
}, nil
}
@ -112,7 +117,8 @@ func (b *Bloom) Write(path string) error {
return err
}
if _, err := f.Write(b.data); err != nil {
f.Close()
xerr := f.Close()
b.log.Check(xerr, "closing bloom file after write failed")
return err
}
if err := f.Close(); err != nil {

View File

@ -3,6 +3,8 @@ package junk
import (
"fmt"
"testing"
"github.com/mjl-/mox/mlog"
)
func TestBloom(t *testing.T) {
@ -10,12 +12,13 @@ func TestBloom(t *testing.T) {
t.Fatalf("missing error for invalid bloom filter size")
}
_, err := NewBloom(make([]byte, 3), 10)
log := mlog.New("junk", nil)
_, err := NewBloom(log, make([]byte, 3), 10)
if err == nil {
t.Fatalf("missing error for invalid bloom filter size")
}
b, err := NewBloom(make([]byte, 256), 5)
b, err := NewBloom(log, make([]byte, 256), 5)
if err != nil {
t.Fatalf("newbloom: %s", err)
}

View File

@ -80,7 +80,7 @@ func (f *Filter) ensureBloom() error {
return nil
}
var err error
f.bloom, err = openBloom(f.bloomPath)
f.bloom, err = openBloom(f.log, f.bloomPath)
return err
}
@ -105,7 +105,8 @@ func (f *Filter) Close() error {
err = f.Save()
}
if err != nil {
f.db.Close()
xerr := f.db.Close()
f.log.Check(xerr, "closing junk filter after error")
} else {
err = f.db.Close()
}
@ -117,7 +118,7 @@ func OpenFilter(ctx context.Context, log mlog.Log, params Params, dbPath, bloomP
var bloom *Bloom
if loadBloom {
var err error
bloom, err = openBloom(bloomPath)
bloom, err = openBloom(log, bloomPath)
if err != nil {
return nil, err
}
@ -213,12 +214,12 @@ func NewFilter(ctx context.Context, log mlog.Log, params Params, dbPath, bloomPa
const bloomK = 10
func openBloom(path string) (*Bloom, error) {
func openBloom(log mlog.Log, path string) (*Bloom, error) {
buf, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("reading bloom file: %w", err)
}
return NewBloom(buf, bloomK)
return NewBloom(log, buf, bloomK)
}
func newDB(ctx context.Context, log mlog.Log, path string) (db *bstore.DB, rerr error) {

View File

@ -209,7 +209,9 @@ func (f *Filter) tokenizeText(r io.Reader, words map[string]struct{}) error {
peekLetter := func() bool {
c, _, err := br.ReadRune()
br.UnreadRune()
if err == nil {
err = br.UnreadRune()
}
return err == nil && unicode.IsLetter(c)
}