// /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 }