Skip to content

Commit

Permalink
BlockDB v2
Browse files Browse the repository at this point in the history
  • Loading branch information
firelizzard18 committed Jun 24, 2024
1 parent 531564f commit eeda55c
Show file tree
Hide file tree
Showing 43 changed files with 2,434 additions and 875 deletions.
5 changes: 2 additions & 3 deletions cmd/accumulated-bootstrap/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"github.com/spf13/cobra"
. "gitlab.com/accumulatenetwork/accumulate/cmd/accumulated/run"
. "gitlab.com/accumulatenetwork/accumulate/internal/util/cmd"
cmdutil "gitlab.com/accumulatenetwork/accumulate/internal/util/cmd"
)

func main() {
Expand All @@ -35,7 +34,7 @@ var flag = struct {
Peers []multiaddr.Multiaddr
External multiaddr.Multiaddr
}{
Key: cmdutil.PrivateKeyFlag{Value: &TransientPrivateKey{}},
Key: PrivateKeyFlag{Value: &TransientPrivateKey{}},
PromListen: []multiaddr.Multiaddr{
multiaddr.StringCast("/ip4/0.0.0.0/tcp/8081/http"),
},
Expand Down Expand Up @@ -65,7 +64,7 @@ func run(*cobra.Command, []string) {
},
}

ctx := cmdutil.ContextForMainProcess(context.Background())
ctx := ContextForMainProcess(context.Background())
inst, err := Start(ctx, cfg)
Check(err)

Expand Down
18 changes: 17 additions & 1 deletion cmd/accumulated/cmd_init_devnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,20 @@
package main

import (
"bufio"
"crypto/ed25519"
"crypto/rand"
"fmt"
"os"
"path/filepath"
"strings"

"github.com/multiformats/go-multiaddr"
"github.com/spf13/cobra"
"gitlab.com/accumulatenetwork/accumulate/cmd/accumulated/run"
"gitlab.com/accumulatenetwork/accumulate/pkg/types/address"
"golang.org/x/exp/slices"
"golang.org/x/term"
)

func initDevNet(cmd *cobra.Command) *run.Config {
Expand Down Expand Up @@ -56,7 +59,20 @@ func initDevNet(cmd *cobra.Command) *run.Config {
cmd.Flag("followers").Changed && dev.Followers != uint64(flagRunDevnet.NumFollowers) ||
cmd.Flag("globals").Changed && !flagRunDevnet.Globals.Equal(dev.Globals)
if wantReset && !flagMain.Reset {
fatalf("the configuration and flags do not match; use --reset if you wish to override (and reset) the existing configuration")
if !term.IsTerminal(int(os.Stdout.Fd())) || !term.IsTerminal(int(os.Stderr.Fd())) {
fatalf("the configuration and flags do not match; use --reset if you wish to override (and reset) the existing configuration")
}
fmt.Fprint(os.Stderr, "Configuration and flags do not match. Reset? [yN] ")
s, err := bufio.NewReader(os.Stdin).ReadString('\n')
check(err)
s = strings.TrimSpace(s)
s = strings.ToLower(s)
switch s {
case "y", "yes":
flagMain.Reset = true
default:
os.Exit(0)
}
}

applyDevNetFlags(cmd, cfg, dev, true)
Expand Down
259 changes: 259 additions & 0 deletions exp/ioutil/mapped_file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
// Copyright 2024 The Accumulate Authors
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

package ioutil

import (
"errors"
"io"
"io/fs"
"os"
"sync"
"sync/atomic"

"github.com/edsrzf/mmap-go"
"gitlab.com/accumulatenetwork/core/schema/pkg/binary"
)

type MappedFile struct {
mu *sync.RWMutex
file *os.File
data mmap.MMap
pool *binary.Pool[*MappedFileRange]
}

func OpenMappedFile(name string, flags int, perm fs.FileMode) (_ *MappedFile, err error) {
f := new(MappedFile)
f.mu = new(sync.RWMutex)
f.pool = binary.NewPointerPool[MappedFileRange]()
defer func() {
if err != nil {
_ = f.Close()
}
}()

f.file, err = os.OpenFile(name, flags, 0600)
if err != nil {
return nil, err
}

st, err := f.file.Stat()
if err != nil {
return nil, err
}

if st.Size() == 0 {
return f, nil
}

f.data, err = mmap.MapRegion(f.file, int(st.Size()), mmap.RDWR, 0, 0)
if err != nil {
return nil, err
}

return f, nil
}

func (f *MappedFile) Name() string {
return f.file.Name()
}

func (f *MappedFile) Close() error {
f.mu.Lock()
defer f.mu.Unlock()

var errs []error
if f.data != nil {
errs = append(errs, f.data.Unmap())
}
if f.file != nil {
errs = append(errs, f.file.Close())
}

f.data = nil
f.file = nil
return errors.Join(errs...)
}

type MappedFileRange struct {
f *MappedFile
released atomic.Bool
Offset int64
End int64
}

func (f *MappedFile) Acquire() *MappedFileRange {
f.mu.RLock()
h := f.pool.Get()
h.f = f
h.released.Store(false)
h.SetRange(0, int64(len(f.data)))
return h
}

func (f *MappedFile) AcquireRange(start, end int64) *MappedFileRange {
f.mu.RLock()
h := f.pool.Get()
h.f = f
h.released.Store(false)
h.SetRange(start, end)
return h
}

func (f *MappedFileRange) AcquireRange(start, end int64) *MappedFileRange {
return f.f.AcquireRange(start, end)
}

func (f *MappedFileRange) Release() {
// Only release once
if f.released.Swap(true) {
return
}

f.f.mu.RUnlock()
f.f.pool.Put(f)
f.f = nil
}

func (f *MappedFileRange) SetRange(start, end int64) {
f.Offset = max(start, 0)
f.End = min(end, int64(len(f.f.data)))
}

func (f *MappedFileRange) Len() int {
return int(f.End - f.Offset)
}

func (f *MappedFileRange) Raw() []byte {
return f.f.data[f.Offset:f.End]
}

func (f *MappedFileRange) Seek(offset int64, whence int) (int64, error) {
switch whence {
case io.SeekStart:
// Ok
case io.SeekCurrent:
offset += f.Offset
case io.SeekEnd:
offset += f.End
default:
return 0, errors.New("invalid whence")
}
if offset < 0 || offset > f.End {
return 0, io.EOF
}
f.Offset = offset
return offset, nil
}

func (f *MappedFileRange) Read(b []byte) (int, error) {
n, err := f.ReadAt(b, f.Offset)
f.Offset += int64(n)
return n, err
}
func (f *MappedFileRange) Write(b []byte) (int, error) {
n, err := f.WriteAt(b, f.Offset)
f.Offset += int64(n)
return n, err
}

func (f *MappedFileRange) ReadAt(b []byte, offset int64) (int, error) {
if offset > int64(len(f.f.data)) {
return 0, io.EOF
}

n := copy(b, f.f.data[offset:])
if n < len(b) {
return n, io.EOF
}
return n, nil
}

func (f *MappedFileRange) WriteAt(b []byte, offset int64) (int, error) {
err := f.Truncate(offset + int64(len(b)))
if err != nil {
return 0, err
}

m := copy(f.f.data[offset:], b)
return m, nil
}

func (f *MappedFileRange) ReadByte() (byte, error) {
if f.Offset >= f.End {
return 0, io.EOF
}
b := f.f.data[f.Offset]
f.Offset++
return b, nil
}

func (f *MappedFileRange) UnreadByte() error {
if f.Offset <= 0 {
return io.EOF
}
f.Offset--
return nil
}

func (f *MappedFileRange) Truncate(size int64) error {
for size > int64(len(f.f.data)) {
err := f.truncateInner(size)
if err != nil {
return err
}
}
return nil
}

func (f *MappedFileRange) truncateInner(size int64) error {
// Upgrade the lock
demote := f.promote()
defer demote()

// Is the mapped region smaller than we want?
if size <= int64(len(f.f.data)) {
return nil
}

// Is the file smaller than we want?
st, err := f.f.file.Stat()
if err != nil {
return err
}

if st.Size() >= size {
size = st.Size()
} else {

// Expand the file
err = f.f.file.Truncate(size)
if err != nil {
return err
}
}

// Remove the old mapping
if f.f.data != nil {
err = f.f.data.Unmap()
if err != nil {
return err
}
}

// Remap
f.f.data, err = mmap.MapRegion(f.f.file, int(size), mmap.RDWR, 0, 0)
return err
}

func (f *MappedFileRange) promote() (demote func()) {
f.f.mu.RUnlock()
f.f.mu.Lock()
return func() {
f.f.mu.Unlock()
f.f.mu.RLock()
}
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ require (
github.com/sergi/go-diff v1.2.0
github.com/ulikunitz/xz v0.5.11
github.com/vektra/mockery/v2 v2.42.3
gitlab.com/accumulatenetwork/core/schema v0.1.1-0.20240618183058-91669372cfa3
gitlab.com/accumulatenetwork/core/schema v0.1.1-0.20240620224759-19369030b361
gitlab.com/firelizzard/go-script v0.0.0-20240404234115-d5f0a716003d
go.opentelemetry.io/otel v1.16.0
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.14.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1164,8 +1164,8 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
gitlab.com/accumulatenetwork/core/schema v0.1.1-0.20240618183058-91669372cfa3 h1:RyNDul6B2nebcjA8+KSBR79MRUftOWWO0NRqN3x0Vh4=
gitlab.com/accumulatenetwork/core/schema v0.1.1-0.20240618183058-91669372cfa3/go.mod h1:FTl7W44SWhDenzAtvKkLu30Cin8DAr249mH4eg7BNLY=
gitlab.com/accumulatenetwork/core/schema v0.1.1-0.20240620224759-19369030b361 h1:J9FcjE7osYPinvoEzWrkpagukyqDwzLqH9fplznBA+M=
gitlab.com/accumulatenetwork/core/schema v0.1.1-0.20240620224759-19369030b361/go.mod h1:FTl7W44SWhDenzAtvKkLu30Cin8DAr249mH4eg7BNLY=
gitlab.com/bosi/decorder v0.4.1 h1:VdsdfxhstabyhZovHafFw+9eJ6eU0d2CkFNJcZz/NU4=
gitlab.com/bosi/decorder v0.4.1/go.mod h1:jecSqWUew6Yle1pCr2eLWTensJMmsxHsBwt+PVbkAqA=
gitlab.com/ethan.reesor/vscode-notebooks/go-playbooks v0.0.0-20220417214602-1121b9fae118 h1:UnyYFTz6dWVMBzLUyqHPIQwMrdpiuE+CE7p/5kUfvmk=
Expand Down
2 changes: 1 addition & 1 deletion pkg/database/bpt/bpt.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type KeyValuePair struct {
}

// New returns a new BPT.
func New(parent database.Record, logger log.Logger, store database.Store, key *database.Key) *BPT {
func New(_ database.Record, logger log.Logger, store database.Store, key *database.Key) *BPT {
b := new(BPT)
b.logger.Set(logger)
b.store = store
Expand Down
10 changes: 6 additions & 4 deletions pkg/database/bpt/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,26 @@ const paramsV2Magic = "\xC0\xFF\xEE"
// paramsStateSize is the marshaled size of [parameters].
const paramsStateSize = 1 + 2 + 2 + 32

func (b *BPT) SetParams(p parameters) error {
func (b *BPT) SetParams(p Parameters) error {
if b.loadedState == nil {
s, err := b.getState().Get()
switch {
case err == nil:
b.loadedState = s
s.Mask = s.Power - 1
case errors.Is(err, errors.NotFound):
b.loadedState = new(stateData)
default:
return errors.UnknownError.Wrap(err)
}
}

if b.loadedState.parameters == (parameters{}) {
b.loadedState.parameters = p
if b.loadedState.Parameters == (Parameters{}) {
b.loadedState.Parameters = p
return b.storeState()
}

if !b.loadedState.parameters.Equal(&p) {
if !b.loadedState.Parameters.Equal(&p) {
return errors.BadRequest.With("BPT parameters cannot be modified")
}
return nil
Expand All @@ -55,6 +56,7 @@ func (b *BPT) loadState() (*stateData, error) {
switch {
case err == nil:
b.loadedState = s
s.Mask = s.Power - 1
return s, nil
case !errors.Is(err, errors.NotFound):
return nil, errors.UnknownError.Wrap(err)
Expand Down
Loading

0 comments on commit eeda55c

Please sign in to comment.