<commit_before>package lmdbsync

import (
	"errors"
	"time"

	"github.com/bmatsuo/lmdb-go/lmdb"
)

type Handler interface {
	HandleTxnErr(c Bag, err error) (Bag, error)
}

// HandlerChain is a Handler implementation that iteratively calls each handler
// in the underlying slice when handling an error.
type HandlerChain []Handler

func (c HandlerChain) HandleTxnErr(b Bag, err error) (Bag, error) {
	for _, h := range c {
		b, err = h.HandleTxnErr(b, err)
		if err == nil {
			return b, nil
		}
	}
	return b, err
}

func (c HandlerChain) Append(h ...Handler) HandlerChain {
	_c := make(HandlerChain, len(c)+len(h))
	copy(_c, c)
	copy(_c[len(c):], h)
	return _c
}

// MapResizedHandler returns a Handler than transparently retrie Txns that
// failed to start due to MapResized errors.
func MapResizedHandler(maxRetry int, repeatDelay func(retry int) time.Duration) Handler {
	return &resizedHandler{
		RetryResize:       maxRetry,
		DelayRepeatResize: repeatDelay,
	}
}

// MapFullFunc is a function for resizing a memory map after it has become
// full.  The function receives the current map size as its argument and
// returns a new map size.  The new size will only be applied if the second
// return value is true.
type MapFullFunc func(size int64) (int64, bool)

// MapFullHandler returns a Handler that retries Txns that failed due to
// MapFull errors by increasing the environment map size according to fn.
//
// A lmdb.TxnOp which is handled by the returned Handler will execute multiple
// times in the occurrance of a MapFull error.
func MapFullHandler(fn MapFullFunc) Handler {
	return &mapFullHandler{fn}
}

// The default number of times to retry a transaction that is returning
// repeatedly MapResized. This signifies rapid database growth from another
// process or some bug/corruption in memory.
//
// If DefaultRetryResize is less than zero the transaction will be retried
// indefinitely.<commit_msg>document possible deadlocks with MapFullHandler and MapResizedHandler<commit_after>package lmdbsync

import (
	"errors"
	"time"

	"github.com/bmatsuo/lmdb-go/lmdb"
)

type Handler interface {
	HandleTxnErr(c Bag, err error) (Bag, error)
}

// HandlerChain is a Handler implementation that iteratively calls each handler
// in the underlying slice when handling an error.
type HandlerChain []Handler

func (c HandlerChain) HandleTxnErr(b Bag, err error) (Bag, error) {
	for _, h := range c {
		b, err = h.HandleTxnErr(b, err)
		if err == nil {
			return b, nil
		}
	}
	return b, err
}

func (c HandlerChain) Append(h ...Handler) HandlerChain {
	_c := make(HandlerChain, len(c)+len(h))
	copy(_c, c)
	copy(_c[len(c):], h)
	return _c
}

// MapResizedHandler returns a Handler than transparently retrie Txns that
// failed to start due to MapResized errors.
//
// When MapResizeHandler is in use transactions must not be nested inside other
// transactions.  Adopting the new map size requires all transactions to
// terminate first.  If any transactions wait for other transactions to
// complete they may cause a deadlock in the presence of a MapResized error.
func MapResizedHandler(maxRetry int, repeatDelay func(retry int) time.Duration) Handler {
	return &resizedHandler{
		RetryResize:       maxRetry,
		DelayRepeatResize: repeatDelay,
	}
}

// MapFullFunc is a function for resizing a memory map after it has become
// full.  The function receives the current map size as its argument and
// returns a new map size.  The new size will only be applied if the second
// return value is true.
type MapFullFunc func(size int64) (int64, bool)

// MapFullHandler returns a Handler that retries Txns that failed due to
// MapFull errors by increasing the environment map size according to fn.
//
// A lmdb.TxnOp which is handled by the returned Handler will execute multiple
// times in the occurrance of a MapFull error.
//
// When MapFullHandler is in use update transactions must not be nested inside
// view transactions (subtransactions are OK).  Resizing the database requires
// all transactions to terminate first.  If any transactions wait for update
// transactions to complete they may cause a deadlock in the presence of a
// MapFull error.
func MapFullHandler(fn MapFullFunc) Handler {
	return &mapFullHandler{fn}
}

// The default number of times to retry a transaction that is returning
// repeatedly MapResized. This signifies rapid database growth from another
// process or some bug/corruption in memory.
//
// If DefaultRetryResize is less than zero the transaction will be retried
// indefinitely.
{'fraction_non_alphanumeric': 0.07719453021614468, 'fraction_numerical': 0.00176444640494045, 'mean_word_length': 3.9293478260869565, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4856833', 'n_tokens_mistral': 1348, 'n_tokens_neox': 1309, 'n_words': 585}