futriis/pkg/types/types.go
2026-02-27 22:04:04 +03:00

189 lines
5.2 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/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(),
}
}