github.com/TrueBlocks/trueblocks-core/src/apps/chifra@v0.0.0-20241022031540-b362680128f7/internal/chunks/handle_check_sequential.go (about)

     1  // Copyright 2021 The TrueBlocks Authors. All rights reserved.
     2  // Use of this source code is governed by a license that can
     3  // be found in the LICENSE file.
     4  
     5  package chunksPkg
     6  
     7  import (
     8  	"fmt"
     9  
    10  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/base"
    11  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/types"
    12  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/utils"
    13  )
    14  
    15  // CheckSequential checks that the range of blocks in each of three arrays (onDisc,
    16  // LocalManifest, RemoteManifest) "cover" the range without gaps. (There may be a bug
    17  // for allow_missing chains where gaps are allowed.) It also makes sure than snap-to-grids
    18  // happen where they should and that non-snaps have at least appsPerChunks records and
    19  // snaps have exactly appsPerChunks records or less.
    20  func (opts *ChunksOptions) CheckSequential(fnArray, cacheArray, remoteArray []string, allowMissing bool, report *types.ReportCheck) error {
    21  	if err := opts.checkSequential("disc", fnArray, allowMissing, report); err != nil {
    22  		return err
    23  	}
    24  
    25  	if err := opts.checkSequential("cache", cacheArray, allowMissing, report); err != nil {
    26  		return err
    27  	}
    28  
    29  	if err := opts.checkSequential("contract", remoteArray, allowMissing, report); err != nil {
    30  		return err
    31  	}
    32  
    33  	return nil
    34  }
    35  
    36  // TODO: Can this be made concurrent?
    37  func (opts *ChunksOptions) checkSequential(which string, array []string, allowMissing bool, report *types.ReportCheck) error {
    38  	prev := base.NotARange
    39  	for _, item := range array {
    40  		var fR base.FileRange
    41  		var err error
    42  		if fR, err = base.RangeFromFilenameE(item); err != nil {
    43  			return err
    44  		}
    45  
    46  		w := utils.MakeFirstUpperCase(which)
    47  		if prev != base.NotARange {
    48  			report.VisitedCnt++
    49  			report.CheckedCnt++
    50  			if prev != fR {
    51  				if !prev.Preceeds(fR, !allowMissing) {
    52  					// try to figure out why
    53  					if prev.Intersects(fR) {
    54  						report.MsgStrings = append(report.MsgStrings, fmt.Sprintf("%s: file ranges intersect %s:%s", w, prev, fR))
    55  					} else if prev.Follows(fR, !allowMissing) {
    56  						report.MsgStrings = append(report.MsgStrings, fmt.Sprintf("%s: previous range is after current %s:%s", w, prev, fR))
    57  					} else if prev.Preceeds(fR, false) {
    58  						report.MsgStrings = append(report.MsgStrings, fmt.Sprintf("%s: gap in sequence %d to %d skips %d", w, prev.Last, fR.First, (fR.First-prev.Last-1)))
    59  					} else {
    60  						report.MsgStrings = append(report.MsgStrings, fmt.Sprintf("%s: files not sequental %s:%s", w, prev, fR))
    61  					}
    62  				} else {
    63  					report.PassedCnt++
    64  				}
    65  			} else {
    66  				report.MsgStrings = append(report.MsgStrings, fmt.Sprintf("%s: duplicate at %s", w, fR))
    67  			}
    68  		}
    69  		prev = fR
    70  	}
    71  	return nil
    72  }