github.com/ethereum/go-ethereum@v1.14.3/core/rawdb/ancient_utils.go (about)

     1  // Copyright 2022 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package rawdb
    18  
    19  import (
    20  	"fmt"
    21  	"path/filepath"
    22  
    23  	"github.com/ethereum/go-ethereum/common"
    24  	"github.com/ethereum/go-ethereum/ethdb"
    25  )
    26  
    27  type tableSize struct {
    28  	name string
    29  	size common.StorageSize
    30  }
    31  
    32  // freezerInfo contains the basic information of the freezer.
    33  type freezerInfo struct {
    34  	name  string      // The identifier of freezer
    35  	head  uint64      // The number of last stored item in the freezer
    36  	tail  uint64      // The number of first stored item in the freezer
    37  	sizes []tableSize // The storage size per table
    38  }
    39  
    40  // count returns the number of stored items in the freezer.
    41  func (info *freezerInfo) count() uint64 {
    42  	return info.head - info.tail + 1
    43  }
    44  
    45  // size returns the storage size of the entire freezer.
    46  func (info *freezerInfo) size() common.StorageSize {
    47  	var total common.StorageSize
    48  	for _, table := range info.sizes {
    49  		total += table.size
    50  	}
    51  	return total
    52  }
    53  
    54  func inspect(name string, order map[string]bool, reader ethdb.AncientReader) (freezerInfo, error) {
    55  	info := freezerInfo{name: name}
    56  	for t := range order {
    57  		size, err := reader.AncientSize(t)
    58  		if err != nil {
    59  			return freezerInfo{}, err
    60  		}
    61  		info.sizes = append(info.sizes, tableSize{name: t, size: common.StorageSize(size)})
    62  	}
    63  	// Retrieve the number of last stored item
    64  	ancients, err := reader.Ancients()
    65  	if err != nil {
    66  		return freezerInfo{}, err
    67  	}
    68  	info.head = ancients - 1
    69  
    70  	// Retrieve the number of first stored item
    71  	tail, err := reader.Tail()
    72  	if err != nil {
    73  		return freezerInfo{}, err
    74  	}
    75  	info.tail = tail
    76  	return info, nil
    77  }
    78  
    79  // inspectFreezers inspects all freezers registered in the system.
    80  func inspectFreezers(db ethdb.Database) ([]freezerInfo, error) {
    81  	var infos []freezerInfo
    82  	for _, freezer := range freezers {
    83  		switch freezer {
    84  		case ChainFreezerName:
    85  			info, err := inspect(ChainFreezerName, chainFreezerNoSnappy, db)
    86  			if err != nil {
    87  				return nil, err
    88  			}
    89  			infos = append(infos, info)
    90  
    91  		case StateFreezerName:
    92  			datadir, err := db.AncientDatadir()
    93  			if err != nil {
    94  				return nil, err
    95  			}
    96  			f, err := NewStateFreezer(datadir, true)
    97  			if err != nil {
    98  				continue // might be possible the state freezer is not existent
    99  			}
   100  			defer f.Close()
   101  
   102  			info, err := inspect(freezer, stateFreezerNoSnappy, f)
   103  			if err != nil {
   104  				return nil, err
   105  			}
   106  			infos = append(infos, info)
   107  
   108  		default:
   109  			return nil, fmt.Errorf("unknown freezer, supported ones: %v", freezers)
   110  		}
   111  	}
   112  	return infos, nil
   113  }
   114  
   115  // InspectFreezerTable dumps out the index of a specific freezer table. The passed
   116  // ancient indicates the path of root ancient directory where the chain freezer can
   117  // be opened. Start and end specify the range for dumping out indexes.
   118  // Note this function can only be used for debugging purposes.
   119  func InspectFreezerTable(ancient string, freezerName string, tableName string, start, end int64) error {
   120  	var (
   121  		path   string
   122  		tables map[string]bool
   123  	)
   124  	switch freezerName {
   125  	case ChainFreezerName:
   126  		path, tables = resolveChainFreezerDir(ancient), chainFreezerNoSnappy
   127  	case StateFreezerName:
   128  		path, tables = filepath.Join(ancient, freezerName), stateFreezerNoSnappy
   129  	default:
   130  		return fmt.Errorf("unknown freezer, supported ones: %v", freezers)
   131  	}
   132  	noSnappy, exist := tables[tableName]
   133  	if !exist {
   134  		var names []string
   135  		for name := range tables {
   136  			names = append(names, name)
   137  		}
   138  		return fmt.Errorf("unknown table, supported ones: %v", names)
   139  	}
   140  	table, err := newFreezerTable(path, tableName, noSnappy, true)
   141  	if err != nil {
   142  		return err
   143  	}
   144  	table.dumpIndexStdout(start, end)
   145  	return nil
   146  }