futriis/pkg/types/types.go

189 lines
5.2 KiB
Go
Raw Normal View History

2026-02-27 22:04:04 +03:00
// /futriis/pkg/types/types.go
// Пакет types определяет основные структуры данных СУБД Futriis.
// Содержит определения для тапплов (баз данных), слайсов (таблиц) и кортежей (записей).
// Использует wait-free подход с атомарными операциями вместо мьютексов.
package types
import (
"sync/atomic"
"time"
"unsafe"
)
// Tapple представляет базу данных (контейнер верхнего уровня) с wait-free доступом
type Tapple struct {
Name string
slices unsafe.Pointer // Атомарный указатель на map[string]*Slice
CreatedAt time.Time
UpdatedAt time.Time
}
// NewTapple создаёт новый таппл с wait-free доступом
func NewTapple(name string) *Tapple {
slices := make(map[string]*Slice)
return &Tapple{
Name: name,
slices: unsafe.Pointer(&slices),
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
}
}
// GetSlices атомарно получает карту слайсов
func (t *Tapple) GetSlices() map[string]*Slice {
ptr := atomic.LoadPointer(&t.slices)
return *(*map[string]*Slice)(ptr)
}
// GetSlice атомарно получает слайс по имени
func (t *Tapple) GetSlice(name string) (*Slice, bool) {
slices := t.GetSlices()
slice, exists := slices[name]
return slice, exists
}
// PutSlice атомарно добавляет или обновляет слайс
func (t *Tapple) PutSlice(name string, slice *Slice) {
for {
oldPtr := atomic.LoadPointer(&t.slices)
oldSlices := *(*map[string]*Slice)(oldPtr)
// Создаём новую карту
newSlices := make(map[string]*Slice)
for k, v := range oldSlices {
newSlices[k] = v
}
newSlices[name] = slice
// Пытаемся атомарно обновить
if atomic.CompareAndSwapPointer(&t.slices, oldPtr, unsafe.Pointer(&newSlices)) {
t.UpdatedAt = time.Now()
break
}
}
}
// DeleteSlice атомарно удаляет слайс
func (t *Tapple) DeleteSlice(name string) bool {
for {
oldPtr := atomic.LoadPointer(&t.slices)
oldSlices := *(*map[string]*Slice)(oldPtr)
if _, exists := oldSlices[name]; !exists {
return false
}
// Создаём новую карту без удаляемого слайса
newSlices := make(map[string]*Slice)
for k, v := range oldSlices {
if k != name {
newSlices[k] = v
}
}
// Пытаемся атомарно обновить
if atomic.CompareAndSwapPointer(&t.slices, oldPtr, unsafe.Pointer(&newSlices)) {
t.UpdatedAt = time.Now()
return true
}
}
}
// Slice представляет таблицу (контейнер для кортежей) с wait-free доступом
type Slice struct {
Name string
tuples unsafe.Pointer // Атомарный указатель на map[string]*Tuple
CreatedAt time.Time
UpdatedAt time.Time
}
// NewSlice создаёт новый слайс с wait-free доступом
func NewSlice(name string) *Slice {
tuples := make(map[string]*Tuple)
return &Slice{
Name: name,
tuples: unsafe.Pointer(&tuples),
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
}
}
// GetTuples атомарно получает карту кортежей
func (s *Slice) GetTuples() map[string]*Tuple {
ptr := atomic.LoadPointer(&s.tuples)
return *(*map[string]*Tuple)(ptr)
}
// GetTuple атомарно получает кортеж по ID
func (s *Slice) GetTuple(id string) (*Tuple, bool) {
tuples := s.GetTuples()
tuple, exists := tuples[id]
return tuple, exists
}
// PutTuple атомарно добавляет или обновляет кортеж
func (s *Slice) PutTuple(id string, tuple *Tuple) {
for {
oldPtr := atomic.LoadPointer(&s.tuples)
oldTuples := *(*map[string]*Tuple)(oldPtr)
// Создаём новую карту
newTuples := make(map[string]*Tuple)
for k, v := range oldTuples {
newTuples[k] = v
}
newTuples[id] = tuple
// Пытаемся атомарно обновить
if atomic.CompareAndSwapPointer(&s.tuples, oldPtr, unsafe.Pointer(&newTuples)) {
s.UpdatedAt = time.Now()
break
}
}
}
// DeleteTuple атомарно удаляет кортеж
func (s *Slice) DeleteTuple(id string) bool {
for {
oldPtr := atomic.LoadPointer(&s.tuples)
oldTuples := *(*map[string]*Tuple)(oldPtr)
if _, exists := oldTuples[id]; !exists {
return false
}
// Создаём новую карту без удаляемого кортежа
newTuples := make(map[string]*Tuple)
for k, v := range oldTuples {
if k != id {
newTuples[k] = v
}
}
// Пытаемся атомарно обновить
if atomic.CompareAndSwapPointer(&s.tuples, oldPtr, unsafe.Pointer(&newTuples)) {
s.UpdatedAt = time.Now()
return true
}
}
}
// Tuple представляет кортеж (запись)
type Tuple struct {
ID string
Fields map[string]interface{}
CreatedAt time.Time
UpdatedAt time.Time
}
// NewTuple создаёт новый кортеж
func NewTuple(id string) *Tuple {
return &Tuple{
ID: id,
Fields: make(map[string]interface{}),
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
}
}