2026-02-27 22:04:04 +03:00

157 lines
4.9 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/tapple.go
// Пакет storage реализует операции с тапплами (базами данных) - контейнерами верхнего уровня.
// TappleManager управляет созданием, удалением и получением тапплов, каждый из которых содержит коллекцию слайсов (таблиц).
// Интегрируется с SliceManager для операций со слайсами.
// Обеспечивает wait-free хранение тапплов в памяти с использованием атомарных указателей.
package storage
import (
"errors"
"sync/atomic"
"time"
"unsafe"
"futriis/pkg/types"
"futriis/pkg/utils"
)
// TappleManager управляет операциями с тапплами (wait-free)
type TappleManager struct {
tapples unsafe.Pointer // Атомарный указатель на map[string]*types.Tapple
sliceManager *SliceManager
indexManager *IndexManager
stats struct {
created int64
deleted int64
}
}
// NewTappleManager создаёт новый менеджер тапплов
func NewTappleManager() *TappleManager {
// Инициализируем пустую карту
tapples := make(map[string]*types.Tapple)
return &TappleManager{
tapples: unsafe.Pointer(&tapples),
sliceManager: NewSliceManager(),
indexManager: NewIndexManager(),
}
}
// CreateTapple создаёт новый таппл с временной меткой
func (tm *TappleManager) CreateTapple(name string) (*types.Tapple, error) {
// Получаем текущую карту
oldPtr := atomic.LoadPointer(&tm.tapples)
oldTapples := *(*map[string]*types.Tapple)(oldPtr)
// Проверяем существование
if _, exists := oldTapples[name]; exists {
return nil, errors.New("tapple already exists")
}
// Создаём новый таппл с временной меткой
tapple := types.NewTapple(name)
tapple.CreatedAt = time.Now()
tapple.UpdatedAt = time.Now()
// Создаём новую карту
newTapples := make(map[string]*types.Tapple)
for k, v := range oldTapples {
newTapples[k] = v
}
newTapples[name] = tapple
// Атомарно обновляем указатель
atomic.StorePointer(&tm.tapples, unsafe.Pointer(&newTapples))
atomic.AddInt64(&tm.stats.created, 1)
logger := utils.GetLogger()
if logger != nil {
logger.Log("INFO", "Created tapple: "+name+" at "+tapple.CreatedAt.Format(time.RFC3339))
}
return tapple, nil
}
// GetTapple возвращает таппл по имени (wait-free)
func (tm *TappleManager) GetTapple(name string) (*types.Tapple, error) {
// Атомарно загружаем указатель
ptr := atomic.LoadPointer(&tm.tapples)
tapples := *(*map[string]*types.Tapple)(ptr)
tapple, exists := tapples[name]
if !exists {
return nil, errors.New("tapple not found")
}
return tapple, nil
}
// GetAllTapples возвращает копию всех тапплов (для Backup)
func (tm *TappleManager) GetAllTapples() map[string]*types.Tapple {
ptr := atomic.LoadPointer(&tm.tapples)
tapples := *(*map[string]*types.Tapple)(ptr)
// Создаём копию для безопасного использования
result := make(map[string]*types.Tapple)
for k, v := range tapples {
result[k] = v
}
return result
}
// DeleteTapple удаляет таппл
func (tm *TappleManager) DeleteTapple(name string) error {
// Получаем текущую карту
oldPtr := atomic.LoadPointer(&tm.tapples)
oldTapples := *(*map[string]*types.Tapple)(oldPtr)
// Проверяем существование
if _, exists := oldTapples[name]; !exists {
return errors.New("tapple not found")
}
// Создаём новую карту без удаляемого таппла
newTapples := make(map[string]*types.Tapple)
for k, v := range oldTapples {
if k != name {
newTapples[k] = v
}
}
// Атомарно обновляем указатель
atomic.StorePointer(&tm.tapples, unsafe.Pointer(&newTapples))
atomic.AddInt64(&tm.stats.deleted, 1)
logger := utils.GetLogger()
if logger != nil {
logger.Log("INFO", "Deleted tapple: "+name)
}
return nil
}
// ListTapples возвращает список всех тапплов (wait-free)
func (tm *TappleManager) ListTapples() []string {
ptr := atomic.LoadPointer(&tm.tapples)
tapples := *(*map[string]*types.Tapple)(ptr)
result := make([]string, 0, len(tapples))
for name := range tapples {
result = append(result, name)
}
return result
}
// GetSliceManager возвращает менеджер слайсов
func (tm *TappleManager) GetSliceManager() *SliceManager {
return tm.sliceManager
}
// GetIndexManager возвращает менеджер индексов
func (tm *TappleManager) GetIndexManager() *IndexManager {
return tm.indexManager
}