150 lines
3.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// /futriis/internal/storage/tuple.go
// Пакет storage реализует операции с кортежами (записями)
package storage
import (
"errors"
"sync/atomic"
"futriis/pkg/types"
"futriis/pkg/utils"
)
// TupleManager управляет операциями с кортежами
type TupleManager struct {
stats struct {
created int64
updated int64
deleted int64
read int64
}
}
// NewTupleManager создаёт новый менеджер кортежей
func NewTupleManager() *TupleManager {
return &TupleManager{}
}
// CreateTuple создаёт новый кортеж в указанном слайсе
// Wait-free операция: использует атомарные операции для счётчиков
func (tm *TupleManager) CreateTuple(slice *types.Slice, id string, fields map[string]interface{}) (*types.Tuple, error) {
if slice == nil {
return nil, errors.New("slice is nil")
}
// Проверяем существование кортежа
slice.RLock()
_, exists := slice.Tuples[id]
slice.RUnlock()
if exists {
return nil, errors.New("tuple already exists")
}
// Создаём новый кортеж
tuple := types.NewTuple(id)
for k, v := range fields {
tuple.Fields[k] = v
}
// Добавляем в слайс
slice.Lock()
slice.Tuples[id] = tuple
slice.Unlock()
// Атомарно увеличиваем счётчик созданных
atomic.AddInt64(&tm.stats.created, 1)
// Логируем операцию
logger := utils.GetLogger()
if logger != nil {
logger.Log("INFO", "Created tuple: "+id)
}
return tuple, nil
}
// ReadTuple читает кортеж по ID
// Wait-free операция для чтения
func (tm *TupleManager) ReadTuple(slice *types.Slice, id string) (*types.Tuple, error) {
if slice == nil {
return nil, errors.New("slice is nil")
}
slice.RLock()
tuple, exists := slice.Tuples[id]
slice.RUnlock()
if !exists {
return nil, errors.New("tuple not found")
}
atomic.AddInt64(&tm.stats.read, 1)
return tuple, nil
}
// UpdateTuple обновляет поля кортежа
func (tm *TupleManager) UpdateTuple(slice *types.Slice, id string, fields map[string]interface{}) (*types.Tuple, error) {
if slice == nil {
return nil, errors.New("slice is nil")
}
slice.Lock()
defer slice.Unlock()
tuple, exists := slice.Tuples[id]
if !exists {
return nil, errors.New("tuple not found")
}
// Обновляем поля
for k, v := range fields {
tuple.Fields[k] = v
}
atomic.AddInt64(&tm.stats.updated, 1)
logger := utils.GetLogger()
if logger != nil {
logger.Log("INFO", "Updated tuple: "+id)
}
return tuple, nil
}
// DeleteTuple удаляет кортеж
func (tm *TupleManager) DeleteTuple(slice *types.Slice, id string) error {
if slice == nil {
return errors.New("slice is nil")
}
slice.Lock()
_, exists := slice.Tuples[id]
if !exists {
slice.Unlock()
return errors.New("tuple not found")
}
delete(slice.Tuples, id)
slice.Unlock()
atomic.AddInt64(&tm.stats.deleted, 1)
logger := utils.GetLogger()
if logger != nil {
logger.Log("INFO", "Deleted tuple: "+id)
}
return nil
}
// GetStats возвращает статистику операций
func (tm *TupleManager) GetStats() map[string]int64 {
return map[string]int64{
"created": atomic.LoadInt64(&tm.stats.created),
"updated": atomic.LoadInt64(&tm.stats.updated),
"deleted": atomic.LoadInt64(&tm.stats.deleted),
"read": atomic.LoadInt64(&tm.stats.read),
}
}