<commit_before>package serf

import (
	"errors"
	"fmt"
	"github.com/hashicorp/memberlist"
	"log"
	"math/rand"
	"net"
	"sync"
	"time"
)

func init() {
	// Seed the random number generator
	rand.Seed(time.Now().UnixNano())
}

// Serf is a single node that is part of a single cluster that gets
// events about joins/leaves/failures/etc. It is created with the Create
// method.
//
// All functions on the Serf structure are safe to call concurrently.
type Serf struct {
	broadcasts    *memberlist.TransmitLimitedQueue
	config        *Config
	failedMembers []*oldMember
	leftMembers   []*oldMember
	memberlist    *memberlist.Memberlist
	memberLock    sync.RWMutex
	members       map[string]*Member

	stateLock  sync.Mutex
	state      SerfState
	shutdownCh chan struct{}
}

// SerfState is the state of the Serf instance.
type SerfState int

const (
	SerfAlive SerfState = iota
	SerfLeft
	SerfShutdown
)

// Member is a single member of the Serf cluster.
type Member struct {
	Name   string
	Addr   net.IP
	Role   string
	Status MemberStatus
}

// MemberStatus is the state that a member is in.
type MemberStatus int

const (
	StatusNone MemberStatus = iota
	StatusAlive
	StatusLeaving
	StatusLeft
	StatusFailed
)

// oldMember is used to track members that are no longer active due to
// leaving, failing, partitioning, etc. It tracks the member along with
// when that member was marked as leaving.
type oldMember struct {
	member *Member
	time   time.Time
}

// Create creates a new Serf instance, starting all the background tasks
// to maintain cluster membership information.
//
// After calling this function, the configuration should no longer be used
// or modified by the caller.
func Create(conf *Config) (*Serf, error) {
	// Some configuration validation first.
	if conf.NodeName == "" {
		return nil, errors.New("NodeName must be set")
	}

	if conf.BroadcastTimeout == 0 {
		// Set a cautious default for the timeout for leave broadcasts.
		conf.BroadcastTimeout = 5 * time.Second
	}

	if conf.LeaveTimeout == 0 {
		// Set a cautious default for a leave timeout.
		conf.LeaveTimeout = 120 * time.Second
	}

	if conf.ReapInterval == 0 {
		// Set a reasonable default for ReapInterval
		conf.ReapInterval = 15 * time.Second
	}

	if conf.ReconnectInterval == 0 {
		// Set a reasonable default for ReconnectInterval
		conf.ReconnectInterval = 30 * time.Second
	}

	if conf.ReconnectTimeout == 0 {
		// Set a reasonable default for ReconnectTimeout
		conf.ReconnectTimeout = 24 * time.Hour
	}

	if conf.TombstoneTimeout == 0 {
		// Set a reasonable default for TombstoneTimeout
		conf.TombstoneTimeout = 24 * time.Hour
	}

	serf := &Serf{
		config:     conf,
		members:    make(map[string]*Member),
		shutdownCh: make(chan struct{}),
		state:      SerfAlive,
	}

	if conf.CoalescePeriod > 0 && conf.EventCh != nil {
		// Event coalescence is enabled, setup the channel.
		conf.EventCh = coalescedEventCh(conf.EventCh, serf.shutdownCh,
			conf.CoalescePeriod, conf.QuiescentPeriod)
	}

	// Setup the broadcast queue, which we use to send our own custom
	// broadcasts along the gossip channel.
	serf.broadcasts = &memberlist.TransmitLimitedQueue{
		NumNodes: func() int {
			serf.memberLock.RLock()
			defer serf.memberLock.RUnlock()
			return len(serf.members)
		},
		RetransmitMult: conf.MemberlistConfig.RetransmitMult,
	}

	// Setup the channel used for handling node events. We make this buffered
	// in case our handling can't keep up with the events. The buffer is
	// probably too big, but we'd rather be safe than lose events.
	eventCh := make(chan memberlist.NodeEvent, 64)
<commit_msg>serf: set memberlistconfig default if not set<commit_after>package serf

import (
	"errors"
	"fmt"
	"github.com/hashicorp/memberlist"
	"log"
	"math/rand"
	"net"
	"sync"
	"time"
)

func init() {
	// Seed the random number generator
	rand.Seed(time.Now().UnixNano())
}

// Serf is a single node that is part of a single cluster that gets
// events about joins/leaves/failures/etc. It is created with the Create
// method.
//
// All functions on the Serf structure are safe to call concurrently.
type Serf struct {
	broadcasts    *memberlist.TransmitLimitedQueue
	config        *Config
	failedMembers []*oldMember
	leftMembers   []*oldMember
	memberlist    *memberlist.Memberlist
	memberLock    sync.RWMutex
	members       map[string]*Member

	stateLock  sync.Mutex
	state      SerfState
	shutdownCh chan struct{}
}

// SerfState is the state of the Serf instance.
type SerfState int

const (
	SerfAlive SerfState = iota
	SerfLeft
	SerfShutdown
)

// Member is a single member of the Serf cluster.
type Member struct {
	Name   string
	Addr   net.IP
	Role   string
	Status MemberStatus
}

// MemberStatus is the state that a member is in.
type MemberStatus int

const (
	StatusNone MemberStatus = iota
	StatusAlive
	StatusLeaving
	StatusLeft
	StatusFailed
)

// oldMember is used to track members that are no longer active due to
// leaving, failing, partitioning, etc. It tracks the member along with
// when that member was marked as leaving.
type oldMember struct {
	member *Member
	time   time.Time
}

// Create creates a new Serf instance, starting all the background tasks
// to maintain cluster membership information.
//
// After calling this function, the configuration should no longer be used
// or modified by the caller.
func Create(conf *Config) (*Serf, error) {
	// Some configuration validation first.
	if conf.NodeName == "" {
		return nil, errors.New("NodeName must be set")
	}

	if conf.BroadcastTimeout == 0 {
		// Set a cautious default for the timeout for leave broadcasts.
		conf.BroadcastTimeout = 5 * time.Second
	}

	if conf.LeaveTimeout == 0 {
		// Set a cautious default for a leave timeout.
		conf.LeaveTimeout = 120 * time.Second
	}

	if conf.ReapInterval == 0 {
		// Set a reasonable default for ReapInterval
		conf.ReapInterval = 15 * time.Second
	}

	if conf.ReconnectInterval == 0 {
		// Set a reasonable default for ReconnectInterval
		conf.ReconnectInterval = 30 * time.Second
	}

	if conf.ReconnectTimeout == 0 {
		// Set a reasonable default for ReconnectTimeout
		conf.ReconnectTimeout = 24 * time.Hour
	}

	if conf.TombstoneTimeout == 0 {
		// Set a reasonable default for TombstoneTimeout
		conf.TombstoneTimeout = 24 * time.Hour
	}

	if conf.MemberlistConfig == nil {
		conf.MemberlistConfig = memberlist.DefaultConfig()
	}

	serf := &Serf{
		config:     conf,
		members:    make(map[string]*Member),
		shutdownCh: make(chan struct{}),
		state:      SerfAlive,
	}

	if conf.CoalescePeriod > 0 && conf.EventCh != nil {
		// Event coalescence is enabled, setup the channel.
		conf.EventCh = coalescedEventCh(conf.EventCh, serf.shutdownCh,
			conf.CoalescePeriod, conf.QuiescentPeriod)
	}

	// Setup the broadcast queue, which we use to send our own custom
	// broadcasts along the gossip channel.
	serf.broadcasts = &memberlist.TransmitLimitedQueue{
		NumNodes: func() int {
			serf.memberLock.RLock()
			defer serf.memberLock.RUnlock()
			return len(serf.members)
		},
		RetransmitMult: conf.MemberlistConfig.RetransmitMult,
	}

	// Setup the channel used for handling node events. We make this buffered
	// in case our handling can't keep up with the events. The buffer is
	// probably too big, but we'd rather be safe than lose events.
	eventCh := make(chan memberlist.NodeEvent, 64)

{'fraction_non_alphanumeric': 0.08672493854138213, 'fraction_numerical': 0.0057361376673040155, 'mean_word_length': 3.4598051157125456, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, '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': '5234008', 'n_tokens_mistral': 2415, 'n_tokens_neox': 2252, 'n_words': 803}