func (be Backend) CheckDiskQuota(quota int64) (
	largeEngines []uuid.UUID,
	inProgressLargeEngines int,
	totalDiskSize int64,
	totalMemSize int64,
) {
	sizes := be.abstract.EngineFileSizes()
	sort.Slice(sizes, func(i, j int) bool {
		a, b := &sizes[i], &sizes[j]
		if a.IsImporting != b.IsImporting {
			return a.IsImporting
		}
		return a.DiskSize+a.MemSize < b.DiskSize+b.MemSize
	})
	for _, size := range sizes {
		totalDiskSize += size.DiskSize
		totalMemSize += size.MemSize
		if totalDiskSize+totalMemSize > quota {
			if size.IsImporting {
				inProgressLargeEngines++
			} else {
				largeEngines = append(largeEngines, size.UUID)
			}
		}
	}
	return
}
CheckDiskQuota verifies if the total engine file size is below the given
quota. If the quota is exceeded, this method returns an array of engines,
which after importing can decrease the total size below quota.
package backend
import (
	"context"
	"fmt"
	"sort"
	"time"
	"github.com/google/uuid"
	"github.com/pingcap/errors"
	"github.com/pingcap/failpoint"
	"github.com/pingcap/parser/model"
	"github.com/pingcap/tidb/store/tikv/oracle"
	"github.com/pingcap/tidb/table"
	"github.com/pingcap/tidb/types"
	"go.uber.org/zap"
	"github.com/pingcap/tidb-lightning/lightning/common"
	"github.com/pingcap/tidb-lightning/lightning/log"
	"github.com/pingcap/tidb-lightning/lightning/metric"
	"github.com/pingcap/tidb-lightning/lightning/verification"
)
const (
	maxRetryTimes = 3  
)
func makeTag(tableName string, engineID int32) string {
	return fmt.Sprintf("%s:%d", tableName, engineID)
}
func makeLogger(tag string, engineUUID uuid.UUID) log.Logger {
	return log.With(
		zap.String("engineTag", tag),
		zap.Stringer("engineUUID", engineUUID),
	)
}
func MakeUUID(tableName string, engineID int32) (string, uuid.UUID) {
	tag := makeTag(tableName, engineID)
	engineUUID := uuid.NewSHA1(engineNamespace, []byte(tag))
	return tag, engineUUID
}
var engineNamespace = uuid.MustParse("d68d6abe-c59e-45d6-ade8-e2b0ceb7bedf")
type EngineFileSize struct {
	UUID uuid.UUID
	DiskSize int64
	MemSize int64
	IsImporting bool
}
type AbstractBackend interface {
	Close()
	MakeEmptyRows() Rows
	RetryImportDelay() time.Duration
	ShouldPostProcess() bool
	NewEncoder(tbl table.Table, options *SessionOptions) (Encoder, error)
	OpenEngine(ctx context.Context, engineUUID uuid.UUID) error
	CloseEngine(ctx context.Context, engineUUID uuid.UUID) error
	ImportEngine(ctx context.Context, engineUUID uuid.UUID) error
	CleanupEngine(ctx context.Context, engineUUID uuid.UUID) error
	CheckRequirements(ctx context.Context) error
	FetchRemoteTableModels(ctx context.Context, schemaName string) ([]*model.TableInfo, error)
	FlushEngine(ctx context.Context, engineUUID uuid.UUID) error
	FlushAllEngines(ctx context.Context) error
	EngineFileSizes() []EngineFileSize
	ResetEngine(ctx context.Context, engineUUID uuid.UUID) error
	LocalWriter(ctx context.Context, engineUUID uuid.UUID, maxCacheSize int64) (EngineWriter, error)
}
func fetchRemoteTableModelsFromTLS(ctx context.Context, tls *common.TLS, schema string) ([]*model.TableInfo, error) {
	var tables []*model.TableInfo
	err := tls.GetJSON(ctx, "/schema/"+schema, &tables)
	if err != nil {
		return nil, errors.Annotatef(err, "cannot read schema '%s' from remote", schema)
	}
	return tables, nil
}
type Backend struct {
	abstract AbstractBackend
}
type engine struct {
	backend AbstractBackend
	logger  log.Logger
	uuid    uuid.UUID
}
type OpenedEngine struct {
	engine
	tableName string
	ts        uint64
}
type ClosedEngine struct {
	engine
}
type LocalEngineWriter struct {
	writer    EngineWriter
	tableName string
	ts        uint64
}
func MakeBackend(ab AbstractBackend) Backend {
	return Backend{abstract: ab}
}
func (be Backend) Close() {
	be.abstract.Close()
}
func (be Backend) MakeEmptyRows() Rows {
	return be.abstract.MakeEmptyRows()
}
func (be Backend) NewEncoder(tbl table.Table, options *SessionOptions) (Encoder, error) {
	return be.abstract.NewEncoder(tbl, options)
}
func (be Backend) ShouldPostProcess() bool {
	return be.abstract.ShouldPostProcess()
}
func (be Backend) CheckRequirements(ctx context.Context) error {
	return be.abstract.CheckRequirements(ctx)
}
func (be Backend) FetchRemoteTableModels(ctx context.Context, schemaName string) ([]*model.TableInfo, error) {
	return be.abstract.FetchRemoteTableModels(ctx, schemaName)
}
func (be Backend) FlushAll(ctx context.Context) error {
	return be.abstract.FlushAllEngines(ctx)
}