<commit_before>package bolt

import (
	"fmt"
	"io"
	"os"
	"time"

	"github.com/boltdb/bolt"
	"github.com/golang/protobuf/proto"
	"github.com/octavore/naga/service"
	"github.com/octavore/nagax/logger"

	"github.com/ketchuphq/ketchup/db"
	"github.com/ketchuphq/ketchup/proto/ketchup/models"
	"github.com/ketchuphq/ketchup/server/config"
	"github.com/ketchuphq/ketchup/util/errors"
)

type BoltConfig struct {
	Bolt struct {
		Path string `json:"path"`
	} `json:"bolt"`
}

// Module bolt provides methods for writing and retrieving
// data from a bolt database.
type Module struct {
	Bolt         *bolt.DB
	Backend      *db.Module
	ConfigModule *config.Module
	Logger       *logger.Module

	config BoltConfig
}

// Init implements service.Init
func (m *Module) Init(c *service.Config) {
	c.Setup = func() (err error) {
		m.Backend.Register(m)
		err = m.ConfigModule.ReadConfig(&m.config)
		if err != nil {
			return err
		}
		if c.Env().IsTest() {
			return
		}
		m.config.Bolt.Path = m.ConfigModule.DataPath(m.config.Bolt.Path, "default.db")
		m.Bolt, err = bolt.Open(m.config.Bolt.Path, os.ModePerm, &bolt.Options{
			Timeout: 5 * time.Second,
		})
		if err != nil {
			if err == bolt.ErrTimeout {
				m.Logger.Error("bolt: timeout while connecting; it may be that the database is already in use by another process.")
			}
			return errors.Wrap(err)
		}
		return m.init()
	}
	var testDB string
	c.SetupTest = func() {
		suffix := time.Now().Format("20060102150405.999")
		testDB = fmt.Sprintf("test-%s.db", suffix)
		err := os.RemoveAll(testDB)
		if err != nil {
			panic(err)
		}
		m.Bolt, err = bolt.Open(testDB, os.ModePerm, &bolt.Options{
			Timeout: 30 * time.Second,
		})
		if err != nil {
			panic(err)
		}
		err = m.init()
		if err != nil {
			panic(err)
		}
		return
	}
	c.Stop = func() {
		err := m.Bolt.Close()
		if err != nil {
			panic(err)
		}
		if testDB != "" {
			err := os.RemoveAll(testDB)
			if err != nil {
				panic(err)
			}
		}
	}
}

type ErrNoKey string

func (e ErrNoKey) Error() string {
	return fmt.Sprintf("boltdb: key not found: %s", string(e))
}

func (m *Module) init() error {
	return m.Bolt.Update(func(tx *bolt.Tx) error {
		buckets := []string{PAGE_BUCKET, ROUTE_BUCKET, USER_BUCKET}
		for _, bucket := range buckets {
			_, err := tx.CreateBucketIfNotExists([]byte(bucket))
			if err != nil {
				return errors.Wrap(err)
			}
		}
		return nil<commit_msg>bolt: Initialize data bucket.<commit_after>package bolt

import (
	"fmt"
	"io"
	"os"
	"time"

	"github.com/boltdb/bolt"
	"github.com/golang/protobuf/proto"
	"github.com/octavore/naga/service"
	"github.com/octavore/nagax/logger"

	"github.com/ketchuphq/ketchup/db"
	"github.com/ketchuphq/ketchup/proto/ketchup/models"
	"github.com/ketchuphq/ketchup/server/config"
	"github.com/ketchuphq/ketchup/util/errors"
)

type BoltConfig struct {
	Bolt struct {
		Path string `json:"path"`
	} `json:"bolt"`
}

// Module bolt provides methods for writing and retrieving
// data from a bolt database.
type Module struct {
	Bolt         *bolt.DB
	Backend      *db.Module
	ConfigModule *config.Module
	Logger       *logger.Module

	config BoltConfig
}

// Init implements service.Init
func (m *Module) Init(c *service.Config) {
	c.Setup = func() (err error) {
		m.Backend.Register(m)
		err = m.ConfigModule.ReadConfig(&m.config)
		if err != nil {
			return err
		}
		if c.Env().IsTest() {
			return
		}
		m.config.Bolt.Path = m.ConfigModule.DataPath(m.config.Bolt.Path, "default.db")
		m.Bolt, err = bolt.Open(m.config.Bolt.Path, os.ModePerm, &bolt.Options{
			Timeout: 5 * time.Second,
		})
		if err != nil {
			if err == bolt.ErrTimeout {
				m.Logger.Error("bolt: timeout while connecting; it may be that the database is already in use by another process.")
			}
			return errors.Wrap(err)
		}
		return m.init()
	}
	var testDB string
	c.SetupTest = func() {
		suffix := time.Now().Format("20060102150405.999")
		testDB = fmt.Sprintf("test-%s.db", suffix)
		err := os.RemoveAll(testDB)
		if err != nil {
			panic(err)
		}
		m.Bolt, err = bolt.Open(testDB, os.ModePerm, &bolt.Options{
			Timeout: 30 * time.Second,
		})
		if err != nil {
			panic(err)
		}
		err = m.init()
		if err != nil {
			panic(err)
		}
		return
	}
	c.Stop = func() {
		err := m.Bolt.Close()
		if err != nil {
			panic(err)
		}
		if testDB != "" {
			err := os.RemoveAll(testDB)
			if err != nil {
				panic(err)
			}
		}
	}
}

type ErrNoKey string

func (e ErrNoKey) Error() string {
	return fmt.Sprintf("boltdb: key not found: %s", string(e))
}

func (m *Module) init() error {
	return m.Bolt.Update(func(tx *bolt.Tx) error {
		buckets := []string{PAGE_BUCKET, ROUTE_BUCKET, USER_BUCKET, DATA_BUCKET}
		for _, bucket := range buckets {
			_, err := tx.CreateBucketIfNotExists([]byte(bucket))
			if err != nil {
				return errors.Wrap(err)
			}
		}
		return nil
{'fraction_non_alphanumeric': 0.15117488043252236, 'fraction_numerical': 0.008317737575379496, 'mean_word_length': 3.160899653979239, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7080676', 'n_tokens_mistral': 2065, 'n_tokens_neox': 1840, 'n_words': 409}