<commit_before>package drax

import (
	"fmt"
	"net"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/cpuguy83/drax/api"
	"github.com/cpuguy83/drax/rpc"
	libkvstore "github.com/docker/libkv/store"
	"github.com/hashicorp/raft"
)

var (
	defaultTimeout = 5 * time.Second
)

// Cluster is used to manage all the cluster state for a given node
type Cluster struct {
	home, addr, peerAddr string
	store                *store
	chShutdown           chan struct{}
	chErrors             chan error
	server               *rpc.Server
	l                    net.Listener
	r                    *Raft
	mu                   sync.Mutex
	rpcDialer            rpc.DialerFn
	peers                raft.PeerStore
}

// New creates a new Cluster and starts it
func New(l net.Listener, rpcDialer rpc.DialerFn, home, addr, peer string) (*Cluster, error) {
	if err := os.MkdirAll(home, 0600); err != nil {
		return nil, fmt.Errorf("error creating home dir: %v", err)
	}

	c := &Cluster{
		home:       home,
		addr:       addr,
		peerAddr:   peer,
		chShutdown: make(chan struct{}),
		chErrors:   make(chan error, 1),
		l:          l,
		rpcDialer:  rpcDialer,
	}
	return c, c.start()
}

func (c *Cluster) start() error {
	c.store = newStore()

	cfg := raft.DefaultConfig()
	cfg.ShutdownOnRemove = false

	raftStream := rpc.NewStreamLayer(c.l.Addr(), byte(raftMessage), c.rpcDialer)
	raftTransport := raft.NewNetworkTransport(raftStream, 3, defaultTimeout, os.Stdout)
	peerStore := newPeerStore(c.home, raftTransport)
	c.peers = peerStore

	peers, err := peerStore.Peers()
	if err != nil {
		return err
	}
	nPeers := len(peers)
	if nPeers <= 1 && c.peerAddr == "" {
		cfg.EnableSingleNode = true
	}

	kvRaft, err := newRaft(filepath.Join(c.home, "raft"), c.addr, peerStore, (*storeFSM)(c.store), raftTransport, cfg)
	if err != nil {
		return err
	}
	c.store.r = kvRaft<commit_msg>Make raft logger configurable<commit_after>package drax

import (
	"fmt"
	"io"
	"net"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/cpuguy83/drax/api"
	"github.com/cpuguy83/drax/rpc"
	libkvstore "github.com/docker/libkv/store"
	"github.com/hashicorp/raft"
)

var (
	defaultTimeout = 5 * time.Second
)

// Cluster is used to manage all the cluster state for a given node
type Cluster struct {
	home, addr, peerAddr string
	store                *store
	chShutdown           chan struct{}
	chErrors             chan error
	server               *rpc.Server
	l                    net.Listener
	r                    *Raft
	mu                   sync.Mutex
	rpcDialer            rpc.DialerFn
	peers                raft.PeerStore
	logger               io.Writer
}

// New creates a new Cluster and starts it
func New(l net.Listener, rpcDialer rpc.DialerFn, home, addr, peer string, logger io.Writer) (*Cluster, error) {
	if err := os.MkdirAll(home, 0600); err != nil {
		return nil, fmt.Errorf("error creating home dir: %v", err)
	}

	c := &Cluster{
		home:       home,
		addr:       addr,
		peerAddr:   peer,
		chShutdown: make(chan struct{}),
		chErrors:   make(chan error, 1),
		l:          l,
		logger:     logger,
		rpcDialer:  rpcDialer,
	}
	return c, c.start()
}

func (c *Cluster) start() error {
	c.store = newStore()

	cfg := raft.DefaultConfig()
	cfg.ShutdownOnRemove = false
	if c.logger != nil {
		cfg.LogOutput = c.logger
	}

	raftStream := rpc.NewStreamLayer(c.l.Addr(), byte(raftMessage), c.rpcDialer)
	raftTransport := raft.NewNetworkTransport(raftStream, 3, defaultTimeout, os.Stdout)
	peerStore := newPeerStore(c.home, raftTransport)
	c.peers = peerStore

	peers, err := peerStore.Peers()
	if err != nil {
		return err
	}
	nPeers := len(peers)
	if nPeers <= 1 && c.peerAddr == "" {
		cfg.EnableSingleNode = true
	}

	kvRaft, err := newRaft(filepath.Join(c.home, "raft"), c.addr, peerStore, (*storeFSM)(c.store), raftTransport, cfg)
	if err != nil {
		return err
	}
	c.store.r = kvRaft
{'fraction_non_alphanumeric': 0.12620619603859828, 'fraction_numerical': 0.006094464195022855, 'mean_word_length': 2.71253534401508, 'pattern_counts': {'":': 0, '<': 5, '<?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': '5025425', 'n_tokens_mistral': 1520, 'n_tokens_neox': 1424, 'n_words': 358}