BunchIndex.go

package datasource

import (
	"Saseul/config"
	"sync"
)

type BunchIndex struct {
	txIndexes         map[string]map[string]interface{}
	chunkIndexes      map[string]map[string]string
	hypothesisIndexes map[string]map[string]string
	receiptIndexes    map[string]map[string]string
	mu                sync.RWMutex
}

func NewBunchIndex() *BunchIndex {
	return &BunchIndex{
		txIndexes:         make(map[string]map[string]interface{}),
		chunkIndexes:      make(map[string]map[string]string),
		hypothesisIndexes: make(map[string]map[string]string),
		receiptIndexes:    make(map[string]map[string]string),
	}
}

func (bi *BunchIndex) AddTxIndex(data map[string]interface{}) bool {
	if data == nil {
		return false
	}

	bi.mu.Lock()
	defer bi.mu.Unlock()

	hash := data["hash"].(string)
	if _, exists := bi.txIndexes[hash]; exists {
		return false
	}

	txCount := len(bi.txIndexes)
	txSize := 0
	for _, tx := range bi.txIndexes {
		if size, ok := tx["size"].(int); ok {
			txSize += size
		}
	}

	countLimit := config.BlockTxCountLimit * 3
	sizeLimit := config.BlockTxSizeLimit * 3

	if txCount >= countLimit || txSize+data["size"].(int) > sizeLimit {
		return false
	}

	bi.txIndexes[hash] = data
	return true
}

func (bi *BunchIndex) ExistsTx(hash string) bool {
	bi.mu.RLock()
	defer bi.mu.RUnlock()

	_, exists := bi.txIndexes[hash]
	return exists
}

func (bi *BunchIndex) InfoTxs() map[string]int {
	bi.mu.RLock()
	defer bi.mu.RUnlock()

	count := len(bi.txIndexes)
	size := 0
	for _, tx := range bi.txIndexes {
		if txSize, ok := tx["size"].(int); ok {
			size += txSize
		}
	}

	return map[string]int{
		"count": count,
		"size":  size,
	}
}

func (bi *BunchIndex) RemoveTxs(utime int) bool {
	bi.mu.Lock()
	defer bi.mu.Unlock()

	for hash, tx := range bi.txIndexes {
		if timestamp, ok := tx["timestamp"].(int); ok && timestamp < utime {
			delete(bi.txIndexes, hash)
		}
	}

	return true
}

func (bi *BunchIndex) FlushTxs() bool {
	bi.mu.Lock()
	defer bi.mu.Unlock()

	bi.txIndexes = make(map[string]map[string]interface{})
	return true
}

func (bi *BunchIndex) AddChunkIndex(data map[string]string) bool {
	if data == nil {
		return false
	}

	bi.mu.Lock()
	defer bi.mu.Unlock()

	roundKey := data["round_key"]
	signer := data["signer"]
	hash := data["hash"]

	if bi.chunkIndexes[roundKey] == nil {
		bi.chunkIndexes[roundKey] = make(map[string]string)
	}

	bi.chunkIndexes[roundKey][signer] = hash
	return true
}

func (bi *BunchIndex) CountChunks(roundKey string) int {
	bi.mu.RLock()
	defer bi.mu.RUnlock()

	if bi.chunkIndexes[roundKey] == nil {
		return 0
	}

	return len(bi.chunkIndexes[roundKey])
}

func (bi *BunchIndex) RemoveChunks(roundKey string) bool {
	bi.mu.Lock()
	defer bi.mu.Unlock()

	for key := range bi.chunkIndexes {
		if key != roundKey {
			delete(bi.chunkIndexes, key)
		}
	}

	return true
}

func (bi *BunchIndex) AddHypothesisIndex(data map[string]string) bool {
	if data == nil {
		return false
	}

	bi.mu.Lock()
	defer bi.mu.Unlock()

	roundKey := data["round_key"]
	signer := data["signer"]
	hash := data["hash"]

	if bi.hypothesisIndexes[roundKey] == nil {
		bi.hypothesisIndexes[roundKey] = make(map[string]string)
	}

	bi.hypothesisIndexes[roundKey][signer] = hash
	return true
}

func (bi *BunchIndex) CountHypotheses(roundKey string) int {
	bi.mu.RLock()
	defer bi.mu.RUnlock()

	if bi.hypothesisIndexes[roundKey] == nil {
		return 0
	}

	return len(bi.hypothesisIndexes[roundKey])
}

func (bi *BunchIndex) RemoveHypotheses(roundKey string) bool {
	bi.mu.Lock()
	defer bi.mu.Unlock()

	for key := range bi.hypothesisIndexes {
		if key != roundKey {
			delete(bi.hypothesisIndexes, key)
		}
	}

	return true
}

func (bi *BunchIndex) AddReceiptIndex(data map[string]string) bool {
	if data == nil {
		return false
	}

	bi.mu.Lock()
	defer bi.mu.Unlock()

	roundKey := data["round_key"]
	signer := data["signer"]
	hash := data["hash"]

	if bi.receiptIndexes[roundKey] == nil {
		bi.receiptIndexes[roundKey] = make(map[string]string)
	}

	if _, exists := bi.receiptIndexes[roundKey][signer]; exists || len(bi.receiptIndexes) >= config.ReceiptCountLimit {
		return false
	}

	bi.receiptIndexes[roundKey][signer] = hash
	return true
}

func (bi *BunchIndex) CountReceipt(roundKey string) int {
	bi.mu.RLock()
	defer bi.mu.RUnlock()

	if bi.receiptIndexes[roundKey] == nil {
		return 0
	}

	return len(bi.receiptIndexes[roundKey])
}

func (bi *BunchIndex) RemoveReceipts(roundKey string) bool {
	bi.mu.Lock()
	defer bi.mu.Unlock()

	for key := range bi.receiptIndexes {
		if key != roundKey {
			delete(bi.receiptIndexes, key)
		}
	}

	return true
}

이 코드는 BunchIndex라는 구조체를 정의하고, 다양한 인덱스 관리 작업을 수행하는 메서드들을 구현하고 있습니다. 이 구조체는 트랜잭션, 청크, 가설, 영수증 등의 인덱스를 관리하며 동시성 제어를 위해 sync.RWMutex를 사용합니다. 각 메서드에 대한 자세한 설명을 드리겠습니다.

BunchIndex 구조체

이 구조체는 네 가지 종류의 인덱스(txIndexes, chunkIndexes, hypothesisIndexes, receiptIndexes)를 맵으로 관리합니다. mu는 동시성 제어를 위해 사용됩니다.

NewBunchIndex 함수

이 함수는 새로운 BunchIndex 객체를 생성하여 초기화합니다.

트랜잭션 관련 메서드

AddTxIndex

트랜잭션 인덱스를 추가합니다.

  1. 데이터가 유효한지 검사합니다.

  2. 트랜잭션 해시가 이미 존재하는지 확인합니다.

  3. 트랜잭션 수와 크기 제한을 초과하는지 검사합니다.

  4. 제한을 초과하지 않으면 인덱스를 추가합니다.

ExistsTx

해당 해시의 트랜잭션이 존재하는지 확인합니다.

InfoTxs

트랜잭션 인덱스의 수와 총 크기를 반환합니다.

RemoveTxs

특정 시간 이전의 트랜잭션 인덱스를 제거합니다.

FlushTxs

모든 트랜잭션 인덱스를 초기화합니다.

청크 관련 메서드

AddChunkIndex

청크 인덱스를 추가합니다. 데이터가 유효한지 확인한 후 인덱스를 추가합니다.

CountChunks

특정 라운드 키에 대한 청크 인덱스의 수를 반환합니다.

RemoveChunks

특정 라운드 키가 아닌 모든 청크 인덱스를 제거합니다.

가설 관련 메서드

AddHypothesisIndex

가설 인덱스를 추가합니다. 데이터가 유효한지 확인한 후 인덱스를 추가합니다.

CountHypotheses

특정 라운드 키에 대한 가설 인덱스의 수를 반환합니다.

RemoveHypotheses

특정 라운드 키가 아닌 모든 가설 인덱스를 제거합니다.

영수증 관련 메서드

AddReceiptIndex

영수증 인덱스를 추가합니다. 데이터가 유효한지 확인한 후 인덱스를 추가합니다.

CountReceipt

특정 라운드 키에 대한 영수증 인덱스의 수를 반환합니다.

RemoveReceipts

특정 라운드 키가 아닌 모든 영수증 인덱스를 제거합니다.

이렇게 BunchIndex 구조체는 트랜잭션, 청크, 가설, 영수증 인덱스를 관리하며, 동시성 제어를 위해 sync.RWMutex를 사용합니다. 이를 통해 여러 고루틴이 안전하게 인덱스를 읽고 쓸 수 있습니다.

Last updated