diff --git a/cluster.old.tar.gz b/cluster.old.tar.gz new file mode 100644 index 0000000..b27e72d Binary files /dev/null and b/cluster.old.tar.gz differ diff --git a/cluster/async.go b/cluster/async.go deleted file mode 100644 index 41c7984..0000000 --- a/cluster/async.go +++ /dev/null @@ -1,85 +0,0 @@ -//go:build amd64 || arm64 || arm64be || ppc64 || ppc64le || mips64 || mips64le || riscv64 || s390x || sparc64 || wasm -// +build amd64 arm64 arm64be ppc64 ppc64le mips64 mips64le riscv64 s390x sparc64 wasm - -/*********************************************************************************************************************** - * - * MIT License - * - * Copyright (c) 2021 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * - **********************************************************************************************************************/ - -package cluster - -import ( - dgbclt "github.com/lni/dragonboat/v3" - dgbcli "github.com/lni/dragonboat/v3/client" - liberr "github.com/nabbar/golib/errors" -) - -func (c *cRaft) AsyncPropose(session *dgbcli.Session, cmd []byte) (*dgbclt.RequestState, liberr.Error) { - r, e := c.nodeHost.Propose(session, cmd, c.timeoutCmdASync) - - if e != nil { - return r, ErrorCommandASync.Error(c.getErrorCommand("Propose"), e) - } - - return r, nil -} - -func (c *cRaft) AsyncProposeSession(session *dgbcli.Session) (*dgbclt.RequestState, liberr.Error) { - r, e := c.nodeHost.ProposeSession(session, c.timeoutCmdASync) - - if e != nil { - return r, ErrorCommandASync.Error(c.getErrorCommand("ProposeSession"), e) - } - - return r, nil -} - -func (c *cRaft) AsyncReadIndex() (*dgbclt.RequestState, liberr.Error) { - r, e := c.nodeHost.ReadIndex(c.config.ClusterID, c.timeoutCmdASync) - - if e != nil { - return r, ErrorCommandASync.Error(c.getErrorCluster(), c.getErrorCommand("ReadIndex"), e) - } - - return r, nil -} - -func (c *cRaft) AsyncRequestCompaction(nodeID uint64) (*dgbclt.SysOpState, liberr.Error) { - var er error - if nodeID == 0 { - nodeID = c.config.NodeID - er = c.getErrorNode() - } else { - er = c.getErrorNodeTarget(nodeID) - } - - r, e := c.nodeHost.RequestCompaction(c.config.ClusterID, nodeID) - - if e != nil { - return r, ErrorCommandASync.Error(c.getErrorCluster(), er, c.getErrorCommand("RequestCompaction"), e) - } - - return r, nil -} diff --git a/cluster/cluster.go b/cluster/cluster.go deleted file mode 100644 index 2d9df95..0000000 --- a/cluster/cluster.go +++ /dev/null @@ -1,298 +0,0 @@ -//go:build amd64 || arm64 || arm64be || ppc64 || ppc64le || mips64 || mips64le || riscv64 || s390x || sparc64 || wasm -// +build amd64 arm64 arm64be ppc64 ppc64le mips64 mips64le riscv64 s390x sparc64 wasm - -/*********************************************************************************************************************** - * - * MIT License - * - * Copyright (c) 2021 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * - **********************************************************************************************************************/ - -package cluster - -import ( - "fmt" - "io" - "time" - - dgbclt "github.com/lni/dragonboat/v3" - dgbcli "github.com/lni/dragonboat/v3/client" - dgbcfg "github.com/lni/dragonboat/v3/config" - dgbstm "github.com/lni/dragonboat/v3/statemachine" - liberr "github.com/nabbar/golib/errors" -) - -type cRaft struct { - memberInit map[uint64]dgbclt.Target - fctCreate interface{} - config dgbcfg.Config - nodeHost *dgbclt.NodeHost - timeoutCmdSync time.Duration - timeoutCmdASync time.Duration -} - -func (c *cRaft) getErrorCluster() error { - //nolint #goerr113 - return fmt.Errorf("cluster: %v", c.config.ClusterID) -} - -func (c *cRaft) getErrorNode() error { - //nolint #goerr113 - return fmt.Errorf("node: %v", c.config.NodeID) -} - -func (c *cRaft) getErrorNodeTarget(target uint64) error { - //nolint #goerr113 - return fmt.Errorf("target node: %v", target) -} - -func (c *cRaft) getErrorCommand(cmd string) error { - //nolint #goerr113 - return fmt.Errorf("command: %v", cmd) -} - -func (c *cRaft) GetConfig() dgbcfg.Config { - return c.config -} - -func (c *cRaft) SetConfig(cfg dgbcfg.Config) { - c.config = cfg -} - -func (c *cRaft) GetFctCreate() dgbstm.CreateStateMachineFunc { - if f, ok := c.fctCreate.(dgbstm.CreateStateMachineFunc); ok { - return f - } - return nil -} - -func (c *cRaft) GetFctCreateConcurrent() dgbstm.CreateConcurrentStateMachineFunc { - if f, ok := c.fctCreate.(dgbstm.CreateConcurrentStateMachineFunc); ok { - return f - } - return nil -} - -func (c *cRaft) GetFctCreateOnDisk() dgbstm.CreateOnDiskStateMachineFunc { - if f, ok := c.fctCreate.(dgbstm.CreateOnDiskStateMachineFunc); ok { - return f - } - return nil -} - -func (c *cRaft) SetFctCreate(fctCreate interface{}) { - c.fctCreate = fctCreate -} - -func (c *cRaft) SetFctCreateSTM(fctCreate dgbstm.CreateStateMachineFunc) { - c.fctCreate = fctCreate -} - -func (c *cRaft) SetFctCreateSTMConcurrent(fctCreate dgbstm.CreateConcurrentStateMachineFunc) { - c.fctCreate = fctCreate -} - -func (c *cRaft) SetFctCreateSTMOnDisk(fctCreate dgbstm.CreateOnDiskStateMachineFunc) { - c.fctCreate = fctCreate -} - -func (c *cRaft) GetMemberInit() map[uint64]dgbclt.Target { - return c.memberInit -} - -func (c *cRaft) SetMemberInit(memberList map[uint64]dgbclt.Target) { - c.memberInit = memberList -} - -func (c *cRaft) SetTimeoutCommandSync(timeout time.Duration) { - c.timeoutCmdSync = timeout -} - -func (c *cRaft) SetTimeoutCommandASync(timeout time.Duration) { - c.timeoutCmdASync = timeout -} - -func (c *cRaft) GetNodeHostConfig() dgbcfg.NodeHostConfig { - return c.nodeHost.NodeHostConfig() -} - -func (c *cRaft) RaftAddress() string { - return c.nodeHost.RaftAddress() -} - -func (c *cRaft) ID() string { - return c.nodeHost.ID() -} - -func (c *cRaft) ClusterStart(join bool) liberr.Error { - err := ErrorNodeHostStart.Error(nil) - - if join { - err = ErrorNodeHostJoin.Error(nil) - } - - if f, ok := c.fctCreate.(dgbstm.CreateStateMachineFunc); ok { - err.Add(c.nodeHost.StartCluster(c.memberInit, join, f, c.config)) - } else if f, ok := c.fctCreate.(dgbstm.CreateConcurrentStateMachineFunc); ok { - err.Add(c.nodeHost.StartConcurrentCluster(c.memberInit, join, f, c.config)) - } else if f, ok := c.fctCreate.(dgbstm.CreateOnDiskStateMachineFunc); ok { - err.Add(c.nodeHost.StartOnDiskCluster(c.memberInit, join, f, c.config)) - } else { - //nolint #goerr113 - return ErrorParamsMismatching.Error(fmt.Errorf("create function is not one of type of CreateStateMachineFunc, CreateConcurrentStateMachineFunc, CreateOnDiskStateMachineFunc")) - } - - if err.HasParent() { - return err - } - - return nil -} - -func (c *cRaft) ClusterStop(force bool) liberr.Error { - e := c.nodeHost.StopCluster(c.config.ClusterID) - - if e != nil && !force { - return ErrorNodeHostStop.Error(c.getErrorCluster(), e) - } - - c.nodeHost.Stop() - return nil -} - -func (c *cRaft) ClusterRestart(force bool) liberr.Error { - if err := c.ClusterStop(force); err != nil { - return ErrorNodeHostRestart.Error(err) - } - - return c.ClusterStart(false) -} - -func (c *cRaft) NodeStop(target uint64) liberr.Error { - var en error - if target == 0 { - target = c.config.NodeID - en = c.getErrorNode() - } else { - en = c.getErrorNodeTarget(target) - } - - e := c.nodeHost.StopNode(c.config.ClusterID, target) - - if e != nil { - return ErrorNodeHostStop.Error(c.getErrorCluster(), en, e) - } - - return nil -} - -func (c *cRaft) NodeRestart(force bool) liberr.Error { - var join = false - - if l, ok, err := c.GetLeaderID(); err == nil && ok && l == c.config.NodeID { - join = true - var sErr = ErrorNodeHostRestart.Error(c.getErrorCluster(), c.getErrorNode()) - for id, nd := range c.memberInit { - if id == c.config.NodeID { - continue - } - if nd == c.RaftAddress() { - continue - } - if err = c.RequestLeaderTransfer(id); err == nil { - sErr.Add(err) - break - } - } - if l, ok, err = c.GetLeaderID(); err == nil && ok && l == c.config.NodeID && !force { - return sErr - } - } else if err == nil && ok { - join = true - } - - if err := c.NodeStop(0); err != nil && !force { - return ErrorNodeHostRestart.Error(err) - } else if err != nil && force { - join = false - _ = c.ClusterStop(true) - } - - return c.ClusterStart(join) -} - -func (c *cRaft) GetLeaderID() (leader uint64, valid bool, err liberr.Error) { - var e error - - leader, valid, e = c.nodeHost.GetLeaderID(c.config.ClusterID) - - if e != nil { - err = ErrorLeader.Error(c.getErrorCluster(), e) - } - - return -} - -func (c *cRaft) GetNoOPSession() *dgbcli.Session { - return c.nodeHost.GetNoOPSession(c.config.ClusterID) -} - -func (c *cRaft) GetNodeUser() (dgbclt.INodeUser, liberr.Error) { - r, e := c.nodeHost.GetNodeUser(c.config.ClusterID) - - if e != nil { - return nil, ErrorNodeUser.Error(c.getErrorCluster()) - } - - return r, nil -} - -func (c *cRaft) HasNodeInfo(nodeId uint64) bool { - if nodeId == 0 { - nodeId = c.config.NodeID - } - - return c.nodeHost.HasNodeInfo(c.config.ClusterID, nodeId) -} - -func (c *cRaft) GetNodeHostInfo(opt dgbclt.NodeHostInfoOption) *dgbclt.NodeHostInfo { - return c.nodeHost.GetNodeHostInfo(opt) -} - -func (c *cRaft) StaleReadDangerous(query interface{}) (interface{}, error) { - return c.nodeHost.StaleRead(c.config.ClusterID, query) -} - -func (c *cRaft) RequestLeaderTransfer(targetNodeID uint64) liberr.Error { - e := c.nodeHost.RequestLeaderTransfer(c.config.ClusterID, targetNodeID) - - if e != nil { - return ErrorLeaderTransfer.Error(c.getErrorCluster(), c.getErrorNodeTarget(targetNodeID), e) - } - - return nil -} - -func (c *cRaft) HandlerMetrics(w io.Writer) { - dgbclt.WriteHealthMetrics(w) -} diff --git a/cluster/config.go b/cluster/config.go deleted file mode 100644 index 7ce538c..0000000 --- a/cluster/config.go +++ /dev/null @@ -1,85 +0,0 @@ -//go:build amd64 || arm64 || arm64be || ppc64 || ppc64le || mips64 || mips64le || riscv64 || s390x || sparc64 || wasm -// +build amd64 arm64 arm64be ppc64 ppc64le mips64 mips64le riscv64 s390x sparc64 wasm - -/*********************************************************************************************************************** - * - * MIT License - * - * Copyright (c) 2021 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * - **********************************************************************************************************************/ - -package cluster - -import ( - "fmt" - - libval "github.com/go-playground/validator/v10" - dgbclt "github.com/lni/dragonboat/v3" - dgbcfg "github.com/lni/dragonboat/v3/config" - liberr "github.com/nabbar/golib/errors" -) - -type Config struct { - Node ConfigNode `mapstructure:"node" json:"node" yaml:"node" toml:"node" validate:""` - Cluster ConfigCluster `mapstructure:"cluster" json:"cluster" yaml:"cluster" toml:"cluster" validate:""` - InitMember map[uint64]string `mapstructure:"init_member" json:"init_member" yaml:"init_member" toml:"init_member"` -} - -func (c Config) GetDGBConfigCluster() dgbcfg.Config { - return c.Cluster.GetDGBConfigCluster() -} - -func (c Config) GetDGBConfigNode() dgbcfg.NodeHostConfig { - return c.Node.GetDGBConfigNodeHost() -} - -func (c Config) GetInitMember() map[uint64]dgbclt.Target { - var m = make(map[uint64]dgbclt.Target) - - for k, v := range c.InitMember { - m[k] = v - } - - return m -} - -func (c Config) Validate() liberr.Error { - err := ErrorValidateConfig.Error(nil) - - if er := libval.New().Struct(c); er != nil { - if e, ok := er.(*libval.InvalidValidationError); ok { - err.Add(e) - } - - for _, e := range er.(libval.ValidationErrors) { - //nolint goerr113 - err.Add(fmt.Errorf("config field '%s' is not validated by constraint '%s'", e.Namespace(), e.ActualTag())) - } - } - - if err.HasParent() { - return err - } - - return nil -} diff --git a/cluster/configCluster.go b/cluster/configCluster.go deleted file mode 100644 index 821a7d5..0000000 --- a/cluster/configCluster.go +++ /dev/null @@ -1,265 +0,0 @@ -//go:build amd64 || arm64 || arm64be || ppc64 || ppc64le || mips64 || mips64le || riscv64 || s390x || sparc64 || wasm -// +build amd64 arm64 arm64be ppc64 ppc64le mips64 mips64le riscv64 s390x sparc64 wasm - -/*********************************************************************************************************************** - * - * MIT License - * - * Copyright (c) 2021 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * - **********************************************************************************************************************/ - -package cluster - -import ( - "fmt" - - libval "github.com/go-playground/validator/v10" - dgbcfg "github.com/lni/dragonboat/v3/config" - liberr "github.com/nabbar/golib/errors" -) - -// nolint #maligned -type ConfigCluster struct { - // NodeID is a non-zero value used to identify a node within a Raft cluster. - NodeID uint64 `mapstructure:"node_id" json:"node_id" yaml:"node_id" toml:"node_id"` - - // ClusterID is the unique value used to identify a Raft cluster. - ClusterID uint64 `mapstructure:"cluster_id" json:"cluster_id" yaml:"cluster_id" toml:"cluster_id"` - - // CheckQuorum specifies whether the leader node should periodically check - // non-leader node status and step down to become a follower node when it no - // longer has the quorum. - CheckQuorum bool `mapstructure:"check_quorum" json:"check_quorum" yaml:"check_quorum" toml:"check_quorum"` - - // ElectionRTT is the minimum number of message RTT between elections. Message - // RTT is defined by NodeHostConfig.RTTMillisecond. The Raft paper suggests it - // to be a magnitude greater than HeartbeatRTT, which is the interval between - // two heartbeats. In Raft, the actual interval between elections is - // randomized to be between ElectionRTT and 2 * ElectionRTT. - // - // As an example, assuming NodeHostConfig.RTTMillisecond is 100 millisecond, - // to set the election interval to be 1 second, then ElectionRTT should be set - // to 10. - // - // When CheckQuorum is enabled, ElectionRTT also defines the interval for - // checking leader quorum. - ElectionRTT uint64 `mapstructure:"election_rtt" json:"election_rtt" yaml:"election_rtt" toml:"election_rtt"` - - // HeartbeatRTT is the number of message RTT between heartbeats. Message - // RTT is defined by NodeHostConfig.RTTMillisecond. The Raft paper suggest the - // heartbeat interval to be close to the average RTT between nodes. - // - // As an example, assuming NodeHostConfig.RTTMillisecond is 100 millisecond, - // to set the heartbeat interval to be every 200 milliseconds, then - // HeartbeatRTT should be set to 2. - HeartbeatRTT uint64 `mapstructure:"heartbeat_rtt" json:"heartbeat_rtt" yaml:"heartbeat_rtt" toml:"heartbeat_rtt"` - - // SnapshotEntries defines how often the state machine should be snapshotted - // automcatically. It is defined in terms of the number of applied Raft log - // entries. SnapshotEntries can be set to 0 to disable such automatic - // snapshotting. - // - // When SnapshotEntries is set to N, it means a snapshot is created for - // roughly every N applied Raft log entries (proposals). This also implies - // that sending N log entries to a follower is more expensive than sending a - // snapshot. - // - // Once a snapshot is generated, Raft log entries covered by the new snapshot - // can be compacted. This involves two steps, redundant log entries are first - // marked as deleted, then they are physically removed from the underlying - // storage when a LogDB compaction is issued at a later stage. See the godoc - // on CompactionOverhead for details on what log entries are actually removed - // and compacted after generating a snapshot. - // - // Once automatic snapshotting is disabled by setting the SnapshotEntries - // field to 0, users can still use NodeHost's RequestSnapshot or - // SyncRequestSnapshot methods to manually request snapshots. - SnapshotEntries uint64 `mapstructure:"snapshot_entries" json:"snapshot_entries" yaml:"snapshot_entries" toml:"snapshot_entries"` - - // CompactionOverhead defines the number of most recent entries to keep after - // each Raft log compaction. Raft log compaction is performance automatically - // every time when a snapshot is created. - // - // For example, when a snapshot is created at let's say index 10,000, then all - // Raft log entries with index <= 10,000 can be removed from that node as they - // have already been covered by the created snapshot image. This frees up the - // maximum storage space but comes at the cost that the full snapshot will - // have to be sent to the follower if the follower requires any Raft log entry - // at index <= 10,000. When CompactionOverhead is set to say 500, Dragonboat - // then compacts the Raft log up to index 9,500 and keeps Raft log entries - // between index (9,500, 1,0000]. As a result, the node can still replicate - // Raft log entries between index (9,500, 1,0000] to other peers and only fall - // back to stream the full snapshot if any Raft log entry with index <= 9,500 - // is required to be replicated. - CompactionOverhead uint64 `mapstructure:"compaction_overhead" json:"compaction_overhead" yaml:"compaction_overhead" toml:"compaction_overhead"` - - // OrderedConfigChange determines whether Raft membership change is enforced - // with ordered config change ID. - OrderedConfigChange bool `mapstructure:"ordered_config_change" json:"ordered_config_change" yaml:"ordered_config_change" toml:"ordered_config_change"` - - // MaxInMemLogSize is the target size in bytes allowed for storing in memory - // Raft logs on each Raft node. In memory Raft logs are the ones that have - // not been applied yet. - // MaxInMemLogSize is a target value implemented to prevent unbounded memory - // growth, it is not for precisely limiting the exact memory usage. - // When MaxInMemLogSize is 0, the target is set to math.MaxUint64. When - // MaxInMemLogSize is set and the target is reached, error will be returned - // when clients try to make new proposals. - // MaxInMemLogSize is recommended to be significantly larger than the biggest - // proposal you are going to use. - MaxInMemLogSize uint64 `mapstructure:"max_in_mem_log_size" json:"max_in_mem_log_size" yaml:"max_in_mem_log_size" toml:"max_in_mem_log_size"` - - // SnapshotCompressionType is the compression type to use for compressing - // generated snapshot data. No compression is used by default. - SnapshotCompressionType dgbcfg.CompressionType `mapstructure:"snapshot_compression" json:"snapshot_compression" yaml:"snapshot_compression" toml:"snapshot_compression"` - - // EntryCompressionType is the compression type to use for compressing the - // payload of user proposals. When Snappy is used, the maximum proposal - // payload allowed is roughly limited to 3.42GBytes. No compression is used - // by default. - EntryCompressionType dgbcfg.CompressionType `mapstructure:"entry_compression" json:"entry_compression" yaml:"entry_compression" toml:"entry_compression"` - - // DisableAutoCompactions disables auto compaction used for reclaiming Raft - // log entry storage spaces. By default, compaction request is issued every - // time when a snapshot is created, this helps to reclaim disk spaces as - // soon as possible at the cost of immediate higher IO overhead. Users can - // disable such auto compactions and use NodeHost.RequestCompaction to - // manually request such compactions when necessary. - DisableAutoCompactions bool `mapstructure:"disable_auto_compactions" json:"disable_auto_compactions" yaml:"disable_auto_compactions" toml:"disable_auto_compactions"` - - // IsObserver indicates whether this is an observer Raft node without voting - // power. Described as non-voting members in the section 4.2.1 of Diego - // Ongaro's thesis, observer nodes are usually used to allow a new node to - // join the cluster and catch up with other existing ndoes without impacting - // the availability. Extra observer nodes can also be introduced to serve - // read-only requests without affecting system write throughput. - // - // Observer support is currently experimental. - IsObserver bool `mapstructure:"is_observer" json:"is_observer" yaml:"is_observer" toml:"is_observer"` - - // IsWitness indicates whether this is a witness Raft node without actual log - // replication and do not have state machine. It is mentioned in the section - // 11.7.2 of Diego Ongaro's thesis. - // - // Witness support is currently experimental. - IsWitness bool `mapstructure:"is_witness" json:"is_witness" yaml:"is_witness" toml:"is_witness"` - - // Quiesce specifies whether to let the Raft cluster enter quiesce mode when - // there is no cluster activity. Clusters in quiesce mode do not exchange - // heartbeat messages to minimize bandwidth consumption. - // - // Quiesce support is currently experimental. - Quiesce bool `mapstructure:"quiesce" json:"quiesce" yaml:"quiesce" toml:"quiesce"` -} - -func (c ConfigCluster) GetDGBConfigCluster() dgbcfg.Config { - d := dgbcfg.Config{ - NodeID: c.NodeID, - ClusterID: c.ClusterID, - SnapshotCompressionType: 0, - EntryCompressionType: 0, - } - - if c.CheckQuorum { - d.CheckQuorum = true - } - - if c.ElectionRTT > 0 { - d.ElectionRTT = c.ElectionRTT - } - - if c.HeartbeatRTT > 0 { - d.HeartbeatRTT = c.HeartbeatRTT - } - - if c.SnapshotEntries > 0 { - d.SnapshotEntries = c.SnapshotEntries - } - - if c.CompactionOverhead > 0 { - d.CompactionOverhead = c.CompactionOverhead - } - - if c.OrderedConfigChange { - d.OrderedConfigChange = true - } - - if c.MaxInMemLogSize > 0 { - d.MaxInMemLogSize = c.MaxInMemLogSize - } - - if c.DisableAutoCompactions { - d.DisableAutoCompactions = true - } - - if c.IsObserver { - d.IsObserver = true - } - - if c.IsWitness { - d.IsWitness = true - } - - if c.Quiesce { - d.Quiesce = true - } - - //nolint #exhaustive - switch c.SnapshotCompressionType { - case dgbcfg.Snappy: - d.SnapshotCompressionType = dgbcfg.Snappy - default: - d.SnapshotCompressionType = dgbcfg.NoCompression - } - - //nolint #exhaustive - switch c.EntryCompressionType { - case dgbcfg.Snappy: - d.EntryCompressionType = dgbcfg.Snappy - default: - d.EntryCompressionType = dgbcfg.NoCompression - } - - return d -} - -func (c ConfigCluster) Validate() liberr.Error { - err := ErrorValidateConfig.Error(nil) - - if er := libval.New().Struct(c); er != nil { - if e, ok := er.(*libval.InvalidValidationError); ok { - err.Add(e) - } - - for _, e := range er.(libval.ValidationErrors) { - //nolint goerr113 - err.Add(fmt.Errorf("config field '%s' is not validated by constraint '%s'", e.Namespace(), e.ActualTag())) - } - } - - if err.HasParent() { - return err - } - - return nil -} diff --git a/cluster/configEngine.go b/cluster/configEngine.go deleted file mode 100644 index f49de94..0000000 --- a/cluster/configEngine.go +++ /dev/null @@ -1,109 +0,0 @@ -//go:build amd64 || arm64 || arm64be || ppc64 || ppc64le || mips64 || mips64le || riscv64 || s390x || sparc64 || wasm -// +build amd64 arm64 arm64be ppc64 ppc64le mips64 mips64le riscv64 s390x sparc64 wasm - -/*********************************************************************************************************************** - * - * MIT License - * - * Copyright (c) 2021 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * - **********************************************************************************************************************/ - -package cluster - -import ( - "fmt" - - libval "github.com/go-playground/validator/v10" - dgbcfg "github.com/lni/dragonboat/v3/config" - liberr "github.com/nabbar/golib/errors" -) - -type ConfigEngine struct { - // ExecShards is the number of execution shards in the first stage of the - // execution engine. Default value is 16. Once deployed, this value can not - // be changed later. - ExecShards uint64 `mapstructure:"exec_shards" json:"exec_shards" yaml:"exec_shards" toml:"exec_shards"` - - // CommitShards is the number of commit shards in the second stage of the - // execution engine. Default value is 16. - CommitShards uint64 `mapstructure:"commit_shards" json:"commit_shards" yaml:"commit_shards" toml:"commit_shards"` - - // ApplyShards is the number of apply shards in the third stage of the - // execution engine. Default value is 16. - ApplyShards uint64 `mapstructure:"apply_shards" json:"apply_shards" yaml:"apply_shards" toml:"apply_shards"` - - // SnapshotShards is the number of snapshot shards in the forth stage of the - // execution engine. Default value is 48. - SnapshotShards uint64 `mapstructure:"snapshot_shards" json:"snapshot_shards" yaml:"snapshot_shards" toml:"snapshot_shards"` - - // CloseShards is the number of close shards used for closing stopped - // state machines. Default value is 32. - CloseShards uint64 `mapstructure:"close_shards" json:"close_shards" yaml:"close_shards" toml:"close_shards"` -} - -func (c ConfigEngine) GetDGBConfigEngine() dgbcfg.EngineConfig { - d := dgbcfg.EngineConfig{} - - if c.ExecShards > 0 { - d.ExecShards = c.ExecShards - } - - if c.CommitShards > 0 { - d.CommitShards = c.CommitShards - } - - if c.ApplyShards > 0 { - d.ApplyShards = c.ApplyShards - } - - if c.SnapshotShards > 0 { - d.SnapshotShards = c.SnapshotShards - } - - if c.CloseShards > 0 { - d.CloseShards = c.CloseShards - } - - return d -} - -func (c ConfigEngine) Validate() liberr.Error { - err := ErrorValidateConfig.Error(nil) - - if er := libval.New().Struct(c); er != nil { - if e, ok := er.(*libval.InvalidValidationError); ok { - err.Add(e) - } - - for _, e := range er.(libval.ValidationErrors) { - //nolint goerr113 - err.Add(fmt.Errorf("config field '%s' is not validated by constraint '%s'", e.Namespace(), e.ActualTag())) - } - } - - if err.HasParent() { - return err - } - - return nil -} diff --git a/cluster/configExpert.go b/cluster/configExpert.go deleted file mode 100644 index d47b56d..0000000 --- a/cluster/configExpert.go +++ /dev/null @@ -1,90 +0,0 @@ -//go:build amd64 || arm64 || arm64be || ppc64 || ppc64le || mips64 || mips64le || riscv64 || s390x || sparc64 || wasm -// +build amd64 arm64 arm64be ppc64 ppc64le mips64 mips64le riscv64 s390x sparc64 wasm - -/*********************************************************************************************************************** - * - * MIT License - * - * Copyright (c) 2021 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * - **********************************************************************************************************************/ - -package cluster - -import ( - "fmt" - "time" - - libval "github.com/go-playground/validator/v10" - dgbcfg "github.com/lni/dragonboat/v3/config" - liberr "github.com/nabbar/golib/errors" -) - -type ConfigExpert struct { - // Engine is the cponfiguration for the execution engine. - Engine ConfigEngine `mapstructure:"engine" json:"engine" yaml:"engine" toml:"engine"` - - // TestNodeHostID is the NodeHostID value to be used by the NodeHost instance. - // This field is expected to be used in tests only. - TestNodeHostID uint64 `mapstructure:"test_node_host_id" json:"test_node_host_id" yaml:"test_node_host_id" toml:"test_node_host_id"` - - // TestGossipProbeInterval define the probe interval used by the gossip - // service in tests. - TestGossipProbeInterval time.Duration `mapstructure:"test_gossip_probe_interval" json:"test_gossip_probe_interval" yaml:"test_gossip_probe_interval" toml:"test_gossip_probe_interval"` -} - -func (c ConfigExpert) GetDGBConfigExpert() dgbcfg.ExpertConfig { - d := dgbcfg.ExpertConfig{ - Engine: c.Engine.GetDGBConfigEngine(), - } - - if c.TestNodeHostID > 0 { - d.TestNodeHostID = c.TestNodeHostID - } - - if c.TestGossipProbeInterval > 0 { - d.TestGossipProbeInterval = c.TestGossipProbeInterval - } - - return d -} - -func (c ConfigExpert) Validate() liberr.Error { - err := ErrorValidateConfig.Error(nil) - - if er := libval.New().Struct(c); er != nil { - if e, ok := er.(*libval.InvalidValidationError); ok { - err.Add(e) - } - - for _, e := range er.(libval.ValidationErrors) { - //nolint goerr113 - err.Add(fmt.Errorf("config field '%s' is not validated by constraint '%s'", e.Namespace(), e.ActualTag())) - } - } - - if err.HasParent() { - return err - } - - return nil -} diff --git a/cluster/configGossip.go b/cluster/configGossip.go deleted file mode 100644 index 39b6571..0000000 --- a/cluster/configGossip.go +++ /dev/null @@ -1,114 +0,0 @@ -//go:build amd64 || arm64 || arm64be || ppc64 || ppc64le || mips64 || mips64le || riscv64 || s390x || sparc64 || wasm -// +build amd64 arm64 arm64be ppc64 ppc64le mips64 mips64le riscv64 s390x sparc64 wasm - -/*********************************************************************************************************************** - * - * MIT License - * - * Copyright (c) 2021 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * - **********************************************************************************************************************/ - -package cluster - -import ( - "fmt" - - libval "github.com/go-playground/validator/v10" - dgbcfg "github.com/lni/dragonboat/v3/config" - liberr "github.com/nabbar/golib/errors" -) - -type ConfigGossip struct { - // BindAddress is the address for the gossip service to bind to and listen on. - // Both UDP and TCP ports are used by the gossip service. The local gossip - // service should be able to receive gossip service related messages by - // binding to and listening on this address. BindAddress is usually in the - // format of IP:Port, Hostname:Port or DNS Name:Port. - BindAddress string `mapstructure:"bind_address" json:"bind_address" yaml:"bind_address" toml:"bind_address" validate:"omitempty,hostname_port"` - - // AdvertiseAddress is the address to advertise to other NodeHost instances - // used for NAT traversal. Gossip services running on remote NodeHost - // instances will use AdvertiseAddress to exchange gossip service related - // messages. AdvertiseAddress is in the format of IP:Port. - AdvertiseAddress string `mapstructure:"advertise_address" json:"advertise_address" yaml:"advertise_address" toml:"advertise_address" validate:"omitempty,printascii"` - - // Seed is a list of AdvertiseAddress of remote NodeHost instances. Local - // NodeHost instance will try to contact all of them to bootstrap the gossip - // service. At least one reachable NodeHost instance is required to - // successfully bootstrap the gossip service. Each seed address is in the - // format of IP:Port, Hostname:Port or DNS Name:Port. - // - // It is ok to include seed addresses that are temporarily unreachable, e.g. - // when launching the first NodeHost instance in your deployment, you can - // include AdvertiseAddresses from other NodeHost instances that you plan to - // launch shortly afterwards. - Seed []string `mapstructure:"seed" json:"seed" yaml:"seed" toml:"seed"` -} - -func (c ConfigGossip) GetDGBConfigGossip() dgbcfg.GossipConfig { - d := dgbcfg.GossipConfig{} - - if c.BindAddress != "" { - d.BindAddress = c.BindAddress - } - - if c.AdvertiseAddress != "" { - d.AdvertiseAddress = c.AdvertiseAddress - } - - if len(c.Seed) > 0 { - d.Seed = make([]string, 0) - - for _, v := range c.Seed { - - if v == "" { - continue - } - - d.Seed = append(d.Seed, v) - } - } - - return d -} - -func (c ConfigGossip) Validate() liberr.Error { - err := ErrorValidateConfig.Error(nil) - - if er := libval.New().Struct(c); er != nil { - if e, ok := er.(*libval.InvalidValidationError); ok { - err.Add(e) - } - - for _, e := range er.(libval.ValidationErrors) { - //nolint goerr113 - err.Add(fmt.Errorf("config field '%s' is not validated by constraint '%s'", e.Namespace(), e.ActualTag())) - } - } - - if err.HasParent() { - return err - } - - return nil -} diff --git a/cluster/configNode.go b/cluster/configNode.go deleted file mode 100644 index e5bd52a..0000000 --- a/cluster/configNode.go +++ /dev/null @@ -1,339 +0,0 @@ -//go:build amd64 || arm64 || arm64be || ppc64 || ppc64le || mips64 || mips64le || riscv64 || s390x || sparc64 || wasm -// +build amd64 arm64 arm64be ppc64 ppc64le mips64 mips64le riscv64 s390x sparc64 wasm - -/*********************************************************************************************************************** - * - * MIT License - * - * Copyright (c) 2021 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * - **********************************************************************************************************************/ - -package cluster - -import ( - "fmt" - - libval "github.com/go-playground/validator/v10" - dgbcfg "github.com/lni/dragonboat/v3/config" - liberr "github.com/nabbar/golib/errors" -) - -// nolint #maligned -type ConfigNode struct { - // DeploymentID is used to determine whether two NodeHost instances belong to - // the same deployment and thus allowed to communicate with each other. This - // helps to prvent accidentially misconfigured NodeHost instances to cause - // data corruption errors by sending out of context messages to unrelated - // Raft nodes. - // For a particular dragonboat based application, you can set DeploymentID - // to the same uint64 value on all production NodeHost instances, then use - // different DeploymentID values on your staging and dev environment. It is - // also recommended to use different DeploymentID values for different - // dragonboat based applications. - // When not set, the default value 0 will be used as the deployment ID and - // thus allowing all NodeHost instances with deployment ID 0 to communicate - // with each other. - DeploymentID uint64 `mapstructure:"deployment_id" json:"deployment_id" yaml:"deployment_id" toml:"deployment_id"` - - // WALDir is the directory used for storing the WAL of Raft entries. It is - // recommended to use low latency storage such as NVME SSD with power loss - // protection to store such WAL data. Leave WALDir to have zero value will - // have everything stored in NodeHostDir. - WALDir string `mapstructure:"wal_dir" json:"wal_dir" yaml:"wal_dir" toml:"wal_dir" validate:"omitempty,printascii"` - - // NodeHostDir is where everything else is stored. - NodeHostDir string `mapstructure:"node_host_dir" json:"node_host_dir" yaml:"node_host_dir" toml:"node_host_dir" validate:"omitempty,printascii"` - - //nolint #godox - // RTTMillisecond defines the average Rround Trip Time (RTT) in milliseconds - // between two NodeHost instances. Such a RTT interval is internally used as - // a logical clock tick, Raft heartbeat and election intervals are both - // defined in term of how many such logical clock ticks (RTT intervals). - // Note that RTTMillisecond is the combined delays between two NodeHost - // instances including all delays caused by network transmission, delays - // caused by NodeHost queuing and processing. As an example, when fully - // loaded, the average Rround Trip Time between two of our NodeHost instances - // used for benchmarking purposes is up to 500 microseconds when the ping time - // between them is 100 microseconds. Set RTTMillisecond to 1 when it is less - // than 1 million in your environment. - RTTMillisecond uint64 `mapstructure:"rtt_millisecond" json:"rtt_millisecond" yaml:"rtt_millisecond" toml:"rtt_millisecond"` - - // RaftAddress is a DNS name:port or IP:port address used by the transport - // module for exchanging Raft messages, snapshots and metadata between - // NodeHost instances. It should be set to the public address that can be - // accessed from remote NodeHost instances. - // - // When the NodeHostConfig.ListenAddress field is empty, NodeHost listens on - // RaftAddress for incoming Raft messages. When hostname or domain name is - // used, it will be resolved to IPv4 addresses first and Dragonboat listens - // to all resolved IPv4 addresses. - // - // By default, the RaftAddress value is not allowed to change between NodeHost - // restarts. AddressByNodeHostID should be set to true when the RaftAddress - // value might change after restart. - RaftAddress string `mapstructure:"raft_address" json:"raft_address" yaml:"raft_address" toml:"raft_address" validate:"omitempty,printascii"` - - //nolint #godox - // AddressByNodeHostID indicates that NodeHost instances should be addressed - // by their NodeHostID values. This feature is usually used when only dynamic - // addresses are available. When enabled, NodeHostID values should be used - // as the target parameter when calling NodeHost's StartCluster, - // RequestAddNode, RequestAddObserver and RequestAddWitness methods. - // - // Enabling AddressByNodeHostID also enables the internal gossip service, - // NodeHostConfig.Gossip must be configured to control the behaviors of the - // gossip service. - // - // Note that once enabled, the AddressByNodeHostID setting can not be later - // disabled after restarts. - // - // Please see the godocs of the NodeHostConfig.Gossip field for a detailed - // example on how AddressByNodeHostID and gossip works. - AddressByNodeHostID bool `mapstructure:"address_by_node_host_id" json:"address_by_node_host_id" yaml:"address_by_node_host_id" toml:"address_by_node_host_id"` - - // ListenAddress is an optional field in the hostname:port or IP:port address - // form used by the transport module to listen on for Raft message and - // snapshots. When the ListenAddress field is not set, The transport module - // listens on RaftAddress. If 0.0.0.0 is specified as the IP of the - // ListenAddress, Dragonboat listens to the specified port on all network - // interfaces. When hostname or domain name is used, it will be resolved to - // IPv4 addresses first and Dragonboat listens to all resolved IPv4 addresses. - ListenAddress string `mapstructure:"listen_address" json:"listen_address" yaml:"listen_address" toml:"listen_address" validate:"omitempty,hostname_port"` - - // MutualTLS defines whether to use mutual TLS for authenticating servers - // and clients. Insecure communication is used when MutualTLS is set to - // False. - // See https://github.com/lni/dragonboat/wiki/TLS-in-Dragonboat for more - // details on how to use Mutual TLS. - MutualTLS bool `mapstructure:"mutual_tls" json:"mutual_tls" yaml:"tls" toml:"tls"` - - // CAFile is the path of the CA certificate file. This field is ignored when - // MutualTLS is false. - CAFile string `mapstructure:"ca_file" json:"ca_file" yaml:"ca_file" toml:"ca_file"` - - // CertFile is the path of the node certificate file. This field is ignored - // when MutualTLS is false. - CertFile string `mapstructure:"cert_file" json:"cert_file" yaml:"cert_file" toml:"cert_file"` - - // KeyFile is the path of the node key file. This field is ignored when - // MutualTLS is false. - KeyFile string `mapstructure:"key_file" json:"key_file" yaml:"key_file" toml:"key_file"` - - // EnableMetrics determines whether health metrics in Prometheus format should - // be enabled. - EnableMetrics bool `mapstructure:"enable_metrics" json:"enable_metrics" yaml:"enable_metrics" toml:"enable_metrics"` - - // MaxSendQueueSize is the maximum size in bytes of each send queue. - // Once the maximum size is reached, further replication messages will be - // dropped to restrict memory usage. When set to 0, it means the send queue - // size is unlimited. - MaxSendQueueSize uint64 `mapstructure:"max_send_queue_size" json:"max_send_queue_size" yaml:"max_send_queue_size" toml:"max_send_queue_size"` - - // MaxReceiveQueueSize is the maximum size in bytes of each receive queue. - // Once the maximum size is reached, further replication messages will be - // dropped to restrict memory usage. When set to 0, it means the queue size - // is unlimited. - MaxReceiveQueueSize uint64 `mapstructure:"max_receive_queue_size" json:"max_receive_queue_size" yaml:"max_receive_queue_size" toml:"max_receive_queue_size"` - - // MaxSnapshotSendBytesPerSecond defines how much snapshot data can be sent - // every second for all Raft clusters managed by the NodeHost instance. - // The default value 0 means there is no limit set for snapshot streaming. - MaxSnapshotSendBytesPerSecond uint64 `mapstructure:"max_snapshot_send_bytes_per_second" json:"max_snapshot_send_bytes_per_second" yaml:"max_snapshot_send_bytes_per_second" toml:"max_snapshot_send_bytes_per_second"` - - // MaxSnapshotRecvBytesPerSecond defines how much snapshot data can be - // received each second for all Raft clusters managed by the NodeHost instance. - // The default value 0 means there is no limit for receiving snapshot data. - MaxSnapshotRecvBytesPerSecond uint64 `mapstructure:"max_snapshot_recv_bytes_per_second" json:"max_snapshot_recv_bytes_per_second" yaml:"max_snapshot_recv_bytes_per_second" toml:"max_snapshot_recv_bytes_per_second"` - - // NotifyCommit specifies whether clients should be notified when their - // regular proposals and config change requests are committed. By default, - // commits are not notified, clients are only notified when their proposals - // are both committed and applied. - NotifyCommit bool `mapstructure:"notify_commit" json:"notify_commit" yaml:"notify_commit" toml:"notify_commit"` - - // Gossip contains configurations for the gossip service. When the - // AddressByNodeHostID field is set to true, each NodeHost instance will use - // an internal gossip service to exchange knowledges of known NodeHost - // instances including their RaftAddress and NodeHostID values. This Gossip - // field contains configurations that controls how the gossip service works. - // - // As an detailed example on how to use the gossip service in the situation - // where all available machines have dynamically assigned IPs on reboot - - // - // Consider that there are three NodeHost instances on three machines, each - // of them has a dynamically assigned IP address which will change on reboot. - // NodeHostConfig.RaftAddress should be set to the current address that can be - // reached by remote NodeHost instance. In this example, we will assume they - // are - // - // 10.0.0.100:24000 - // 10.0.0.200:24000 - // 10.0.0.300:24000 - // - // To use these machines, first enable the NodeHostConfig.AddressByNodeHostID - // field and start the NodeHost instances. The NodeHostID value of each - // NodeHost instance can be obtained by calling NodeHost.ID(). Let's say they - // are - // - // "nhid-xxxxx", - // "nhid-yyyyy", - // "nhid-zzzzz". - // - // All these NodeHostID are fixed, they will never change after reboots. - // - // When starting Raft nodes or requesting new nodes to be added, use the above - // mentioned NodeHostID values as the target parameters (which are of the - // Target type). Let's say we want to start a Raft Node as a part of a three - // replicas Raft cluster, the initialMembers parameter of the StartCluster - // method can be set to - // - // initialMembers := map[uint64]Target { - // 1: "nhid-xxxxx", - // 2: "nhid-yyyyy", - // 3: "nhid-zzzzz", - // } - // - // This indicates that node 1 of the cluster will be running on the NodeHost - // instance identified by the NodeHostID value "nhid-xxxxx", node 2 of the - // same cluster will be running on the NodeHost instance identified by the - // NodeHostID value of "nhid-yyyyy" and so on. - // - // The internal gossip service exchanges NodeHost details, including their - // NodeHostID and RaftAddress values, with all other known NodeHost instances. - // Thanks to the nature of gossip, it will eventually allow each NodeHost - // instance to be aware of the current details of all NodeHost instances. - // As a result, let's say when Raft node 1 wants to send a Raft message to - // node 2, it first figures out that node 2 is running on the NodeHost - // identified by the NodeHostID value "nhid-yyyyy", RaftAddress information - // from the gossip service further shows that "nhid-yyyyy" maps to a machine - // currently reachable at 10.0.0.200:24000. Raft messages can thus be - // delivered. - // - // The Gossip field here is used to configure how the gossip service works. - // In this example, let's say we choose to use the following configurations - // for those three NodeHost instaces. - // - // GossipConfig { - // BindAddress: "10.0.0.100:24001", - // Seed: []string{10.0.0.200:24001}, - // } - // - // GossipConfig { - // BindAddress: "10.0.0.200:24001", - // Seed: []string{10.0.0.300:24001}, - // } - // - // GossipConfig { - // BindAddress: "10.0.0.300:24001", - // Seed: []string{10.0.0.100:24001}, - // } - // - // For those three machines, the gossip component listens on - // "10.0.0.100:24001", "10.0.0.200:24001" and "10.0.0.300:24001" respectively - // for incoming gossip messages. The Seed field is a list of known gossip end - // points the local gossip service will try to talk to. The Seed field doesn't - // need to include all gossip end points, a few well connected nodes in the - // gossip network is enough. - Gossip ConfigGossip `mapstructure:"gossip" json:"gossip" yaml:"gossip" toml:"gossip" validate:"omitempty"` - - // Expert contains options for expert users who are familiar with the internals - // of Dragonboat. Users are recommended not to use this field unless - // absoloutely necessary. It is important to note that any change to this field - // may cause an existing instance unable to restart, it may also cause negative - // performance impacts. - Expert ConfigExpert `mapstructure:"expert" json:"expert" yaml:"expert" toml:"expert" validate:"omitempty"` -} - -func (c ConfigNode) GetDGBConfigNodeHost() dgbcfg.NodeHostConfig { - d := dgbcfg.NodeHostConfig{ - DeploymentID: c.DeploymentID, - WALDir: c.WALDir, - NodeHostDir: c.NodeHostDir, - RaftAddress: c.RaftAddress, - ListenAddress: c.ListenAddress, - Gossip: c.Gossip.GetDGBConfigGossip(), - Expert: c.Expert.GetDGBConfigExpert(), - } - - if c.RTTMillisecond > 0 { - d.RTTMillisecond = c.RTTMillisecond - } - - if c.AddressByNodeHostID { - d.AddressByNodeHostID = true - } - - if c.MutualTLS && c.CAFile != "" && c.CertFile != "" && c.KeyFile != "" { - d.MutualTLS = true - d.CAFile = c.CAFile - d.CertFile = c.CertFile - d.KeyFile = c.KeyFile - } - - if c.EnableMetrics { - d.EnableMetrics = true - } - - if c.MaxSendQueueSize > 0 { - d.MaxSendQueueSize = c.MaxSendQueueSize - } - - if c.MaxReceiveQueueSize > 0 { - d.MaxReceiveQueueSize = c.MaxReceiveQueueSize - } - - if c.MaxSnapshotSendBytesPerSecond > 0 { - d.MaxSnapshotSendBytesPerSecond = c.MaxSnapshotSendBytesPerSecond - } - - if c.MaxSnapshotRecvBytesPerSecond > 0 { - d.MaxSnapshotRecvBytesPerSecond = c.MaxSnapshotRecvBytesPerSecond - } - - if c.NotifyCommit { - d.NotifyCommit = true - } - - return d -} - -func (c ConfigNode) Validate() liberr.Error { - err := ErrorValidateConfig.Error(nil) - - if er := libval.New().Struct(c); er != nil { - if e, ok := er.(*libval.InvalidValidationError); ok { - err.Add(e) - } - - for _, e := range er.(libval.ValidationErrors) { - //nolint goerr113 - err.Add(fmt.Errorf("config field '%s' is not validated by constraint '%s'", e.Namespace(), e.ActualTag())) - } - } - - if err.HasParent() { - return err - } - - return nil -} diff --git a/cluster/errors.go b/cluster/errors.go deleted file mode 100644 index 85ed5da..0000000 --- a/cluster/errors.go +++ /dev/null @@ -1,114 +0,0 @@ -//go:build amd64 || arm64 || arm64be || ppc64 || ppc64le || mips64 || mips64le || riscv64 || s390x || sparc64 || wasm -// +build amd64 arm64 arm64be ppc64 ppc64le mips64 mips64le riscv64 s390x sparc64 wasm - -/*********************************************************************************************************************** - * - * MIT License - * - * Copyright (c) 2021 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * - **********************************************************************************************************************/ - -package cluster - -import liberr "github.com/nabbar/golib/errors" - -const ( - ErrorParamsEmpty liberr.CodeError = iota + liberr.MinPkgCluster - ErrorParamsMissing - ErrorParamsMismatching - ErrorLeader - ErrorLeaderTransfer - ErrorNodeUser - ErrorNodeHostNew - ErrorNodeHostStart - ErrorNodeHostJoin - ErrorNodeHostStop - ErrorNodeHostRestart - ErrorCommandSync - ErrorCommandASync - ErrorCommandLocal - ErrorValidateConfig - ErrorValidateCluster - ErrorValidateNode - ErrorValidateGossip - ErrorValidateExpert - ErrorValidateEngine -) - -var isCodeError = false - -func IsCodeError() bool { - return isCodeError -} - -func init() { - isCodeError = liberr.ExistInMapMessage(ErrorParamsEmpty) - liberr.RegisterIdFctMessage(ErrorParamsEmpty, getMessage) -} - -func getMessage(code liberr.CodeError) (message string) { - switch code { - case ErrorParamsEmpty: - return "at least one given parameter is empty" - case ErrorParamsMissing: - return "at least one given parameter is missing" - case ErrorParamsMismatching: - return "at least one given parameter does not match the awaiting type" - case ErrorLeader: - return "unable to retrieve cluster leader" - case ErrorLeaderTransfer: - return "unable to transfer cluster leader" - case ErrorNodeUser: - return "unable to retrieve cluster node user" - case ErrorNodeHostNew: - return "unable to init new cluster NodeHost" - case ErrorNodeHostStart: - return "unable to start cluster" - case ErrorNodeHostJoin: - return "unable to join cluster" - case ErrorNodeHostStop: - return "unable to stop cluster or node" - case ErrorNodeHostRestart: - return "unable to restart cluster node properly" - case ErrorCommandSync: - return "unable to call cluster synchronous command" - case ErrorCommandASync: - return "unable to call cluster asynchronous command" - case ErrorCommandLocal: - return "unable to call cluster local command" - case ErrorValidateConfig: - return "cluster main config seems to be invalid" - case ErrorValidateCluster: - return "cluster config seems to be invalid" - case ErrorValidateNode: - return "cluster node config seems to be invalid" - case ErrorValidateGossip: - return "cluster gossip config seems to be invalid" - case ErrorValidateExpert: - return "cluster expert config seems to be invalid" - case ErrorValidateEngine: - return "cluster engine config seems to be invalid" - } - - return liberr.NullMessage -} diff --git a/cluster/interface.go b/cluster/interface.go deleted file mode 100644 index 83a960a..0000000 --- a/cluster/interface.go +++ /dev/null @@ -1,127 +0,0 @@ -//go:build amd64 || arm64 || arm64be || ppc64 || ppc64le || mips64 || mips64le || riscv64 || s390x || sparc64 || wasm -// +build amd64 arm64 arm64be ppc64 ppc64le mips64 mips64le riscv64 s390x sparc64 wasm - -/*********************************************************************************************************************** - * - * MIT License - * - * Copyright (c) 2021 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * - **********************************************************************************************************************/ - -package cluster - -import ( - "context" - "io" - "time" - - dgbclt "github.com/lni/dragonboat/v3" - dgbcli "github.com/lni/dragonboat/v3/client" - dgbcfg "github.com/lni/dragonboat/v3/config" - dgbstm "github.com/lni/dragonboat/v3/statemachine" - liberr "github.com/nabbar/golib/errors" -) - -const ( - _DefaultTimeoutCommandSync = 10 * time.Second - _DefaultTimeoutCommandAsync = 100 * time.Second -) - -type Cluster interface { - GetConfig() dgbcfg.Config - SetConfig(cfg dgbcfg.Config) - GetNodeHostConfig() dgbcfg.NodeHostConfig - - GetFctCreate() dgbstm.CreateStateMachineFunc - GetFctCreateConcurrent() dgbstm.CreateConcurrentStateMachineFunc - GetFctCreateOnDisk() dgbstm.CreateOnDiskStateMachineFunc - SetFctCreate(fctCreate interface{}) - SetFctCreateSTM(fctCreate dgbstm.CreateStateMachineFunc) - SetFctCreateSTMConcurrent(fctCreate dgbstm.CreateConcurrentStateMachineFunc) - SetFctCreateSTMOnDisk(fctCreate dgbstm.CreateOnDiskStateMachineFunc) - - GetMemberInit() map[uint64]dgbclt.Target - SetMemberInit(memberList map[uint64]dgbclt.Target) - - SetTimeoutCommandSync(timeout time.Duration) - SetTimeoutCommandASync(timeout time.Duration) - - HasNodeInfo(nodeId uint64) bool - RaftAddress() string - ID() string - - ClusterStart(join bool) liberr.Error - ClusterStop(force bool) liberr.Error - ClusterRestart(force bool) liberr.Error - - NodeStop(target uint64) liberr.Error - NodeRestart(force bool) liberr.Error - - GetLeaderID() (leader uint64, valid bool, err liberr.Error) - GetNoOPSession() *dgbcli.Session - GetNodeHostInfo(opt dgbclt.NodeHostInfoOption) *dgbclt.NodeHostInfo - RequestLeaderTransfer(targetNodeID uint64) liberr.Error - - HandlerMetrics(w io.Writer) - - StaleReadDangerous(query interface{}) (interface{}, error) - - SyncPropose(parent context.Context, session *dgbcli.Session, cmd []byte) (dgbstm.Result, liberr.Error) - SyncRead(parent context.Context, query interface{}) (interface{}, liberr.Error) - SyncGetClusterMembership(parent context.Context) (*dgbclt.Membership, liberr.Error) - SyncGetSession(parent context.Context) (*dgbcli.Session, liberr.Error) - SyncCloseSession(parent context.Context, cs *dgbcli.Session) liberr.Error - SyncRequestSnapshot(parent context.Context, opt dgbclt.SnapshotOption) (uint64, liberr.Error) - SyncRequestDeleteNode(parent context.Context, nodeID uint64, configChangeIndex uint64) liberr.Error - SyncRequestAddNode(parent context.Context, nodeID uint64, target string, configChangeIndex uint64) liberr.Error - SyncRequestAddObserver(parent context.Context, nodeID uint64, target string, configChangeIndex uint64) liberr.Error - SyncRequestAddWitness(parent context.Context, nodeID uint64, target string, configChangeIndex uint64) liberr.Error - SyncRemoveData(parent context.Context, nodeID uint64) liberr.Error - - AsyncPropose(session *dgbcli.Session, cmd []byte) (*dgbclt.RequestState, liberr.Error) - AsyncProposeSession(session *dgbcli.Session) (*dgbclt.RequestState, liberr.Error) - AsyncReadIndex() (*dgbclt.RequestState, liberr.Error) - AsyncRequestCompaction(nodeID uint64) (*dgbclt.SysOpState, liberr.Error) - - LocalReadNode(rs *dgbclt.RequestState, query interface{}) (interface{}, liberr.Error) - LocalNAReadNode(rs *dgbclt.RequestState, query []byte) ([]byte, liberr.Error) -} - -func NewCluster(cfg Config, fctCreate interface{}) (Cluster, liberr.Error) { - c := &cRaft{ - memberInit: cfg.GetInitMember(), - fctCreate: fctCreate, - config: cfg.GetDGBConfigCluster(), - nodeHost: nil, - timeoutCmdSync: _DefaultTimeoutCommandSync, - timeoutCmdASync: _DefaultTimeoutCommandAsync, - } - - if n, e := dgbclt.NewNodeHost(cfg.GetDGBConfigNode()); e != nil { - return nil, ErrorNodeHostNew.Error(e) - } else { - c.nodeHost = n - } - - return c, nil -} diff --git a/cluster/local.go b/cluster/local.go deleted file mode 100644 index e81d3bd..0000000 --- a/cluster/local.go +++ /dev/null @@ -1,56 +0,0 @@ -//go:build amd64 || arm64 || arm64be || ppc64 || ppc64le || mips64 || mips64le || riscv64 || s390x || sparc64 || wasm -// +build amd64 arm64 arm64be ppc64 ppc64le mips64 mips64le riscv64 s390x sparc64 wasm - -/*********************************************************************************************************************** - * - * MIT License - * - * Copyright (c) 2021 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * - **********************************************************************************************************************/ - -package cluster - -import ( - dgbclt "github.com/lni/dragonboat/v3" - liberr "github.com/nabbar/golib/errors" -) - -func (c *cRaft) LocalReadNode(rs *dgbclt.RequestState, query interface{}) (interface{}, liberr.Error) { - i, e := c.nodeHost.ReadLocalNode(rs, query) - - if e != nil { - return i, ErrorCommandLocal.Error(c.getErrorCommand("ReadNode"), e) - } - - return i, nil -} - -func (c *cRaft) LocalNAReadNode(rs *dgbclt.RequestState, query []byte) ([]byte, liberr.Error) { - r, e := c.nodeHost.NAReadLocalNode(rs, query) - - if e != nil { - return r, ErrorCommandLocal.Error(c.getErrorCommand("ReadNode"), e) - } - - return r, nil -} diff --git a/cluster/logger.go b/cluster/logger.go deleted file mode 100644 index 1d7b100..0000000 --- a/cluster/logger.go +++ /dev/null @@ -1,110 +0,0 @@ -//go:build amd64 || arm64 || arm64be || ppc64 || ppc64le || mips64 || mips64le || riscv64 || s390x || sparc64 || wasm -// +build amd64 arm64 arm64be ppc64 ppc64le mips64 mips64le riscv64 s390x sparc64 wasm - -/*********************************************************************************************************************** - * - * MIT License - * - * Copyright (c) 2021 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * - **********************************************************************************************************************/ - -package cluster - -import ( - "context" - - dgblog "github.com/lni/dragonboat/v3/logger" - liblog "github.com/nabbar/golib/logger" - loglvl "github.com/nabbar/golib/logger/level" -) - -const LogLib = "DragonBoat" - -func SetLoggerFactory(log liblog.FuncLog) { - if log == nil { - log = func() liblog.Logger { - return liblog.New(context.Background) - } - } - - dgblog.SetLoggerFactory(func(pkgName string) dgblog.ILogger { - return &logDragonBoat{ - pkg: pkgName, - log: log, - } - }) -} - -type logDragonBoat struct { - pkg string - log liblog.FuncLog -} - -func (l *logDragonBoat) SetLevel(level dgblog.LogLevel) { - if l.log == nil { - return - } - - switch level { - case dgblog.CRITICAL: - l.log().SetLevel(loglvl.FatalLevel) - case dgblog.ERROR: - l.log().SetLevel(loglvl.ErrorLevel) - case dgblog.WARNING: - l.log().SetLevel(loglvl.WarnLevel) - case dgblog.INFO: - l.log().SetLevel(loglvl.InfoLevel) - case dgblog.DEBUG: - l.log().SetLevel(loglvl.DebugLevel) - } -} - -func (l *logDragonBoat) logMsg(lvl loglvl.Level, message string, args ...interface{}) { - if l.log == nil { - l.log = func() liblog.Logger { - return liblog.New(context.Background) - } - } - - l.log().Entry(lvl, message, args...).FieldAdd("lib", LogLib).FieldAdd("pkg", l.pkg).Log() -} - -func (l *logDragonBoat) Debugf(format string, args ...interface{}) { - l.logMsg(loglvl.DebugLevel, format, args...) -} - -func (l *logDragonBoat) Infof(format string, args ...interface{}) { - l.logMsg(loglvl.InfoLevel, format, args...) -} - -func (l *logDragonBoat) Warningf(format string, args ...interface{}) { - l.logMsg(loglvl.WarnLevel, format, args...) -} - -func (l *logDragonBoat) Errorf(format string, args ...interface{}) { - l.logMsg(loglvl.ErrorLevel, format, args...) -} - -func (l *logDragonBoat) Panicf(format string, args ...interface{}) { - l.logMsg(loglvl.FatalLevel, format, args...) -} diff --git a/cluster/sync.go b/cluster/sync.go deleted file mode 100644 index dcf7f16..0000000 --- a/cluster/sync.go +++ /dev/null @@ -1,248 +0,0 @@ -//go:build amd64 || arm64 || arm64be || ppc64 || ppc64le || mips64 || mips64le || riscv64 || s390x || sparc64 || wasm -// +build amd64 arm64 arm64be ppc64 ppc64le mips64 mips64le riscv64 s390x sparc64 wasm - -/*********************************************************************************************************************** - * - * MIT License - * - * Copyright (c) 2021 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * - **********************************************************************************************************************/ - -package cluster - -import ( - "context" - "time" - - dgbclt "github.com/lni/dragonboat/v3" - dgbcli "github.com/lni/dragonboat/v3/client" - dgbstm "github.com/lni/dragonboat/v3/statemachine" - liberr "github.com/nabbar/golib/errors" -) - -func (c *cRaft) syncCtxTimeout(parent context.Context) (context.Context, context.CancelFunc) { - var ( - ctx context.Context - cnl context.CancelFunc - ) - - if parent != nil { - ctx, cnl = context.WithDeadline(parent, time.Now().Add(c.timeoutCmdSync)) - } else { - ctx, cnl = context.WithDeadline(context.Background(), time.Now().Add(c.timeoutCmdSync)) - } - - return ctx, cnl -} - -func (c *cRaft) syncCtxCancel(cancel context.CancelFunc) { - if cancel != nil { - cancel() - } -} - -func (c *cRaft) SyncPropose(parent context.Context, session *dgbcli.Session, cmd []byte) (dgbstm.Result, liberr.Error) { - ctx, cnl := c.syncCtxTimeout(parent) - defer c.syncCtxCancel(cnl) - - r, e := c.nodeHost.SyncPropose(ctx, session, cmd) - - if e != nil { - return r, ErrorCommandSync.Error(c.getErrorCommand("Propose"), e) - } - - return r, nil -} - -func (c *cRaft) SyncRead(parent context.Context, query interface{}) (interface{}, liberr.Error) { - ctx, cnl := c.syncCtxTimeout(parent) - defer c.syncCtxCancel(cnl) - - r, e := c.nodeHost.SyncRead(ctx, c.config.ClusterID, query) - - if e != nil { - return r, ErrorCommandSync.Error(c.getErrorCluster(), c.getErrorCommand("Read"), e) - } - - return r, nil -} - -func (c *cRaft) SyncGetClusterMembership(parent context.Context) (*dgbclt.Membership, liberr.Error) { - ctx, cnl := c.syncCtxTimeout(parent) - defer c.syncCtxCancel(cnl) - - r, e := c.nodeHost.SyncGetClusterMembership(ctx, c.config.ClusterID) - - if e != nil { - return r, ErrorCommandSync.Error(c.getErrorCluster(), c.getErrorCommand("GetClusterMembership"), e) - } - - return r, nil -} - -func (c *cRaft) SyncGetSession(parent context.Context) (*dgbcli.Session, liberr.Error) { - ctx, cnl := c.syncCtxTimeout(parent) - defer c.syncCtxCancel(cnl) - - r, e := c.nodeHost.SyncGetSession(ctx, c.config.ClusterID) - - if e != nil { - return r, ErrorCommandSync.Error(c.getErrorCluster(), c.getErrorCommand("GetSession"), e) - } - - return r, nil -} - -func (c *cRaft) SyncCloseSession(parent context.Context, cs *dgbcli.Session) liberr.Error { - ctx, cnl := c.syncCtxTimeout(parent) - defer c.syncCtxCancel(cnl) - - e := c.nodeHost.SyncCloseSession(ctx, cs) - - if e != nil { - return ErrorCommandSync.Error(c.getErrorCommand("CloseSession"), e) - } - - return nil -} - -func (c *cRaft) SyncRequestSnapshot(parent context.Context, opt dgbclt.SnapshotOption) (uint64, liberr.Error) { - ctx, cnl := c.syncCtxTimeout(parent) - defer c.syncCtxCancel(cnl) - - r, e := c.nodeHost.SyncRequestSnapshot(ctx, c.config.ClusterID, opt) - - if e != nil { - return r, ErrorCommandSync.Error(c.getErrorCluster(), c.getErrorCommand("RequestSnapshot"), e) - } - - return r, nil -} - -func (c *cRaft) SyncRequestDeleteNode(parent context.Context, nodeID uint64, configChangeIndex uint64) liberr.Error { - ctx, cnl := c.syncCtxTimeout(parent) - defer c.syncCtxCancel(cnl) - - var en error - if nodeID == 0 { - nodeID = c.config.NodeID - en = c.getErrorNode() - } else { - en = c.getErrorNodeTarget(nodeID) - } - - e := c.nodeHost.SyncRequestDeleteNode(ctx, c.config.ClusterID, nodeID, configChangeIndex) - - if e != nil { - return ErrorCommandSync.Error(c.getErrorCluster(), en, c.getErrorCommand("RequestDeleteNode"), e) - } - - return nil -} - -// nolint #dupl -func (c *cRaft) SyncRequestAddNode(parent context.Context, nodeID uint64, target string, configChangeIndex uint64) liberr.Error { - ctx, cnl := c.syncCtxTimeout(parent) - defer c.syncCtxCancel(cnl) - - var en error - if nodeID == 0 { - nodeID = c.config.NodeID - en = c.getErrorNode() - } else { - en = c.getErrorNodeTarget(nodeID) - } - - e := c.nodeHost.SyncRequestAddNode(ctx, c.config.ClusterID, nodeID, target, configChangeIndex) - - if e != nil { - return ErrorCommandSync.Error(c.getErrorCluster(), en, c.getErrorCommand("RequestAddNode"), e) - } - - return nil -} - -// nolint #dupl -func (c *cRaft) SyncRequestAddObserver(parent context.Context, nodeID uint64, target string, configChangeIndex uint64) liberr.Error { - ctx, cnl := c.syncCtxTimeout(parent) - defer c.syncCtxCancel(cnl) - - var en error - if nodeID == 0 { - nodeID = c.config.NodeID - en = c.getErrorNode() - } else { - en = c.getErrorNodeTarget(nodeID) - } - - e := c.nodeHost.SyncRequestAddObserver(ctx, c.config.ClusterID, nodeID, target, configChangeIndex) - - if e != nil { - return ErrorCommandSync.Error(c.getErrorCluster(), en, c.getErrorCommand("RequestAddObserver"), e) - } - - return nil -} - -// nolint #dupl -func (c *cRaft) SyncRequestAddWitness(parent context.Context, nodeID uint64, target string, configChangeIndex uint64) liberr.Error { - ctx, cnl := c.syncCtxTimeout(parent) - defer c.syncCtxCancel(cnl) - - var en error - if nodeID == 0 { - nodeID = c.config.NodeID - en = c.getErrorNode() - } else { - en = c.getErrorNodeTarget(nodeID) - } - - e := c.nodeHost.SyncRequestAddWitness(ctx, c.config.ClusterID, nodeID, target, configChangeIndex) - - if e != nil { - return ErrorCommandSync.Error(c.getErrorCluster(), en, c.getErrorCommand("RequestAddWitness"), e) - } - - return nil -} - -func (c *cRaft) SyncRemoveData(parent context.Context, nodeID uint64) liberr.Error { - ctx, cnl := c.syncCtxTimeout(parent) - defer c.syncCtxCancel(cnl) - - var en error - if nodeID == 0 { - nodeID = c.config.NodeID - en = c.getErrorNode() - } else { - en = c.getErrorNodeTarget(nodeID) - } - - e := c.nodeHost.SyncRemoveData(ctx, c.config.ClusterID, nodeID) - - if e != nil { - return ErrorCommandSync.Error(c.getErrorCluster(), en, c.getErrorCommand("RemoveData"), e) - } - - return nil -} diff --git a/config/components.go b/config/components.go index f8f4f79..004356d 100644 --- a/config/components.go +++ b/config/components.go @@ -31,12 +31,12 @@ import ( "encoding/json" "fmt" "io" + "slices" cfgcst "github.com/nabbar/golib/config/const" cfgtps "github.com/nabbar/golib/config/types" loglvl "github.com/nabbar/golib/logger/level" spfcbr "github.com/spf13/cobra" - "golang.org/x/exp/slices" ) func (c *configModel) ComponentHas(key string) bool { diff --git a/context/config.go b/context/config.go index 1bcf32d..0f165fb 100644 --- a/context/config.go +++ b/context/config.go @@ -26,10 +26,9 @@ package context import ( "context" + "slices" "sync" "time" - - "golang.org/x/exp/slices" ) type FuncContext func() context.Context diff --git a/go.mod b/go.mod index 4455889..94b4702 100644 --- a/go.mod +++ b/go.mod @@ -1,15 +1,17 @@ module github.com/nabbar/golib -go 1.22.6 +go 1.23 + +toolchain go1.23.2 require ( github.com/aws/aws-sdk-go v1.55.5 - github.com/aws/aws-sdk-go-v2 v1.31.0 - github.com/aws/aws-sdk-go-v2/config v1.27.39 - github.com/aws/aws-sdk-go-v2/credentials v1.17.37 - github.com/aws/aws-sdk-go-v2/service/iam v1.36.3 - github.com/aws/aws-sdk-go-v2/service/s3 v1.63.3 - github.com/aws/smithy-go v1.21.0 + github.com/aws/aws-sdk-go-v2 v1.32.0 + github.com/aws/aws-sdk-go-v2/config v1.27.41 + github.com/aws/aws-sdk-go-v2/credentials v1.17.39 + github.com/aws/aws-sdk-go-v2/service/iam v1.37.0 + github.com/aws/aws-sdk-go-v2/service/s3 v1.65.0 + github.com/aws/smithy-go v1.22.0 github.com/bits-and-blooms/bitset v1.14.3 github.com/c-bata/go-prompt v0.2.6 github.com/dsnet/compress v0.0.1 @@ -25,7 +27,6 @@ require ( github.com/hashicorp/go-uuid v1.0.3 github.com/hashicorp/go-version v1.7.0 github.com/jlaffaye/ftp v0.2.0 - github.com/lni/dragonboat/v3 v3.3.8 github.com/matcornic/hermes/v2 v2.1.0 github.com/mattn/go-colorable v0.1.13 github.com/mitchellh/go-homedir v1.1.0 @@ -33,7 +34,6 @@ require ( github.com/nats-io/jwt/v2 v2.7.0 github.com/nats-io/nats-server/v2 v2.10.21 github.com/nats-io/nats.go v1.37.0 - github.com/nutsdb/nutsdb v1.0.4 github.com/onsi/ginkgo/v2 v2.20.2 github.com/onsi/gomega v1.34.2 github.com/pelletier/go-toml v1.9.5 @@ -47,15 +47,13 @@ require ( github.com/ugorji/go/codec v1.2.12 github.com/ulikunitz/xz v0.5.12 github.com/vbauerster/mpb/v8 v8.8.3 - github.com/xanzy/go-gitlab v0.109.0 + github.com/xanzy/go-gitlab v0.110.0 github.com/xhit/go-simple-mail v2.2.2+incompatible - github.com/xujiajun/utils v0.0.0-20220904132955-5f7c5b914235 - golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 - golang.org/x/net v0.29.0 + golang.org/x/net v0.30.0 golang.org/x/oauth2 v0.23.0 golang.org/x/sync v0.8.0 - golang.org/x/sys v0.25.0 - golang.org/x/term v0.24.0 + golang.org/x/sys v0.26.0 + golang.org/x/term v0.25.0 gopkg.in/yaml.v3 v3.0.1 gorm.io/driver/clickhouse v0.6.1 gorm.io/driver/mysql v1.5.7 @@ -70,103 +68,80 @@ require ( github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect github.com/ClickHouse/ch-go v0.62.0 // indirect github.com/ClickHouse/clickhouse-go/v2 v2.29.0 // indirect - github.com/Masterminds/semver v1.4.2 // indirect - github.com/Masterminds/sprig v2.16.0+incompatible // indirect - github.com/PuerkitoBio/goquery v1.5.0 // indirect - github.com/VictoriaMetrics/metrics v1.6.2 // indirect + github.com/Masterminds/goutils v1.1.1 // indirect + github.com/Masterminds/semver v1.5.0 // indirect + github.com/Masterminds/sprig v2.22.0+incompatible // indirect + github.com/PuerkitoBio/goquery v1.10.0 // indirect github.com/VividCortex/ewma v1.2.0 // indirect github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect github.com/andybalholm/brotli v1.1.0 // indirect - github.com/andybalholm/cascadia v1.0.0 // indirect - github.com/antlabs/stl v0.0.2 // indirect - github.com/antlabs/timer v0.1.4 // indirect - github.com/aokoli/goutils v1.0.1 // indirect - github.com/armon/go-metrics v0.4.1 // indirect - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.5 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.14 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.18 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.18 // indirect + github.com/andybalholm/cascadia v1.3.2 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.6 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.15 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.19 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.19 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.18 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.5 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.20 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.20 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.18 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.23.3 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.27.3 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.31.3 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.19 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.0 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.0 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.0 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.24.0 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.0 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.32.0 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/bwmarrin/snowflake v0.3.0 // indirect github.com/bytedance/sonic v1.12.3 // indirect github.com/bytedance/sonic/loader v0.2.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cloudwego/base64x v0.1.4 // indirect github.com/cloudwego/iasm v0.2.0 // indirect - github.com/cockroachdb/errors v1.7.5 // indirect - github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f // indirect - github.com/cockroachdb/pebble v0.0.0-20210331181633-27fc006b8bfb // indirect - github.com/cockroachdb/redact v1.0.6 // indirect - github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2 // indirect github.com/gabriel-vasile/mimetype v1.4.5 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/go-asn1-ber/asn1-ber v1.5.7 // indirect github.com/go-faster/city v1.0.1 // indirect github.com/go-faster/errors v0.7.1 // indirect github.com/go-logr/logr v1.4.2 // indirect - github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-sql-driver/mysql v1.8.1 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/goccy/go-json v0.10.3 // indirect - github.com/gofrs/flock v0.12.1 // indirect - github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect github.com/golang-sql/sqlexp v0.1.0 // indirect - github.com/golang/protobuf v1.5.3 // indirect - github.com/golang/snappy v0.0.4 // indirect - github.com/google/btree v1.0.1 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/pprof v0.0.0-20241001023024-f4c0cfd0cf1d // indirect github.com/google/uuid v1.6.0 // indirect - github.com/gorilla/css v1.0.0 // indirect + github.com/gorilla/css v1.0.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-immutable-radix v1.3.1 // indirect - github.com/hashicorp/go-msgpack v0.5.3 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-sockaddr v1.0.0 // indirect - github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/hashicorp/memberlist v0.2.2 // indirect - github.com/huandu/xstrings v1.2.0 // indirect - github.com/imdario/mergo v0.3.12 // indirect + github.com/huandu/xstrings v1.5.0 // indirect + github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/jackc/pgx/v5 v5.7.1 // indirect github.com/jackc/puddle/v2 v2.2.2 // indirect - github.com/jaytaylor/html2text v0.0.0-20180606194806-57d518f124b0 // indirect + github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/juju/ratelimit v1.0.2-0.20191002062651-f60b32039441 // indirect github.com/klauspost/compress v1.17.10 // indirect github.com/klauspost/cpuid/v2 v2.2.8 // indirect - github.com/kr/pretty v0.3.1 // indirect - github.com/kr/text v0.2.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect - github.com/lni/goutils v1.3.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect - github.com/mattn/go-sqlite3 v1.14.23 // indirect + github.com/mattn/go-sqlite3 v1.14.24 // indirect github.com/mattn/go-tty v0.0.7 // indirect github.com/microsoft/go-mssqldb v1.7.2 // indirect - github.com/miekg/dns v1.1.43 // indirect github.com/minio/highwayhash v1.0.3 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect @@ -178,14 +153,12 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/pkg/term v1.2.0-beta.2 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rivo/uniseg v0.4.7 // indirect - github.com/rogpeppe/go-internal v1.10.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.6.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect - github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect github.com/segmentio/asm v1.2.0 // indirect github.com/shopspring/decimal v1.4.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect @@ -194,23 +167,20 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect github.com/subosito/gotenv v1.6.0 // indirect - github.com/tidwall/btree v1.7.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect - github.com/valyala/fastrand v1.0.0 // indirect - github.com/valyala/histogram v1.0.1 // indirect - github.com/vanng822/css v0.0.0-20190504095207-a21e860bcd04 // indirect - github.com/vanng822/go-premailer v0.0.0-20191214114701-be27abe028fe // indirect + github.com/vanng822/css v1.0.1 // indirect + github.com/vanng822/go-premailer v1.21.0 // indirect github.com/x448/float16 v0.8.4 // indirect - github.com/xujiajun/mmap-go v1.0.1 // indirect - github.com/yusufpapurcu/wmi v1.2.3 // indirect + github.com/yusufpapurcu/wmi v1.2.4 // indirect go.opentelemetry.io/otel v1.30.0 // indirect go.opentelemetry.io/otel/trace v1.30.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/arch v0.10.0 // indirect - golang.org/x/crypto v0.27.0 // indirect - golang.org/x/text v0.18.0 // indirect - golang.org/x/time v0.6.0 // indirect - golang.org/x/tools v0.25.0 // indirect + golang.org/x/arch v0.11.0 // indirect + golang.org/x/crypto v0.28.0 // indirect + golang.org/x/exp v0.0.0-20241004190924-225e2abe05e6 // indirect + golang.org/x/text v0.19.0 // indirect + golang.org/x/time v0.7.0 // indirect + golang.org/x/tools v0.26.0 // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect ) diff --git a/mail/email.go b/mail/email.go index 6387610..0e8e3ee 100644 --- a/mail/email.go +++ b/mail/email.go @@ -25,7 +25,7 @@ package mail -import "golang.org/x/exp/slices" +import "slices" const ( headerFrom = "From" diff --git a/monitor/metrics.go b/monitor/metrics.go index 35d8216..e6de20a 100644 --- a/monitor/metrics.go +++ b/monitor/metrics.go @@ -28,11 +28,11 @@ package monitor import ( "context" + "slices" "time" monsts "github.com/nabbar/golib/monitor/status" libprm "github.com/nabbar/golib/prometheus" - "golang.org/x/exp/slices" ) func (o *mon) RegisterMetricsName(names ...string) { diff --git a/nutsdb/Command.go b/nutsdb/Command.go deleted file mode 100644 index fa960ea..0000000 --- a/nutsdb/Command.go +++ /dev/null @@ -1,225 +0,0 @@ -//go:build !386 && !arm && !mips && !mipsle -// +build !386,!arm,!mips,!mipsle - -/*********************************************************************************************************************** - * - * MIT License - * - * Copyright (c) 2021 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * - **********************************************************************************************************************/ - -package nutsdb - -import ( - "github.com/nutsdb/nutsdb" -) - -type Commands interface { - CommandTransaction - CommandBPTree - CommandSet - CommandList - CommandZSet -} - -type CommandTransaction interface { - // Put sets the value for a key in the bucket. - Put(bucket string, key, value []byte, ttl uint32) error - - // PutWithTimestamp sets the value for a key in the bucket but allow capabilities to custom the timestamp for ttl. - PutWithTimestamp(bucket string, key, value []byte, ttl uint32, timestamp uint64) error -} - -type CommandBPTree interface { - // Get retrieves the value for a key in the bucket. - // The returned value is only valid for the life of the transaction. - Get(bucket string, key []byte) (e *nutsdb.Entry, err error) - - //GetAll returns all keys and values of the bucket stored at given bucket. - GetAll(bucket string) (entries nutsdb.Entries, err error) - - // RangeScan query a range at given bucket, start and end slice. - RangeScan(bucket string, start, end []byte) (es nutsdb.Entries, err error) - - // PrefixScan iterates over a key prefix at given bucket, prefix and limitNum. - // LimitNum will limit the number of entries return. - PrefixScan(bucket string, prefix []byte, offsetNum int, limitNum int) (es nutsdb.Entries, off int, err error) - - // PrefixSearchScan iterates over a key prefix at given bucket, prefix, match regular expression and limitNum. - // LimitNum will limit the number of entries return. - PrefixSearchScan(bucket string, prefix []byte, reg string, offsetNum int, limitNum int) (es nutsdb.Entries, off int, err error) - - // Delete removes a key from the bucket at given bucket and key. - Delete(bucket string, key []byte) error -} - -type CommandSet interface { - // SAdd adds the specified members to the set stored int the bucket at given bucket,key and items. - SAdd(bucket string, key []byte, items ...[]byte) error - - // SRem removes the specified members from the set stored int the bucket at given bucket,key and items. - SRem(bucket string, key []byte, items ...[]byte) error - - // SAreMembers returns if the specified members are the member of the set int the bucket at given bucket,key and items. - SAreMembers(bucket string, key []byte, items ...[]byte) (bool, error) - - // SIsMember returns if member is a member of the set stored int the bucket at given bucket,key and item. - SIsMember(bucket string, key, item []byte) (bool, error) - - // SMembers returns all the members of the set value stored int the bucket at given bucket and key. - SMembers(bucket string, key []byte) (list [][]byte, err error) - - // SHasKey returns if the set in the bucket at given bucket and key. - SHasKey(bucket string, key []byte) (bool, error) - - // SPop removes and returns one or more random elements from the set value store in the bucket at given bucket and key. - SPop(bucket string, key []byte) ([]byte, error) - - // SCard returns the set cardinality (number of elements) of the set stored in the bucket at given bucket and key. - SCard(bucket string, key []byte) (int, error) - - // SDiffByOneBucket returns the members of the set resulting from the difference - // between the first set and all the successive sets in one bucket. - SDiffByOneBucket(bucket string, key1, key2 []byte) (list [][]byte, err error) - - // SDiffByTwoBuckets returns the members of the set resulting from the difference - // between the first set and all the successive sets in two buckets. - SDiffByTwoBuckets(bucket1 string, key1 []byte, bucket2 string, key2 []byte) (list [][]byte, err error) - - // SMoveByOneBucket moves member from the set at source to the set at destination in one bucket. - SMoveByOneBucket(bucket string, key1, key2, item []byte) (bool, error) - - // SMoveByTwoBuckets moves member from the set at source to the set at destination in two buckets. - SMoveByTwoBuckets(bucket1 string, key1 []byte, bucket2 string, key2, item []byte) (bool, error) - - // SUnionByOneBucket the members of the set resulting from the union of all the given sets in one bucket. - SUnionByOneBucket(bucket string, key1, key2 []byte) (list [][]byte, err error) - - // SUnionByTwoBuckets the members of the set resulting from the union of all the given sets in two buckets. - SUnionByTwoBuckets(bucket1 string, key1 []byte, bucket2 string, key2 []byte) (list [][]byte, err error) -} - -type CommandList interface { - // RPop removes and returns the last element of the list stored in the bucket at given bucket and key. - RPop(bucket string, key []byte) (item []byte, err error) - - // RPeek returns the last element of the list stored in the bucket at given bucket and key. - RPeek(bucket string, key []byte) (item []byte, err error) - - // RPush inserts the values at the tail of the list stored in the bucket at given bucket,key and values. - RPush(bucket string, key []byte, values ...[]byte) error - - // LPush inserts the values at the head of the list stored in the bucket at given bucket,key and values. - LPush(bucket string, key []byte, values ...[]byte) error - - // LPop removes and returns the first element of the list stored in the bucket at given bucket and key. - LPop(bucket string, key []byte) (item []byte, err error) - - // LPeek returns the first element of the list stored in the bucket at given bucket and key. - LPeek(bucket string, key []byte) (item []byte, err error) - - // LSize returns the size of key in the bucket in the bucket at given bucket and key. - LSize(bucket string, key []byte) (int, error) - - // LRange returns the specified elements of the list stored in the bucket at given bucket,key, start and end. - // The offsets start and stop are zero-based indexes 0 being the first element of the list (the head of the list), - // 1 being the next element and so on. - // Start and end can also be negative numbers indicating offsets from the end of the list, - // where -1 is the last element of the list, -2 the penultimate element and so on. - LRange(bucket string, key []byte, start, end int) (list [][]byte, err error) - - // LRem removes the first count occurrences of elements equal to value from the list stored in the bucket at given bucket,key,count. - // The count argument influences the operation in the following ways: - // count > 0: Remove elements equal to value moving from head to tail. - // count < 0: Remove elements equal to value moving from tail to head. - // count = 0: Remove all elements equal to value. - LRem(bucket string, key []byte, count int, value []byte) (removedNum int, err error) - - // LSet sets the list element at index to value. - LSet(bucket string, key []byte, index int, value []byte) error - - // LTrim trims an existing list so that it will contain only the specified range of elements specified. - // the offsets start and stop are zero-based indexes 0 being the first element of the list (the head of the list), - // 1 being the next element and so on. - // start and end can also be negative numbers indicating offsets from the end of the list, - // where -1 is the last element of the list, -2 the penultimate element and so on. - LTrim(bucket string, key []byte, start, end int) error -} - -type CommandZSet interface { - // ZAdd adds the specified member key with the specified score and specified val to the sorted set stored at bucket. - ZAdd(bucket string, key []byte, score float64, val []byte) error - - // ZMembers returns all the members of the set value stored at bucket. - ZMembers(bucket string) (map[string]*nutsdb.SortedSetMember, error) - - // ZCard returns the sorted set cardinality (number of elements) of the sorted set stored at bucket. - ZCard(bucket string) (int, error) - - // ZCount returns the number of elements in the sorted set at bucket with a score between min and max and opts. - // opts includes the following parameters: - // Limit int // limit the max nodes to return - // ExcludeStart bool // exclude start value, so it search in interval (start, end] or (start, end) - // ExcludeEnd bool // exclude end value, so it search in interval [start, end) or (start, end) - ZCount(bucket string, start, end float64, opts *nutsdb.GetByScoreRangeOptions) (int, error) - - // ZPopMax removes and returns the member with the highest score in the sorted set stored at bucket. - ZPopMax(bucket string) (*nutsdb.SortedSetMember, error) - - // ZPopMin removes and returns the member with the lowest score in the sorted set stored at bucket. - ZPopMin(bucket string) (*nutsdb.SortedSetMember, error) - - // ZPeekMax returns the member with the highest score in the sorted set stored at bucket. - ZPeekMax(bucket string) (*nutsdb.SortedSetMember, error) - - // ZPeekMin returns the member with the lowest score in the sorted set stored at bucket. - ZPeekMin(bucket string) (*nutsdb.SortedSetMember, error) - - // ZRangeByScore returns all the elements in the sorted set at bucket with a score between min and max. - ZRangeByScore(bucket string, start, end float64, opts *nutsdb.GetByScoreRangeOptions) ([]*nutsdb.SortedSetMember, error) - - // ZRangeByRank returns all the elements in the sorted set in one bucket and key - // with a rank between start and end (including elements with rank equal to start or end). - ZRangeByRank(bucket string, start, end int) ([]*nutsdb.SortedSetMember, error) - - // ZRem removes the specified members from the sorted set stored in one bucket at given bucket and key. - ZRem(bucket, key string) error - - // ZRemRangeByRank removes all elements in the sorted set stored in one bucket at given bucket with rank between start and end. - // the rank is 1-based integer. Rank 1 means the first node; Rank -1 means the last node. - ZRemRangeByRank(bucket string, start, end int) error - - // ZRank returns the rank of member in the sorted set stored in the bucket at given bucket and key, - // with the scores ordered from low to high. - ZRank(bucket string, key []byte) (int, error) - - // ZRevRank returns the rank of member in the sorted set stored in the bucket at given bucket and key, - // with the scores ordered from high to low. - ZRevRank(bucket string, key []byte) (int, error) - - // ZScore returns the score of member in the sorted set in the bucket at given bucket and key. - ZScore(bucket string, key []byte) (float64, error) - - // ZGetByKey returns node in the bucket at given bucket and key. - ZGetByKey(bucket string, key []byte) (*nutsdb.SortedSetMember, error) -} diff --git a/nutsdb/client.go b/nutsdb/client.go deleted file mode 100644 index 8e4fc83..0000000 --- a/nutsdb/client.go +++ /dev/null @@ -1,1595 +0,0 @@ -//go:build !386 && !arm && !mips && !mipsle -// +build !386,!arm,!mips,!mipsle - -/*********************************************************************************************************************** - * - * MIT License - * - * Copyright (c) 2021 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * - **********************************************************************************************************************/ - -package nutsdb - -import ( - "context" - "fmt" - "reflect" - "strconv" - "time" - - "github.com/lni/dragonboat/v3/statemachine" - libclu "github.com/nabbar/golib/cluster" - liberr "github.com/nabbar/golib/errors" - "github.com/nutsdb/nutsdb" -) - -type Client interface { - Commands - Run(cmd CmdCode, args []string) (*CommandResponse, liberr.Error) -} - -type clientNutDB struct { - x context.Context - t time.Duration - c func() libclu.Cluster - w func(ctx context.Context, tick time.Duration) -} - -func (c *clientNutDB) call(cmd *CommandRequest, read bool) (*CommandResponse, liberr.Error) { - var ( - p []byte - e liberr.Error - i interface{} - d statemachine.Result - r *CommandResponse - - ok bool - ) - - if read { - c.w(c.x, c.t) - if i, e = c.c().SyncRead(c.x, cmd); e != nil { - return nil, e - } else if r, ok = i.(*CommandResponse); !ok { - return nil, ErrorClientCommandResponseInvalid.Error(nil) - } else { - return r, nil - } - } else if p, e = cmd.EncodeRequest(); e != nil { - return nil, e - } else { - c.w(c.x, c.t) - if d, e = c.c().SyncPropose(c.x, c.c().GetNoOPSession(), p); e != nil { - return nil, e - } else if r, e = cmd.DecodeResult(d.Data); e != nil { - return nil, e - } else { - return r, nil - } - } -} - -func (c *clientNutDB) strToType(dest reflect.Type, val string) (interface{}, liberr.Error) { - sliceByte := reflect.ValueOf(make([]byte, 0)) - - switch dest.Kind() { - case reflect.Bool: - if v, e := strconv.ParseBool(val); e != nil { - return nil, ErrorParamMismatching.Error(e) - } else { - return v, nil - } - case reflect.Int: - if v, e := strconv.ParseInt(val, 10, 64); e != nil { - return nil, ErrorParamMismatching.Error(e) - } else { - return int(v), nil - } - case reflect.Int8: - if v, e := strconv.ParseInt(val, 10, 8); e != nil { - return nil, ErrorParamMismatching.Error(e) - } else { - return int8(v), nil - } - case reflect.Int16: - if v, e := strconv.ParseInt(val, 10, 16); e != nil { - return nil, ErrorParamMismatching.Error(e) - } else { - return int16(v), nil - } - case reflect.Int32: - if v, e := strconv.ParseInt(val, 10, 32); e != nil { - return nil, ErrorParamMismatching.Error(e) - } else { - return int32(v), nil - } - case reflect.Int64: - if v, e := strconv.ParseInt(val, 10, 64); e != nil { - return nil, ErrorParamMismatching.Error(e) - } else { - return v, nil - } - case reflect.Uint: - if v, e := strconv.ParseUint(val, 10, 64); e != nil { - return nil, ErrorParamMismatching.Error(e) - } else { - return uint(v), nil - } - case reflect.Uint8: - if v, e := strconv.ParseUint(val, 10, 8); e != nil { - return nil, ErrorParamMismatching.Error(e) - } else { - return uint8(v), nil - } - case reflect.Uint16: - if v, e := strconv.ParseUint(val, 10, 16); e != nil { - return nil, ErrorParamMismatching.Error(e) - } else { - return uint16(v), nil - } - case reflect.Uint32: - if v, e := strconv.ParseUint(val, 10, 32); e != nil { - return nil, ErrorParamMismatching.Error(e) - } else { - return uint32(v), nil - } - case reflect.Uint64: - if v, e := strconv.ParseUint(val, 10, 64); e != nil { - return nil, ErrorParamMismatching.Error(e) - } else { - return v, nil - } - case reflect.Uintptr: - return nil, ErrorParamInvalid.Error(fmt.Errorf("cannot convert int UintPtr")) - case reflect.Float32: - if v, e := strconv.ParseFloat(val, 32); e != nil { - return nil, ErrorParamMismatching.Error(e) - } else { - return float32(v), nil - } - case reflect.Float64: - if v, e := strconv.ParseFloat(val, 64); e != nil { - return nil, ErrorParamMismatching.Error(e) - } else { - return v, nil - } - case reflect.Complex64: - if v, e := strconv.ParseComplex(val, 64); e != nil { - return nil, ErrorParamMismatching.Error(e) - } else { - return complex64(v), nil - } - case reflect.Complex128: - if v, e := strconv.ParseComplex(val, 128); e != nil { - return nil, ErrorParamMismatching.Error(e) - } else { - return v, nil - } - case reflect.Slice: - if dest == sliceByte.Type() { - return []byte(val), nil - } else { - return nil, ErrorParamInvalid.Error(nil) - } - case reflect.String: - return val, nil - default: - return nil, ErrorParamInvalid.Error(nil) - } -} - -func (c *clientNutDB) Run(cmd CmdCode, args []string) (*CommandResponse, liberr.Error) { - method := reflect.ValueOf(c).MethodByName(cmd.Name()) - nbPrm := method.Type().NumIn() - - switch cmd { - case CmdZCount: - if len(args) < 3 || len(args) > 6 { - return nil, ErrorParamInvalidNumber.Error(nil) - } - case CmdZRangeByScore: - if len(args) < 3 || len(args) > 6 { - return nil, ErrorParamInvalidNumber.Error(nil) - } - default: - if len(args) != nbPrm { - return nil, ErrorParamInvalidNumber.Error(nil) - } - } - - params := make([]reflect.Value, nbPrm) - opt := &nutsdb.GetByScoreRangeOptions{ - Limit: 0, - ExcludeStart: false, - ExcludeEnd: false, - } - - for i := 0; i < nbPrm; i++ { - switch cmd { - case CmdZCount, CmdZRangeByScore: - switch i { - case 3: - if v, e := c.strToType(reflect.TypeOf(opt.Limit), args[i]); e != nil { - return nil, e - } else if v == nil { - opt.Limit = 0 - } else if vv, ok := v.(int); !ok { - return nil, ErrorParamMismatching.Error(nil) - } else { - opt.Limit = vv - } - case 4: - if v, e := c.strToType(reflect.TypeOf(opt.ExcludeStart), args[i]); e != nil { - return nil, e - } else if v == nil { - opt.ExcludeStart = false - } else if vv, ok := v.(bool); !ok { - return nil, ErrorParamMismatching.Error(nil) - } else { - opt.ExcludeStart = vv - } - case 5: - if v, e := c.strToType(reflect.TypeOf(opt.ExcludeEnd), args[i]); e != nil { - return nil, e - } else if v == nil { - opt.ExcludeEnd = false - } else if vv, ok := v.(bool); !ok { - return nil, ErrorParamMismatching.Error(nil) - } else { - opt.ExcludeEnd = vv - } - default: - return nil, ErrorParamInvalid.Error(nil) - } - default: - if v, e := c.strToType(method.Type().In(i), args[i]); e != nil { - return nil, e - } else { - params[i] = reflect.ValueOf(v) - } - } - } - - switch cmd { - case CmdZCount, CmdZRangeByScore: - params[3] = reflect.ValueOf(opt) - } - - resp := method.Call(params) - - ret := CommandResponse{ - Error: nil, - Value: make([]interface{}, 0), - } - - for i := 0; i < len(resp); i++ { - v := resp[i].Interface() - if e, ok := v.(error); ok { - ret.Error = e - } else { - ret.Value = append(ret.Value, v) - } - } - - if ret.Error == nil && len(ret.Value) < 1 { - return nil, nil - } - - return &ret, nil -} - -// nolint #dupl -func (c *clientNutDB) Put(bucket string, key, value []byte, ttl uint32) error { - var ( - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, key, value, ttl) - - if r, f = c.call(d, false); f != nil { - return f - } else if r == nil { - return nil - } else if r.Error != nil { - return r.Error - } - - return nil -} - -// nolint #dupl -func (c *clientNutDB) PutWithTimestamp(bucket string, key, value []byte, ttl uint32, timestamp uint64) error { - var ( - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, key, value, ttl, timestamp) - - if r, f = c.call(d, false); f != nil { - return f - } else if r == nil { - return nil - } else if r.Error != nil { - return r.Error - } - - return nil -} - -// nolint #dupl -func (c *clientNutDB) Get(bucket string, key []byte) (e *nutsdb.Entry, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, key) - - if r, f = c.call(d, true); f != nil { - return nil, f - } else if r == nil { - return nil, nil - } else if r.Error != nil { - return nil, r.Error - } else if len(r.Value) < 1 { - return nil, nil - } - - if e, k = r.Value[0].(*nutsdb.Entry); !k { - e = nil - } - - return -} - -// nolint #dupl -func (c *clientNutDB) GetAll(bucket string) (entries nutsdb.Entries, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket) - - if r, f = c.call(d, true); f != nil { - return nil, f - } else if r == nil { - return nil, nil - } else if r.Error != nil { - return nil, r.Error - } else if len(r.Value) < 1 { - return nil, nil - } - - if entries, k = r.Value[0].(nutsdb.Entries); !k { - entries = nil - } - - return -} - -// nolint #dupl -func (c *clientNutDB) RangeScan(bucket string, start, end []byte) (es nutsdb.Entries, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, start, end) - - if r, f = c.call(d, true); f != nil { - return nil, f - } else if r == nil { - return nil, nil - } else if r.Error != nil { - return nil, r.Error - } else if len(r.Value) < 1 { - return nil, nil - } - - if es, k = r.Value[0].(nutsdb.Entries); !k { - es = nil - } - - return -} - -// nolint #dupl -func (c *clientNutDB) PrefixScan(bucket string, prefix []byte, offsetNum int, limitNum int) (es nutsdb.Entries, off int, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, prefix, offsetNum, limitNum) - - if r, f = c.call(d, true); f != nil { - return nil, 0, f - } else if r == nil { - return nil, 0, nil - } else if r.Error != nil { - return nil, 0, r.Error - } else if len(r.Value) < 2 { - return nil, 0, nil - } - - if es, k = r.Value[0].(nutsdb.Entries); !k { - es = nil - } - - if off, k = r.Value[1].(int); !k { - off = 0 - } - - return -} - -// nolint #dupl -func (c *clientNutDB) PrefixSearchScan(bucket string, prefix []byte, reg string, offsetNum int, limitNum int) (es nutsdb.Entries, off int, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, prefix, reg, offsetNum, limitNum) - - if r, f = c.call(d, true); f != nil { - return nil, 0, f - } else if r == nil { - return nil, 0, nil - } else if r.Error != nil { - return nil, 0, r.Error - } else if len(r.Value) < 2 { - return nil, 0, nil - } - - if es, k = r.Value[0].(nutsdb.Entries); !k { - es = nil - } - - if off, k = r.Value[1].(int); !k { - off = 0 - } - - return -} - -// nolint #dupl -func (c *clientNutDB) Delete(bucket string, key []byte) error { - var ( - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, key) - - if r, f = c.call(d, true); f != nil { - return f - } else if r == nil { - return nil - } else if r.Error != nil { - return r.Error - } - - return nil -} - -// nolint #dupl -func (c *clientNutDB) SAdd(bucket string, key []byte, items ...[]byte) error { - var ( - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, key, items) - - if r, f = c.call(d, true); f != nil { - return f - } else if r == nil { - return nil - } else if r.Error != nil { - return r.Error - } - - return nil -} - -// nolint #dupl -func (c *clientNutDB) SRem(bucket string, key []byte, items ...[]byte) error { - var ( - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, key, items) - - if r, f = c.call(d, true); f != nil { - return f - } else if r == nil { - return nil - } else if r.Error != nil { - return r.Error - } - - return nil -} - -// nolint #dupl -func (c *clientNutDB) SAreMembers(bucket string, key []byte, items ...[]byte) (ok bool, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, key, items) - - if r, f = c.call(d, true); f != nil { - return false, f - } else if r == nil { - return false, nil - } else if r.Error != nil { - return false, r.Error - } else if len(r.Value) < 1 { - return false, nil - } - - if ok, k = r.Value[0].(bool); !k { - ok = false - } - - return -} - -// nolint #dupl -func (c *clientNutDB) SIsMember(bucket string, key, item []byte) (ok bool, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, key, item) - - if r, f = c.call(d, true); f != nil { - return false, f - } else if r == nil { - return false, nil - } else if r.Error != nil { - return false, r.Error - } else if len(r.Value) < 1 { - return false, nil - } - - if ok, k = r.Value[0].(bool); !k { - ok = false - } - - return -} - -// nolint #dupl -func (c *clientNutDB) SMembers(bucket string, key []byte) (list [][]byte, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, key) - - if r, f = c.call(d, true); f != nil { - return nil, f - } else if r == nil { - return nil, nil - } else if r.Error != nil { - return nil, r.Error - } else if len(r.Value) < 1 { - return nil, nil - } - - if list, k = r.Value[0].([][]byte); !k { - list = nil - } - - return -} - -// nolint #dupl -func (c *clientNutDB) SHasKey(bucket string, key []byte) (ok bool, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, key) - - if r, f = c.call(d, true); f != nil { - return false, f - } else if r == nil { - return false, nil - } else if r.Error != nil { - return false, r.Error - } else if len(r.Value) < 1 { - return false, nil - } - - if ok, k = r.Value[0].(bool); !k { - ok = false - } - - return -} - -// nolint #dupl -func (c *clientNutDB) SPop(bucket string, key []byte) (val []byte, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, key) - - if r, f = c.call(d, true); f != nil { - return nil, f - } else if r == nil { - return nil, nil - } else if r.Error != nil { - return nil, r.Error - } else if len(r.Value) < 1 { - return nil, nil - } - - if val, k = r.Value[0].([]byte); !k { - val = nil - } - - return -} - -// nolint #dupl -func (c *clientNutDB) SCard(bucket string, key []byte) (card int, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, key) - - if r, f = c.call(d, true); f != nil { - return 0, f - } else if r == nil { - return 0, nil - } else if r.Error != nil { - return 0, r.Error - } else if len(r.Value) < 1 { - return 0, nil - } - - if card, k = r.Value[0].(int); !k { - card = 0 - } - - return -} - -// nolint #dupl -func (c *clientNutDB) SDiffByOneBucket(bucket string, key1, key2 []byte) (list [][]byte, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, key1, key2) - - if r, f = c.call(d, true); f != nil { - return nil, f - } else if r == nil { - return nil, nil - } else if r.Error != nil { - return nil, r.Error - } else if len(r.Value) < 1 { - return nil, nil - } - - if list, k = r.Value[0].([][]byte); !k { - list = nil - } - - return -} - -// nolint #dupl -func (c *clientNutDB) SDiffByTwoBuckets(bucket1 string, key1 []byte, bucket2 string, key2 []byte) (list [][]byte, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket1, key1, bucket2, key2) - - if r, f = c.call(d, true); f != nil { - return nil, f - } else if r == nil { - return nil, nil - } else if r.Error != nil { - return nil, r.Error - } else if len(r.Value) < 1 { - return nil, nil - } - - if list, k = r.Value[0].([][]byte); !k { - list = nil - } - - return -} - -// nolint #dupl -func (c *clientNutDB) SMoveByOneBucket(bucket string, key1, key2, item []byte) (ok bool, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, key1, key2, item) - - if r, f = c.call(d, true); f != nil { - return false, f - } else if r == nil { - return false, nil - } else if r.Error != nil { - return false, r.Error - } else if len(r.Value) < 1 { - return false, nil - } - - if ok, k = r.Value[0].(bool); !k { - ok = false - } - - return -} - -// nolint #dupl -func (c *clientNutDB) SMoveByTwoBuckets(bucket1 string, key1 []byte, bucket2 string, key2, item []byte) (ok bool, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket1, key1, bucket2, key2, item) - - if r, f = c.call(d, true); f != nil { - return false, f - } else if r == nil { - return false, nil - } else if r.Error != nil { - return false, r.Error - } else if len(r.Value) < 1 { - return false, nil - } - - if ok, k = r.Value[0].(bool); !k { - ok = false - } - - return -} - -// nolint #dupl -func (c *clientNutDB) SUnionByOneBucket(bucket string, key1, key2 []byte) (list [][]byte, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, key1, key2) - - if r, f = c.call(d, true); f != nil { - return nil, f - } else if r == nil { - return nil, nil - } else if r.Error != nil { - return nil, r.Error - } else if len(r.Value) < 1 { - return nil, nil - } - - if list, k = r.Value[0].([][]byte); !k { - list = nil - } - - return -} - -// nolint #dupl -func (c *clientNutDB) SUnionByTwoBuckets(bucket1 string, key1 []byte, bucket2 string, key2 []byte) (list [][]byte, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket1, key1, bucket2, key2) - - if r, f = c.call(d, true); f != nil { - return nil, f - } else if r == nil { - return nil, nil - } else if r.Error != nil { - return nil, r.Error - } else if len(r.Value) < 1 { - return nil, nil - } - - if list, k = r.Value[0].([][]byte); !k { - list = nil - } - - return -} - -// nolint #dupl -func (c *clientNutDB) RPop(bucket string, key []byte) (item []byte, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, key) - - if r, f = c.call(d, true); f != nil { - return nil, f - } else if r == nil { - return nil, nil - } else if r.Error != nil { - return nil, r.Error - } else if len(r.Value) < 1 { - return nil, nil - } - - if item, k = r.Value[0].([]byte); !k { - item = nil - } - - return -} - -// nolint #dupl -func (c *clientNutDB) RPeek(bucket string, key []byte) (item []byte, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, key) - - if r, f = c.call(d, true); f != nil { - return nil, f - } else if r == nil { - return nil, nil - } else if r.Error != nil { - return nil, r.Error - } else if len(r.Value) < 1 { - return nil, nil - } - - if item, k = r.Value[0].([]byte); !k { - item = nil - } - - return -} - -// nolint #dupl -func (c *clientNutDB) RPush(bucket string, key []byte, values ...[]byte) error { - var ( - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, key, values) - - if r, f = c.call(d, true); f != nil { - return f - } else if r == nil { - return nil - } else if r.Error != nil { - return r.Error - } - - return nil -} - -// nolint #dupl -func (c *clientNutDB) LPush(bucket string, key []byte, values ...[]byte) error { - var ( - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, key, values) - - if r, f = c.call(d, true); f != nil { - return f - } else if r == nil { - return nil - } else if r.Error != nil { - return r.Error - } - - return nil -} - -// nolint #dupl -func (c *clientNutDB) LPop(bucket string, key []byte) (item []byte, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, key) - - if r, f = c.call(d, true); f != nil { - return nil, f - } else if r == nil { - return nil, nil - } else if r.Error != nil { - return nil, r.Error - } else if len(r.Value) < 1 { - return nil, nil - } - - if item, k = r.Value[0].([]byte); !k { - item = nil - } - - return -} - -// nolint #dupl -func (c *clientNutDB) LPeek(bucket string, key []byte) (item []byte, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, key) - - if r, f = c.call(d, true); f != nil { - return nil, f - } else if r == nil { - return nil, nil - } else if r.Error != nil { - return nil, r.Error - } else if len(r.Value) < 1 { - return nil, nil - } - - if item, k = r.Value[0].([]byte); !k { - item = nil - } - - return -} - -// nolint #dupl -func (c *clientNutDB) LSize(bucket string, key []byte) (size int, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, key) - - if r, f = c.call(d, true); f != nil { - return 0, f - } else if r == nil { - return 0, nil - } else if r.Error != nil { - return 0, r.Error - } else if len(r.Value) < 1 { - return 0, nil - } - - if size, k = r.Value[0].(int); !k { - size = 0 - } - - return -} - -// nolint #dupl -func (c *clientNutDB) LRange(bucket string, key []byte, start, end int) (list [][]byte, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, key, start, end) - - if r, f = c.call(d, true); f != nil { - return nil, f - } else if r == nil { - return nil, nil - } else if r.Error != nil { - return nil, r.Error - } else if len(r.Value) < 1 { - return nil, nil - } - - if list, k = r.Value[0].([][]byte); !k { - list = nil - } - - return -} - -// nolint #dupl -func (c *clientNutDB) LRem(bucket string, key []byte, count int, value []byte) (removedNum int, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, key, count, value) - - if r, f = c.call(d, true); f != nil { - return 0, f - } else if r == nil { - return 0, nil - } else if r.Error != nil { - return 0, r.Error - } else if len(r.Value) < 1 { - return 0, nil - } - - if removedNum, k = r.Value[0].(int); !k { - removedNum = 0 - } - - return -} - -// nolint #dupl -func (c *clientNutDB) LSet(bucket string, key []byte, index int, value []byte) error { - var ( - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, key, index, value) - - if r, f = c.call(d, true); f != nil { - return f - } else if r == nil { - return nil - } else if r.Error != nil { - return r.Error - } - - return nil -} - -// nolint #dupl -func (c *clientNutDB) LTrim(bucket string, key []byte, start, end int) error { - var ( - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, key, start, end) - - if r, f = c.call(d, true); f != nil { - return f - } else if r == nil { - return nil - } else if r.Error != nil { - return r.Error - } - - return nil -} - -// nolint #dupl -func (c *clientNutDB) ZAdd(bucket string, key []byte, score float64, val []byte) error { - var ( - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, key, score, val) - - if r, f = c.call(d, true); f != nil { - return f - } else if r == nil { - return nil - } else if r.Error != nil { - return r.Error - } - - return nil -} - -// nolint #dupl -func (c *clientNutDB) ZMembers(bucket string) (list map[string]*nutsdb.SortedSetMember, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket) - - if r, f = c.call(d, true); f != nil { - return nil, f - } else if r == nil { - return nil, nil - } else if r.Error != nil { - return nil, r.Error - } else if len(r.Value) < 1 { - return nil, nil - } - - if list, k = r.Value[0].(map[string]*nutsdb.SortedSetMember); !k { - list = nil - } - - return -} - -// nolint #dupl -func (c *clientNutDB) ZCard(bucket string) (card int, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket) - - if r, f = c.call(d, true); f != nil { - return 0, f - } else if r == nil { - return 0, nil - } else if r.Error != nil { - return 0, r.Error - } else if len(r.Value) < 1 { - return 0, nil - } - - if card, k = r.Value[0].(int); !k { - card = 0 - } - - return -} - -// nolint #dupl -func (c *clientNutDB) ZCount(bucket string, start, end float64, opts *nutsdb.GetByScoreRangeOptions) (number int, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, start, end, opts) - - if r, f = c.call(d, true); f != nil { - return 0, f - } else if r == nil { - return 0, nil - } else if r.Error != nil { - return 0, r.Error - } else if len(r.Value) < 1 { - return 0, nil - } - - if number, k = r.Value[0].(int); !k { - number = 0 - } - - return -} - -// nolint #dupl -func (c *clientNutDB) ZPopMax(bucket string) (item *nutsdb.SortedSetMember, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket) - - if r, f = c.call(d, true); f != nil { - return nil, f - } else if r == nil { - return nil, nil - } else if r.Error != nil { - return nil, r.Error - } else if len(r.Value) < 1 { - return nil, nil - } - - if item, k = r.Value[0].(*nutsdb.SortedSetMember); !k { - item = nil - } - - return -} - -// nolint #dupl -func (c *clientNutDB) ZPopMin(bucket string) (item *nutsdb.SortedSetMember, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket) - - if r, f = c.call(d, true); f != nil { - return nil, f - } else if r == nil { - return nil, nil - } else if r.Error != nil { - return nil, r.Error - } else if len(r.Value) < 1 { - return nil, nil - } - - if item, k = r.Value[0].(*nutsdb.SortedSetMember); !k { - item = nil - } - - return -} - -// nolint #dupl -func (c *clientNutDB) ZPeekMax(bucket string) (item *nutsdb.SortedSetMember, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket) - - if r, f = c.call(d, true); f != nil { - return nil, f - } else if r == nil { - return nil, nil - } else if r.Error != nil { - return nil, r.Error - } else if len(r.Value) < 1 { - return nil, nil - } - - if item, k = r.Value[0].(*nutsdb.SortedSetMember); !k { - item = nil - } - - return -} - -// nolint #dupl -func (c *clientNutDB) ZPeekMin(bucket string) (item *nutsdb.SortedSetMember, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket) - - if r, f = c.call(d, true); f != nil { - return nil, f - } else if r == nil { - return nil, nil - } else if r.Error != nil { - return nil, r.Error - } else if len(r.Value) < 1 { - return nil, nil - } - - if item, k = r.Value[0].(*nutsdb.SortedSetMember); !k { - item = nil - } - - return -} - -// nolint #dupl -func (c *clientNutDB) ZRangeByScore(bucket string, start, end float64, opts *nutsdb.GetByScoreRangeOptions) (list []*nutsdb.SortedSetMember, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, start, end, opts) - - if r, f = c.call(d, true); f != nil { - return nil, f - } else if r == nil { - return nil, nil - } else if r.Error != nil { - return nil, r.Error - } else if len(r.Value) < 1 { - return nil, nil - } - - if list, k = r.Value[0].([]*nutsdb.SortedSetMember); !k { - list = nil - } - - return -} - -// nolint #dupl -func (c *clientNutDB) ZRangeByRank(bucket string, start, end int) (list []*nutsdb.SortedSetMember, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, start, end) - - if r, f = c.call(d, true); f != nil { - return nil, f - } else if r == nil { - return nil, nil - } else if r.Error != nil { - return nil, r.Error - } else if len(r.Value) < 1 { - return nil, nil - } - - if list, k = r.Value[0].([]*nutsdb.SortedSetMember); !k { - list = nil - } - - return -} - -// nolint #dupl -func (c *clientNutDB) ZRem(bucket, key string) error { - var ( - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, key) - - if r, f = c.call(d, true); f != nil { - return f - } else if r == nil { - return nil - } else if r.Error != nil { - return r.Error - } - - return nil -} - -// nolint #dupl -func (c *clientNutDB) ZRemRangeByRank(bucket string, start, end int) error { - var ( - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, start, end) - - if r, f = c.call(d, true); f != nil { - return f - } else if r == nil { - return nil - } else if r.Error != nil { - return r.Error - } - - return nil -} - -// nolint #dupl -func (c *clientNutDB) ZRank(bucket string, key []byte) (rank int, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, key) - - if r, f = c.call(d, true); f != nil { - return 0, f - } else if r == nil { - return 0, nil - } else if r.Error != nil { - return 0, r.Error - } else if len(r.Value) < 1 { - return 0, nil - } - - if rank, k = r.Value[0].(int); !k { - rank = 0 - } - - return -} - -// nolint #dupl -func (c *clientNutDB) ZRevRank(bucket string, key []byte) (rank int, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, key) - - if r, f = c.call(d, true); f != nil { - return 0, f - } else if r == nil { - return 0, nil - } else if r.Error != nil { - return 0, r.Error - } else if len(r.Value) < 1 { - return 0, nil - } - - if rank, k = r.Value[0].(int); !k { - rank = 0 - } - - return -} - -// nolint #dupl -func (c *clientNutDB) ZScore(bucket string, key []byte) (score float64, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, key) - - if r, f = c.call(d, true); f != nil { - return 0, f - } else if r == nil { - return 0, nil - } else if r.Error != nil { - return 0, r.Error - } else if len(r.Value) < 1 { - return 0, nil - } - - if score, k = r.Value[0].(float64); !k { - score = 0 - } - - return -} - -// nolint #dupl -func (c *clientNutDB) ZGetByKey(bucket string, key []byte) (item *nutsdb.SortedSetMember, err error) { - var ( - k bool - f liberr.Error - r *CommandResponse - d *CommandRequest - ) - - d = NewCommandByCaller(bucket, key) - - if r, f = c.call(d, true); f != nil { - return nil, f - } else if r == nil { - return nil, nil - } else if r.Error != nil { - return nil, r.Error - } else if len(r.Value) < 1 { - return nil, nil - } - - if item, k = r.Value[0].(*nutsdb.SortedSetMember); !k { - item = nil - } - - return -} diff --git a/nutsdb/cmdCode.go b/nutsdb/cmdCode.go deleted file mode 100644 index 8aef31d..0000000 --- a/nutsdb/cmdCode.go +++ /dev/null @@ -1,777 +0,0 @@ -//go:build !386 && !arm && !mips && !mipsle -// +build !386,!arm,!mips,!mipsle - -/*********************************************************************************************************************** - * - * MIT License - * - * Copyright (c) 2021 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * - **********************************************************************************************************************/ - -package nutsdb - -type CmdCode uint32 - -const ( - // CmdUnknown is no Command. - CmdUnknown CmdCode = iota - // Command for transaction. - CmdPut - CmdPutWithTimestamp - // Command for BPTree. - CmdGet - CmdGetAll - CmdRangeScan - CmdPrefixScan - CmdPrefixSearchScan - CmdDelete - CmdFindTxIDOnDisk - CmdFindOnDisk - CmdFindLeafOnDisk - // Command for Set. - CmdSAdd - CmdSRem - CmdSAreMembers - CmdSIsMember - CmdSMembers - CmdSHasKey - CmdSPop - CmdSCard - CmdSDiffByOneBucket - CmdSDiffByTwoBuckets - CmdSMoveByOneBucket - CmdSMoveByTwoBuckets - CmdSUnionByOneBucket - CmdSUnionByTwoBuckets - // Command for List. - CmdRPop - CmdRPeek - CmdRPush - CmdLPush - CmdLPop - CmdLPeek - CmdLSize - CmdLRange - CmdLRem - CmdLSet - CmdLTrim - // Command for ZSet. - CmdZAdd - CmdZMembers - CmdZCard - CmdZCount - CmdZPopMax - CmdZPopMin - CmdZPeekMax - CmdZPeekMin - CmdZRangeByScore - CmdZRangeByRank - CmdZRem - CmdZRemRangeByRank - CmdZRank - CmdZRevRank - CmdZScore - CmdZGetByKey -) - -// nolint #funlen -func CmdCodeFromName(name string) CmdCode { - switch name { - case CmdPut.Name(): - return CmdPut - - case CmdPutWithTimestamp.Name(): - return CmdPutWithTimestamp - - case CmdGet.Name(): - return CmdGet - - case CmdGetAll.Name(): - return CmdGetAll - - case CmdRangeScan.Name(): - return CmdRangeScan - - case CmdPrefixScan.Name(): - return CmdPrefixScan - - case CmdPrefixSearchScan.Name(): - return CmdPrefixSearchScan - - case CmdDelete.Name(): - return CmdDelete - - case CmdFindTxIDOnDisk.Name(): - return CmdFindTxIDOnDisk - - case CmdFindOnDisk.Name(): - return CmdFindOnDisk - - case CmdFindLeafOnDisk.Name(): - return CmdFindLeafOnDisk - - case CmdSAdd.Name(): - return CmdSAdd - - case CmdSRem.Name(): - return CmdSRem - - case CmdSAreMembers.Name(): - return CmdSAreMembers - - case CmdSIsMember.Name(): - return CmdSIsMember - - case CmdSMembers.Name(): - return CmdSMembers - - case CmdSHasKey.Name(): - return CmdSHasKey - - case CmdSPop.Name(): - return CmdSPop - - case CmdSCard.Name(): - return CmdSCard - - case CmdSDiffByOneBucket.Name(): - return CmdSDiffByOneBucket - - case CmdSDiffByTwoBuckets.Name(): - return CmdSDiffByTwoBuckets - - case CmdSMoveByOneBucket.Name(): - return CmdSMoveByOneBucket - - case CmdSMoveByTwoBuckets.Name(): - return CmdSMoveByTwoBuckets - - case CmdSUnionByOneBucket.Name(): - return CmdSUnionByOneBucket - - case CmdSUnionByTwoBuckets.Name(): - return CmdSUnionByTwoBuckets - - case CmdRPop.Name(): - return CmdRPop - - case CmdRPeek.Name(): - return CmdRPeek - - case CmdRPush.Name(): - return CmdRPush - - case CmdLPush.Name(): - return CmdLPush - - case CmdLPop.Name(): - return CmdLPop - - case CmdLPeek.Name(): - return CmdLPeek - - case CmdLSize.Name(): - return CmdLSize - - case CmdLRange.Name(): - return CmdLRange - - case CmdLRem.Name(): - return CmdLRem - - case CmdLSet.Name(): - return CmdLSet - - case CmdLTrim.Name(): - return CmdLTrim - - case CmdZAdd.Name(): - return CmdZAdd - - case CmdZMembers.Name(): - return CmdZMembers - - case CmdZCard.Name(): - return CmdZCard - - case CmdZCount.Name(): - return CmdZCount - - case CmdZPopMax.Name(): - return CmdZPopMax - - case CmdZPopMin.Name(): - return CmdZPopMin - - case CmdZPeekMax.Name(): - return CmdZPeekMax - - case CmdZPeekMin.Name(): - return CmdZPeekMin - - case CmdZRangeByScore.Name(): - return CmdZRangeByScore - - case CmdZRangeByRank.Name(): - return CmdZRangeByRank - - case CmdZRem.Name(): - return CmdZRem - - case CmdZRemRangeByRank.Name(): - return CmdZRemRangeByRank - - case CmdZRank.Name(): - return CmdZRank - - case CmdZRevRank.Name(): - return CmdZRevRank - - case CmdZScore.Name(): - return CmdZScore - - case CmdZGetByKey.Name(): - return CmdZGetByKey - - default: - return CmdUnknown - } -} - -// nolint #funlen -func (c CmdCode) Name() string { - switch c { - case CmdPut: - return "Put" - - case CmdPutWithTimestamp: - return "PutWithTimestamp" - - case CmdGet: - return "Get" - - case CmdGetAll: - return "GetAll" - - case CmdRangeScan: - return "RangeScan" - - case CmdPrefixScan: - return "PrefixScan" - - case CmdPrefixSearchScan: - return "PrefixSearchScan" - - case CmdDelete: - return "Delete" - - case CmdFindTxIDOnDisk: - return "FindTxIDOnDisk" - - case CmdFindOnDisk: - return "FindOnDisk" - - case CmdFindLeafOnDisk: - return "FindLeafOnDisk" - - case CmdSAdd: - return "SAdd" - - case CmdSRem: - return "SRem" - - case CmdSAreMembers: - return "SAreMembers" - - case CmdSIsMember: - return "SIsMember" - - case CmdSMembers: - return "SMembers" - - case CmdSHasKey: - return "SHasKey" - - case CmdSPop: - return "SPop" - - case CmdSCard: - return "SCard" - - case CmdSDiffByOneBucket: - return "SDiffByOneBucket" - - case CmdSDiffByTwoBuckets: - return "SDiffByTwoBuckets" - - case CmdSMoveByOneBucket: - return "SMoveByOneBucket" - - case CmdSMoveByTwoBuckets: - return "SMoveByTwoBuckets" - - case CmdSUnionByOneBucket: - return "SUnionByOneBucket" - - case CmdSUnionByTwoBuckets: - return "SUnionByTwoBuckets" - - case CmdRPop: - return "RPop" - - case CmdRPeek: - return "RPeek" - - case CmdRPush: - return "RPush" - - case CmdLPush: - return "LPush" - - case CmdLPop: - return "LPop" - - case CmdLPeek: - return "LPeek" - - case CmdLSize: - return "LSize" - - case CmdLRange: - return "LRange" - - case CmdLRem: - return "LRem" - - case CmdLSet: - return "LSet" - - case CmdLTrim: - return "LTrim" - - case CmdZAdd: - return "ZAdd" - - case CmdZMembers: - return "ZMembers" - - case CmdZCard: - return "ZCard" - - case CmdZCount: - return "ZCount" - - case CmdZPopMax: - return "ZPopMax" - - case CmdZPopMin: - return "ZPopMin" - - case CmdZPeekMax: - return "ZPeekMax" - - case CmdZPeekMin: - return "ZPeekMin" - - case CmdZRangeByScore: - return "ZRangeByScore" - - case CmdZRangeByRank: - return "ZRangeByRank" - - case CmdZRem: - return "ZRem" - - case CmdZRemRangeByRank: - return "ZRemRangeByRank" - - case CmdZRank: - return "ZRank" - - case CmdZRevRank: - return "ZRevRank" - - case CmdZScore: - return "ZScore" - - case CmdZGetByKey: - return "ZGetByKey" - - default: - return "" - } -} - -// nolint #funlen -func (c CmdCode) Desc() string { - switch c { - case CmdPut: - return "Sets the value for a key in the bucket." - - case CmdPutWithTimestamp: - return "Sets the value for a key in the bucket but allow capabilities to custom the timestamp for ttl" - - case CmdGet: - return "Retrieves the value for a key in the bucket" - - case CmdGetAll: - return "Returns all keys and values of the bucket stored at given bucket" - - case CmdRangeScan: - return "Query a range at given bucket, start and end slice." - - case CmdPrefixScan: - return "Iterates over a key prefix at given bucket, prefix and limitNum. LimitNum will limit the number of entries return." - - case CmdPrefixSearchScan: - return "Iterates over a key prefix at given bucket, prefix, match regular expression and limitNum. LimitNum will limit the number of entries return." - - case CmdDelete: - return "Removes a key from the bucket at given bucket and key." - - case CmdFindTxIDOnDisk: - return "Returns if txId on disk at given fid and txID." - - case CmdFindOnDisk: - return "Returns entry on disk at given fID, rootOff and key." - - case CmdFindLeafOnDisk: - return "Returns binary leaf node on disk at given fId, rootOff and key." - - case CmdSAdd: - return "Adds the specified members to the set stored int the bucket at given bucket,key and items." - - case CmdSRem: - return "Removes the specified members from the set stored int the bucket at given bucket,key and items." - - case CmdSAreMembers: - return "Returns if the specified members are the member of the set int the bucket at given bucket,key and items." - - case CmdSIsMember: - return "Returns if member is a member of the set stored int the bucket at given bucket,key and item." - - case CmdSMembers: - return "Returns all the members of the set value stored int the bucket at given bucket and key." - - case CmdSHasKey: - return "Returns if the set in the bucket at given bucket and key." - - case CmdSPop: - return "Removes and returns one or more random elements from the set value store in the bucket at given bucket and key." - - case CmdSCard: - return "Returns the set cardinality (number of elements) of the set stored in the bucket at given bucket and key." - - case CmdSDiffByOneBucket: - return "Returns the members of the set resulting from the difference between the first set and all the successive sets in one bucket." - - case CmdSDiffByTwoBuckets: - return "Returns the members of the set resulting from the difference between the first set and all the successive sets in two buckets." - - case CmdSMoveByOneBucket: - return "Moves member from the set at source to the set at destination in one bucket." - - case CmdSMoveByTwoBuckets: - return "Moves member from the set at source to the set at destination in two buckets." - - case CmdSUnionByOneBucket: - return "The members of the set resulting from the union of all the given sets in one bucket." - - case CmdSUnionByTwoBuckets: - return "The members of the set resulting from the union of all the given sets in two buckets." - - case CmdRPop: - return "Removes and returns the last element of the list stored in the bucket at given bucket and key." - - case CmdRPeek: - return "Returns the last element of the list stored in the bucket at given bucket and key." - - case CmdRPush: - return "Inserts the values at the tail of the list stored in the bucket at given bucket,key and values." - - case CmdLPush: - return "Inserts the values at the head of the list stored in the bucket at given bucket,key and values." - - case CmdLPop: - return "Removes and returns the first element of the list stored in the bucket at given bucket and key." - - case CmdLPeek: - return "Returns the first element of the list stored in the bucket at given bucket and key." - - case CmdLSize: - return "Returns the size of key in the bucket in the bucket at given bucket and key." - - case CmdLRange: - return "Returns the specified elements of the list stored in the bucket at given bucket,key, start and end. \n" + - "The offsets start and stop are zero-based indexes 0 being the first element of the list (the head of the list), 1 being the next element and so on. \n" + - "Start and end can also be negative numbers indicating offsets from the end of the list, where -1 is the last element of the list, -2 the penultimate element and so on." - - case CmdLRem: - return "Removes the first count occurrences of elements equal to value from the list stored in the bucket at given bucket,key,count. \n" + - "The count argument influences the operation in the following ways: \n" + - "count > 0: Remove elements equal to value moving from head to tail. \n" + - "count < 0: Remove elements equal to value moving from tail to head. \n" + - "count = 0: Remove all elements equal to value." - - case CmdLSet: - return "Sets the list element at index to value." - - case CmdLTrim: - return "Trims an existing list so that it will contain only the specified range of elements specified. \n" + - "The offsets start and stop are zero-based indexes 0 being the first element of the list (the head of the list), 1 being the next element and so on. \n" + - "Start and end can also be negative numbers indicating offsets from the end of the list, where -1 is the last element of the list, -2 the penultimate element and so on." - - case CmdZAdd: - return "Adds the specified member key with the specified score and specified val to the sorted set stored at bucket." - - case CmdZMembers: - return "Returns all the members of the set value stored at bucket." - - case CmdZCard: - return "Returns the sorted set cardinality (number of elements) of the sorted set stored at bucket." - - case CmdZCount: - return "Returns the number of elements in the sorted set at bucket with a score between min and max and opts. \n" + - "Options includes the following parameters: \n" + - "Limit: (int) the max nodes to return. \n" + - "ExcludeStart: (bool) exclude start value, so it search in interval (start, end] or (start, end). \n" + - "ExcludeEnd: (bool) exclude end value, so it search in interval [start, end) or (start, end)." - - case CmdZPopMax: - return "Removes and returns the member with the highest score in the sorted set stored at bucket." - - case CmdZPopMin: - return "Removes and returns the member with the lowest score in the sorted set stored at bucket." - - case CmdZPeekMax: - return "Returns the member with the highest score in the sorted set stored at bucket." - - case CmdZPeekMin: - return "Returns the member with the lowest score in the sorted set stored at bucket." - - case CmdZRangeByScore: - return "Returns all the elements in the sorted set at bucket with a score between min and max." - - case CmdZRangeByRank: - return "Returns all the elements in the sorted set in one bucket and key with a rank between start and end (including elements with rank equal to start or end)." - - case CmdZRem: - return "Removes the specified members from the sorted set stored in one bucket at given bucket and key." - - case CmdZRemRangeByRank: - return "Removes all elements in the sorted set stored in one bucket at given bucket with rank between start and end. \n" + - "The rank is 1-based integer. Rank 1 means the first node; Rank -1 means the last node." - - case CmdZRank: - return "Returns the rank of member in the sorted set stored in the bucket at given bucket and key, with the scores ordered from low to high." - - case CmdZRevRank: - return "Returns the rank of member in the sorted set stored in the bucket at given bucket and key, with the scores ordered from high to low." - - case CmdZScore: - return "Returns the score of member in the sorted set in the bucket at given bucket and key." - - case CmdZGetByKey: - return "Returns node in the bucket at given bucket and key." - - default: - return "" - } -} - -// nolint #funlen -func (c CmdCode) Usage() string { - switch c { - case CmdPut: - return c.Name() + " " - - case CmdPutWithTimestamp: - return "Sets the value for a key in the bucket but allow capabilities to custom the timestamp for ttl" - - case CmdGet: - return "Retrieves the value for a key in the bucket" - - case CmdGetAll: - return "Returns all keys and values of the bucket stored at given bucket" - - case CmdRangeScan: - return "Query a range at given bucket, start and end slice." - - case CmdPrefixScan: - return "Iterates over a key prefix at given bucket, prefix and limitNum. LimitNum will limit the number of entries return." - - case CmdPrefixSearchScan: - return "Iterates over a key prefix at given bucket, prefix, match regular expression and limitNum. LimitNum will limit the number of entries return." - - case CmdDelete: - return "Removes a key from the bucket at given bucket and key." - - case CmdFindTxIDOnDisk: - return "Returns if txId on disk at given fid and txID." - - case CmdFindOnDisk: - return "Returns entry on disk at given fID, rootOff and key." - - case CmdFindLeafOnDisk: - return "Returns binary leaf node on disk at given fId, rootOff and key." - - case CmdSAdd: - return "Adds the specified members to the set stored int the bucket at given bucket,key and items." - - case CmdSRem: - return "Removes the specified members from the set stored int the bucket at given bucket,key and items." - - case CmdSAreMembers: - return "Returns if the specified members are the member of the set int the bucket at given bucket,key and items." - - case CmdSIsMember: - return "Returns if member is a member of the set stored int the bucket at given bucket,key and item." - - case CmdSMembers: - return "Returns all the members of the set value stored int the bucket at given bucket and key." - - case CmdSHasKey: - return "Returns if the set in the bucket at given bucket and key." - - case CmdSPop: - return "Removes and returns one or more random elements from the set value store in the bucket at given bucket and key." - - case CmdSCard: - return "Returns the set cardinality (number of elements) of the set stored in the bucket at given bucket and key." - - case CmdSDiffByOneBucket: - return "Returns the members of the set resulting from the difference between the first set and all the successive sets in one bucket." - - case CmdSDiffByTwoBuckets: - return "Returns the members of the set resulting from the difference between the first set and all the successive sets in two buckets." - - case CmdSMoveByOneBucket: - return "Moves member from the set at source to the set at destination in one bucket." - - case CmdSMoveByTwoBuckets: - return "Moves member from the set at source to the set at destination in two buckets." - - case CmdSUnionByOneBucket: - return "The members of the set resulting from the union of all the given sets in one bucket." - - case CmdSUnionByTwoBuckets: - return "The members of the set resulting from the union of all the given sets in two buckets." - - case CmdRPop: - return "Removes and returns the last element of the list stored in the bucket at given bucket and key." - - case CmdRPeek: - return "Returns the last element of the list stored in the bucket at given bucket and key." - - case CmdRPush: - return "Inserts the values at the tail of the list stored in the bucket at given bucket,key and values." - - case CmdLPush: - return "Inserts the values at the head of the list stored in the bucket at given bucket,key and values." - - case CmdLPop: - return "Removes and returns the first element of the list stored in the bucket at given bucket and key." - - case CmdLPeek: - return "Returns the first element of the list stored in the bucket at given bucket and key." - - case CmdLSize: - return "Returns the size of key in the bucket in the bucket at given bucket and key." - - case CmdLRange: - return "Returns the specified elements of the list stored in the bucket at given bucket,key, start and end. \n" + - "The offsets start and stop are zero-based indexes 0 being the first element of the list (the head of the list), 1 being the next element and so on. \n" + - "Start and end can also be negative numbers indicating offsets from the end of the list, where -1 is the last element of the list, -2 the penultimate element and so on." - - case CmdLRem: - return "Removes the first count occurrences of elements equal to value from the list stored in the bucket at given bucket,key,count. \n" + - "The count argument influences the operation in the following ways: \n" + - "count > 0: Remove elements equal to value moving from head to tail. \n" + - "count < 0: Remove elements equal to value moving from tail to head. \n" + - "count = 0: Remove all elements equal to value." - - case CmdLSet: - return "Sets the list element at index to value." - - case CmdLTrim: - return "Trims an existing list so that it will contain only the specified range of elements specified. \n" + - "The offsets start and stop are zero-based indexes 0 being the first element of the list (the head of the list), 1 being the next element and so on. \n" + - "Start and end can also be negative numbers indicating offsets from the end of the list, where -1 is the last element of the list, -2 the penultimate element and so on." - - case CmdZAdd: - return "Adds the specified member key with the specified score and specified val to the sorted set stored at bucket." - - case CmdZMembers: - return "Returns all the members of the set value stored at bucket." - - case CmdZCard: - return "Returns the sorted set cardinality (number of elements) of the sorted set stored at bucket." - - case CmdZCount: - return "Returns the number of elements in the sorted set at bucket with a score between min and max and opts. \n" + - "Options includes the following parameters: \n" + - "Limit: (int) the max nodes to return. \n" + - "ExcludeStart: (bool) exclude start value, so it search in interval (start, end] or (start, end). \n" + - "ExcludeEnd: (bool) exclude end value, so it search in interval [start, end) or (start, end)." - - case CmdZPopMax: - return "Removes and returns the member with the highest score in the sorted set stored at bucket." - - case CmdZPopMin: - return "Removes and returns the member with the lowest score in the sorted set stored at bucket." - - case CmdZPeekMax: - return "Returns the member with the highest score in the sorted set stored at bucket." - - case CmdZPeekMin: - return "Returns the member with the lowest score in the sorted set stored at bucket." - - case CmdZRangeByScore: - return "Returns all the elements in the sorted set at bucket with a score between min and max." - - case CmdZRangeByRank: - return "Returns all the elements in the sorted set in one bucket and key with a rank between start and end (including elements with rank equal to start or end)." - - case CmdZRem: - return "Removes the specified members from the sorted set stored in one bucket at given bucket and key." - - case CmdZRemRangeByRank: - return "Removes all elements in the sorted set stored in one bucket at given bucket with rank between start and end. \n" + - "The rank is 1-based integer. Rank 1 means the first node; Rank -1 means the last node." - - case CmdZRank: - return "Returns the rank of member in the sorted set stored in the bucket at given bucket and key, with the scores ordered from low to high." - - case CmdZRevRank: - return "Returns the rank of member in the sorted set stored in the bucket at given bucket and key, with the scores ordered from high to low." - - case CmdZScore: - return "Returns the score of member in the sorted set in the bucket at given bucket and key." - - case CmdZGetByKey: - return "Returns node in the bucket at given bucket and key." - - default: - return "" - } -} diff --git a/nutsdb/config.go b/nutsdb/config.go deleted file mode 100644 index 919043d..0000000 --- a/nutsdb/config.go +++ /dev/null @@ -1,112 +0,0 @@ -//go:build !386 && !arm && !mips && !mipsle -// +build !386,!arm,!mips,!mipsle - -/*********************************************************************************************************************** - * - * MIT License - * - * Copyright (c) 2021 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * - **********************************************************************************************************************/ - -package nutsdb - -import ( - "fmt" - - moncfg "github.com/nabbar/golib/monitor/types" - - libval "github.com/go-playground/validator/v10" - libclu "github.com/nabbar/golib/cluster" - liberr "github.com/nabbar/golib/errors" - "github.com/nutsdb/nutsdb" -) - -type Config struct { - DB NutsDBOptions `mapstructure:"db" json:"db" yaml:"db" toml:"db" validate:""` - Cluster libclu.Config `mapstructure:"cluster" json:"cluster" yaml:"cluster" toml:"cluster" validate:""` - Directory NutsDBFolder `mapstructure:"directories" json:"directories" yaml:"directories" toml:"directories" validate:""` - Monitor moncfg.Config `mapstructure:"monitor" json:"monitor" yaml:"monitor" toml:"monitor" validate:""` -} - -func (c Config) GetConfigFolder() NutsDBFolder { - return c.Directory -} - -func (c Config) GetConfigDB() (nutsdb.Options, liberr.Error) { - if dir, err := c.Directory.GetDirectoryData(); err != nil { - return nutsdb.Options{}, err - } else { - return c.DB.GetNutsDBOptions(dir), nil - } -} - -func (c Config) GetConfigCluster() (libclu.Config, liberr.Error) { - cfg := c.Cluster - - if dir, err := c.Directory.GetDirectoryWal(); err != nil { - return cfg, err - } else { - cfg.Node.WALDir = dir - } - - if dir, err := c.Directory.GetDirectoryHost(); err != nil { - return cfg, err - } else { - cfg.Node.NodeHostDir = dir - } - - return cfg, nil -} - -func (c Config) GetOptions() (Options, liberr.Error) { - return NewOptions(c.DB, c.Directory) -} - -func (c Config) Validate() liberr.Error { - err := ErrorValidateConfig.Error(nil) - - if er := libval.New().Struct(c); er != nil { - if e, ok := er.(*libval.InvalidValidationError); ok { - err.Add(e) - } - - for _, e := range er.(libval.ValidationErrors) { - //nolint goerr113 - err.Add(fmt.Errorf("config field '%s' is not validated by constraint '%s'", e.Namespace(), e.ActualTag())) - } - } - - if err.HasParent() { - return err - } - - return nil -} - -func (c Config) ValidateDB() liberr.Error { - return c.DB.Validate() -} - -func (c Config) ValidateCluster() liberr.Error { - return c.Cluster.Validate() -} diff --git a/nutsdb/configDb.go b/nutsdb/configDb.go deleted file mode 100644 index 9760791..0000000 --- a/nutsdb/configDb.go +++ /dev/null @@ -1,117 +0,0 @@ -//go:build !386 && !arm && !mips && !mipsle -// +build !386,!arm,!mips,!mipsle - -/*********************************************************************************************************************** - * - * MIT License - * - * Copyright (c) 2021 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * - **********************************************************************************************************************/ - -package nutsdb - -import ( - "fmt" - - libval "github.com/go-playground/validator/v10" - liberr "github.com/nabbar/golib/errors" - nutsdb "github.com/nutsdb/nutsdb" -) - -type NutsDBOptions struct { - // EntryIdxMode represents using which mode to index the entries. - EntryIdxMode nutsdb.EntryIdxMode `mapstructure:"entry_idx_mode" json:"entry_idx_mode" yaml:"entry_idx_mode" toml:"entry_idx_mode"` - - // RWMode represents the read and write mode. - // RWMode includes two options: FileIO and MMap. - // FileIO represents the read and write mode using standard I/O. - // MMap represents the read and write mode using mmap. - RWMode nutsdb.RWMode `mapstructure:"rw_mode" json:"rw_mode" yaml:"rw_mode" toml:"rw_mode"` - - // SegmentSize default value is 8 MBytes - SegmentSize int64 `mapstructure:"segment_size" json:"segment_size" yaml:"segment_size" toml:"segment_size"` - - // SyncEnable represents if call Sync() function. - // if SyncEnable is false, high write performance but potential data loss likely. - // if SyncEnable is true, slower but persistent. - SyncEnable bool `mapstructure:"sync_enable" json:"sync_enable" yaml:"sync_enable" toml:"sync_enable"` -} - -func (o NutsDBOptions) GetNutsDBOptions(dataDir string) nutsdb.Options { - d := nutsdb.DefaultOptions - - if len(dataDir) < 1 { - d.RWMode = nutsdb.MMap - } else { - d.Dir = dataDir - - //nolint #exhaustive - switch o.RWMode { - case nutsdb.MMap: - d.RWMode = nutsdb.MMap - default: - d.RWMode = nutsdb.FileIO - } - } - - //nolint #exhaustive - switch o.EntryIdxMode { - case nutsdb.HintKeyAndRAMIdxMode: - d.EntryIdxMode = nutsdb.HintKeyAndRAMIdxMode - default: - d.EntryIdxMode = nutsdb.HintKeyValAndRAMIdxMode - } - - if o.SegmentSize > 0 { - d.SegmentSize = o.SegmentSize - } - - if o.SyncEnable { - d.SyncEnable = true - } else { - d.SyncEnable = false - } - - return d -} - -func (o NutsDBOptions) Validate() liberr.Error { - err := ErrorValidateConfig.Error(nil) - - if er := libval.New().Struct(o); er != nil { - if e, ok := er.(*libval.InvalidValidationError); ok { - err.Add(e) - } - - for _, e := range er.(libval.ValidationErrors) { - //nolint goerr113 - err.Add(fmt.Errorf("config field '%s' is not validated by constraint '%s'", e.Namespace(), e.ActualTag())) - } - } - - if err.HasParent() { - return err - } - - return nil -} diff --git a/nutsdb/configFs.go b/nutsdb/configFs.go deleted file mode 100644 index 18916d3..0000000 --- a/nutsdb/configFs.go +++ /dev/null @@ -1,203 +0,0 @@ -//go:build !386 && !arm && !mips && !mipsle -// +build !386,!arm,!mips,!mipsle - -/*********************************************************************************************************************** - * - * MIT License - * - * Copyright (c) 2021 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * - **********************************************************************************************************************/ - -package nutsdb - -import ( - "errors" - "fmt" - "os" - "path/filepath" - - libval "github.com/go-playground/validator/v10" - liberr "github.com/nabbar/golib/errors" -) - -const ( - _DefaultFolderData = "data" - _DefaultFolderBackup = "backup" - _DefaultFolderWal = "wal" - _DefaultFolderHost = "host" -) - -type NutsDBFolder struct { - // Working represents the main working folder witch will include sub directories : data, backup, temp... - // If the base directory is empty, all the sub directory will be absolute directories. - Base string `mapstructure:"base" json:"base" yaml:"base" toml:"base" validate:"dir,required"` - - // Data represents the sub-dir for the opening database. - // By default, it will use `data` as sub folder. - Data string `mapstructure:"sub_data" json:"sub_data" yaml:"sub_data" toml:"sub_data" validate:"printascii,required"` - - // Backup represents the sub-dir with all backup sub-folder. - // By default, it will use `backup` as sub folder. - Backup string `mapstructure:"sub_backup" json:"sub_backup" yaml:"sub_backup" toml:"sub_backup" validate:"printascii,required"` - - // Temp represents the sub-dir for temporary file/dir. - // By default, it will use the system temporary folder. - Temp string `mapstructure:"sub_temp" json:"sub_temp" yaml:"sub_temp" toml:"sub_temp" validate:"printascii,required"` - - // WalDir represents the sub-dir for cluster negociation. - // By default, it will use `wal` as sub folder. - WalDir string `mapstructure:"wal_dir" json:"wal_dir" yaml:"wal_dir" toml:"wal_dir" validate:"printascii,required"` - - // HostDir represents the sub-dir for cluster storage. - // By default, it will use `host` as sub folder. - HostDir string `mapstructure:"host_dir" json:"host_dir" yaml:"host_dir" toml:"host_dir" validate:"printascii,required"` - - // LimitNumberBackup represents how many backup will be keep. - LimitNumberBackup uint8 `mapstructure:"limit_number_backup" json:"limit_number_backup" yaml:"limit_number_backup" toml:"limit_number_backup"` - - // Permission represents the permission apply to folder created. - // By default, it will use `0755` as permission. - Permission os.FileMode `mapstructure:"permission" json:"permission" yaml:"permission" toml:"permission"` -} - -func (f NutsDBFolder) Validate() liberr.Error { - err := ErrorValidateConfig.Error(nil) - - if er := libval.New().Struct(f); er != nil { - if e, ok := er.(*libval.InvalidValidationError); ok { - err.Add(e) - } - - for _, e := range er.(libval.ValidationErrors) { - //nolint goerr113 - err.Add(fmt.Errorf("config field '%s' is not validated by constraint '%s'", e.Namespace(), e.ActualTag())) - } - } - - if err.HasParent() { - return err - } - - return nil -} - -func (f NutsDBFolder) getDirectory(base, dir string) (string, liberr.Error) { - if f.Permission == 0 { - f.Permission = 0770 - } - - var ( - abs string - err error - ) - - if len(dir) < 1 { - return "", nil - } - - if len(base) > 0 { - dir = filepath.Join(base, dir) - } - - if abs, err = filepath.Abs(dir); err != nil { - return "", ErrorFolderCheck.Error(err) - } - - if f.Permission == 0 { - f.Permission = 0755 - } - - if _, err = os.Stat(abs); err != nil && !errors.Is(err, os.ErrNotExist) { - return "", ErrorFolderCheck.Error(err) - } else if err != nil { - if err = os.MkdirAll(abs, f.Permission); err != nil { - return "", ErrorFolderCreate.Error(err) - } - } - - return abs, nil -} - -func (f NutsDBFolder) GetDirectoryBase() (string, liberr.Error) { - return f.getDirectory("", f.Base) -} - -func (f NutsDBFolder) GetDirectoryData() (string, liberr.Error) { - if base, err := f.GetDirectoryBase(); err != nil { - return "", err - } else if fs, err := f.getDirectory(base, f.Data); err != nil { - return "", err - } else if fs == "" { - return f.getDirectory(base, _DefaultFolderData) - } else { - return fs, nil - } -} - -func (f NutsDBFolder) GetDirectoryBackup() (string, liberr.Error) { - if base, err := f.GetDirectoryBase(); err != nil { - return "", err - } else if fs, err := f.getDirectory(base, f.Backup); err != nil { - return "", err - } else if fs == "" { - return f.getDirectory(base, _DefaultFolderBackup) - } else { - return fs, nil - } -} - -func (f NutsDBFolder) GetDirectoryWal() (string, liberr.Error) { - if base, err := f.GetDirectoryBase(); err != nil { - return "", err - } else if fs, err := f.getDirectory(base, f.WalDir); err != nil { - return "", err - } else if fs == "" { - return f.getDirectory(base, _DefaultFolderWal) - } else { - return fs, nil - } -} - -func (f NutsDBFolder) GetDirectoryHost() (string, liberr.Error) { - if base, err := f.GetDirectoryBase(); err != nil { - return "", err - } else if fs, err := f.getDirectory(base, f.HostDir); err != nil { - return "", err - } else if fs == "" { - return f.getDirectory(base, _DefaultFolderHost) - } else { - return fs, nil - } -} - -func (f NutsDBFolder) GetDirectoryTemp() (string, liberr.Error) { - if base, err := f.GetDirectoryBase(); err != nil { - return "", err - } else if fs, err := f.getDirectory(base, f.Temp); err != nil { - return "", err - } else if fs == "" { - return f.getDirectory("", os.TempDir()) - } else { - return fs, nil - } -} diff --git a/nutsdb/entryKv.go b/nutsdb/entryKv.go deleted file mode 100644 index e5a81e0..0000000 --- a/nutsdb/entryKv.go +++ /dev/null @@ -1,279 +0,0 @@ -//go:build !386 && !arm && !mips && !mipsle -// +build !386,!arm,!mips,!mipsle - -/*********************************************************************************************************************** - * - * MIT License - * - * Copyright (c) 2021 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * - **********************************************************************************************************************/ - -package nutsdb - -import ( - "context" - "fmt" - "reflect" - "runtime" - "strings" - - "github.com/fxamacker/cbor/v2" - liberr "github.com/nabbar/golib/errors" - liblog "github.com/nabbar/golib/logger" - loglvl "github.com/nabbar/golib/logger/level" - "github.com/nutsdb/nutsdb" -) - -const ( - _MinSkipCaller = 2 -) - -type CommandRequest struct { - l liblog.FuncLog - Cmd CmdCode `mapstructure:"cmd" json:"cmd" yaml:"cmd" toml:"cmd" cbor:"cmd"` - Params []interface{} `mapstructure:"params" json:"params" yaml:"params" toml:"params" cbor:"params"` -} - -type CommandResponse struct { - Error error `mapstructure:"error" json:"error" yaml:"error" toml:"error" cbor:"error"` - Value []interface{} `mapstructure:"value" json:"value" yaml:"value" toml:"value" cbor:"value"` -} - -func NewCommand() *CommandRequest { - return &CommandRequest{ - Cmd: CmdUnknown, - Params: make([]interface{}, 0), - } -} - -func NewCommandByDecode(l liblog.FuncLog, p []byte) (*CommandRequest, liberr.Error) { - d := NewCommand() - - if e := cbor.Unmarshal(p, d); e != nil { - return nil, ErrorCommandUnmarshal.Error(e) - } - - d.SetLogger(l) - - return d, nil -} - -func NewCommandByCaller(params ...interface{}) *CommandRequest { - pc := make([]uintptr, 10) // at least 1 entry needed - runtime.Callers(_MinSkipCaller, pc) - f := runtime.FuncForPC(pc[0]) - - d := NewCommand() - fn := strings.Split(f.Name(), ".") - d.Cmd = CmdCodeFromName(fn[len(fn)-1]) - - if len(params) > 0 { - d.Params = params - } - - return d -} - -func (c *CommandRequest) SetLogger(l liblog.FuncLog) { - if l != nil { - c.l = l - } -} - -func (c *CommandRequest) GetLogger() liblog.Logger { - if c.l != nil { - return c.l() - } - - var log = liblog.New(context.Background) - - c.l = func() liblog.Logger { - return log - } - - return log -} - -func (c *CommandRequest) InitParams(num int) { - c.Params = make([]interface{}, num) -} - -func (c *CommandRequest) InitParamsCounter(num int) int { - c.InitParams(num) - return 0 -} - -func (c *CommandRequest) SetParams(num int, val interface{}) { - if num < len(c.Params) { - c.Params[num] = val - return - } - - tmp := c.Params - c.Params = make([]interface{}, len(c.Params)+1) - - if len(tmp) > 0 { - for i := 0; i < len(tmp); i++ { - c.Params[i] = tmp[i] - } - } - - c.Params[num] = val -} - -func (c *CommandRequest) SetParamsInc(num int, val interface{}) int { - c.SetParams(num, val) - num++ - return num -} - -func (c *CommandRequest) EncodeRequest() ([]byte, liberr.Error) { - if p, e := cbor.Marshal(c); e != nil { - return nil, ErrorCommandMarshal.Error(e) - } else { - return p, nil - } -} - -func (c *CommandRequest) DecodeResult(p []byte) (*CommandResponse, liberr.Error) { - res := CommandResponse{} - - if e := cbor.Unmarshal(p, &res); e != nil { - return nil, ErrorCommandResultUnmarshal.Error(e) - } else { - return &res, nil - } -} - -func (c *CommandRequest) RunLocal(tx *nutsdb.Tx) (*CommandResponse, liberr.Error) { - if tx == nil { - return nil, ErrorTransactionClosed.Error(nil) - } - - if c.Cmd == CmdUnknown { - return nil, ErrorClientCommandInvalid.Error(nil) - } - - valTx := reflect.ValueOf(tx) - mtName := c.Cmd.Name() - method := valTx.MethodByName(mtName) - nbPrm := method.Type().NumIn() - - if len(c.Params) != nbPrm { - //nolint #goerr113 - return nil, ErrorClientCommandParamsBadNumber.Error(fmt.Errorf("%s need %d parameters", c.Cmd.Name(), nbPrm)) - } - - params := make([]reflect.Value, nbPrm) - for i := 0; i < nbPrm; i++ { - v := reflect.ValueOf(c.Params[i]) - c.GetLogger().Entry(loglvl.DebugLevel, "Param %d : type %s - Val %v", i, v.Type().Name(), v.Interface()).Log() - - if v.Type().Kind() == method.Type().In(i).Kind() { - params[i] = v - continue - } - - if !v.Type().ConvertibleTo(method.Type().In(i)) { - //nolint #goerr113 - return nil, ErrorClientCommandParamsMismatching.Error(fmt.Errorf("cmd: %s", mtName), fmt.Errorf("param num: %d", i), fmt.Errorf("param type: %s, avaitting type: %s", v.Type().Kind(), method.Type().In(i).Kind())) - } - - //nolint #exhaustive - switch method.Type().In(i).Kind() { - case reflect.Bool: - params[i] = reflect.ValueOf(v.Bool()) - case reflect.Int: - params[i] = reflect.ValueOf(int(v.Int())) - case reflect.Int8: - params[i] = reflect.ValueOf(int8(v.Int())) - case reflect.Int16: - params[i] = reflect.ValueOf(int8(v.Int())) - case reflect.Int32: - params[i] = reflect.ValueOf(int16(v.Int())) - case reflect.Int64: - params[i] = reflect.ValueOf(v.Int()) - case reflect.Uintptr: - params[i] = reflect.ValueOf(v.UnsafeAddr()) - case reflect.Uint: - params[i] = reflect.ValueOf(uint(v.Uint())) - case reflect.Uint8: - params[i] = reflect.ValueOf(uint8(v.Uint())) - case reflect.Uint16: - params[i] = reflect.ValueOf(uint16(v.Uint())) - case reflect.Uint32: - params[i] = reflect.ValueOf(uint32(v.Uint())) - case reflect.Uint64: - params[i] = reflect.ValueOf(v.Uint()) - case reflect.Float32: - params[i] = reflect.ValueOf(float32(v.Float())) - case reflect.Float64: - params[i] = reflect.ValueOf(v.Float()) - case reflect.Complex64: - params[i] = reflect.ValueOf(complex64(v.Complex())) - case reflect.Complex128: - params[i] = reflect.ValueOf(v.Complex()) - case reflect.Interface: - params[i] = reflect.ValueOf(v.Interface()) - case reflect.String: - params[i] = reflect.ValueOf(v.String()) - } - - c.GetLogger().Entry(loglvl.DebugLevel, "Change Param %d : type %s to %v", i, v.Type().Name(), params[i].Type().Name()).Log() - } - - resp := method.Call(params) - ret := CommandResponse{ - Error: nil, - Value: make([]interface{}, 0), - } - - for i := 0; i < len(resp); i++ { - v := resp[i].Interface() - if e, ok := v.(error); ok { - ret.Error = e - } else { - ret.Value = append(ret.Value, v) - } - } - - if ret.Error == nil && len(ret.Value) < 1 { - return nil, nil - } - - return &ret, nil -} - -func (c *CommandRequest) Run(tx *nutsdb.Tx) ([]byte, liberr.Error) { - if c.Cmd == CmdUnknown { - return nil, ErrorClientCommandInvalid.Error(nil) - } - - if r, err := c.RunLocal(tx); err != nil { - return nil, err - } else if p, e := cbor.Marshal(r); e != nil { - return nil, ErrorCommandResultMarshal.Error(e) - } else { - return p, nil - } -} diff --git a/nutsdb/errors.go b/nutsdb/errors.go deleted file mode 100644 index e66659d..0000000 --- a/nutsdb/errors.go +++ /dev/null @@ -1,164 +0,0 @@ -//go:build !386 && !arm && !mips && !mipsle -// +build !386,!arm,!mips,!mipsle - -/*********************************************************************************************************************** - * - * MIT License - * - * Copyright (c) 2021 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * - **********************************************************************************************************************/ - -package nutsdb - -import ( - "fmt" - - liberr "github.com/nabbar/golib/errors" -) - -const pkgName = "golib/nutsdb" - -const ( - ErrorParamEmpty liberr.CodeError = iota + liberr.MinPkgNutsDB - ErrorParamMissing - ErrorParamMismatching - ErrorParamInvalid - ErrorParamInvalidNumber - ErrorValidateConfig - ErrorValidateNutsDB - ErrorClusterInit - ErrorFileTemp - ErrorFolderCheck - ErrorFolderCreate - ErrorFolderCopy - ErrorFolderDelete - ErrorFolderExtract - ErrorFolderArchive - ErrorFolderCompress - ErrorDatabaseClosed - ErrorDatabaseKeyInvalid - ErrorDatabaseBackup - ErrorDatabaseSnapshot - ErrorTransactionInit - ErrorTransactionClosed - ErrorTransactionCommit - ErrorTransactionPutKey - ErrorCommandInvalid - ErrorCommandUnmarshal - ErrorCommandMarshal - ErrorCommandResultUnmarshal - ErrorCommandResultMarshal - ErrorLogEntryAdd - ErrorClientCommandInvalid - ErrorClientCommandParamsBadNumber - ErrorClientCommandParamsMismatching - ErrorClientCommandCall - ErrorClientCommandCommit - ErrorClientCommandResponseInvalid -) - -func init() { - if liberr.ExistInMapMessage(ErrorParamEmpty) { - panic(fmt.Errorf("error code collision %s", pkgName)) - } - liberr.RegisterIdFctMessage(ErrorParamEmpty, getMessage) -} - -func getMessage(code liberr.CodeError) (message string) { - switch code { - case liberr.UnknownError: - return liberr.NullMessage - case ErrorParamEmpty: - return "at least one given parameter is empty" - case ErrorParamMissing: - return "at least one given parameter is missing" - case ErrorParamMismatching: - return "at least one given parameter does not match the awaiting type" - case ErrorParamInvalid: - return "at least one given parameter is invalid" - case ErrorParamInvalidNumber: - return "the number of parameters is not matching the awaiting number" - case ErrorValidateConfig: - return "config seems to be invalid" - case ErrorValidateNutsDB: - return "database config seems to be invalid" - case ErrorClusterInit: - return "cannot start or join cluster" - case ErrorFileTemp: - return "error while trying to create new temp file" - case ErrorFolderCheck: - return "error while trying to check or stat folder" - case ErrorFolderCreate: - return "error while trying to create folder" - case ErrorFolderCopy: - return "error while trying to copy folder" - case ErrorFolderArchive: - return "error while trying to archive folder" - case ErrorFolderCompress: - return "error while trying to compress folder" - case ErrorFolderExtract: - return "error while trying to extract snapshot archive" - case ErrorDatabaseClosed: - return "database is closed" - case ErrorDatabaseKeyInvalid: - return "database key seems to be invalid" - case ErrorDatabaseBackup: - return "error occured while trying to backup database folder" - case ErrorDatabaseSnapshot: - return "error occured while trying to backup database to cluster members" - case ErrorTransactionInit: - return "cannot initialize new transaction from database" - case ErrorTransactionClosed: - return "transaction is closed" - case ErrorTransactionCommit: - return "cannot commit transaction writable into database" - case ErrorTransactionPutKey: - return "cannot send Put command into database transaction" - case ErrorCommandInvalid: - return "given query is not a valid DB command" - case ErrorCommandUnmarshal: - return "cannot unmarshall DB command" - case ErrorCommandMarshal: - return "cannot marshall DB command" - case ErrorCommandResultUnmarshal: - return "cannot unmarshall DB command result" - case ErrorCommandResultMarshal: - return "cannot marshall DB command result" - case ErrorLogEntryAdd: - return "cannot add key/value to database" - case ErrorClientCommandInvalid: - return "invalid command" - case ErrorClientCommandParamsBadNumber: - return "invalid number of parameters for client command" - case ErrorClientCommandParamsMismatching: - return "invalid type of parameter for client command" - case ErrorClientCommandCall: - return "error occured while running client command" - case ErrorClientCommandCommit: - return "error occured while commit client command" - case ErrorClientCommandResponseInvalid: - return "response of requested client command seems to be invalid" - } - - return liberr.NullMessage -} diff --git a/nutsdb/interface.go b/nutsdb/interface.go deleted file mode 100644 index 0dd1283..0000000 --- a/nutsdb/interface.go +++ /dev/null @@ -1,78 +0,0 @@ -//go:build !386 && !arm && !mips && !mipsle -// +build !386,!arm,!mips,!mipsle - -/*********************************************************************************************************************** - * - * MIT License - * - * Copyright (c) 2021 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * - **********************************************************************************************************************/ - -package nutsdb - -import ( - "context" - "sync/atomic" - "time" - - libclu "github.com/nabbar/golib/cluster" - libctx "github.com/nabbar/golib/context" - liberr "github.com/nabbar/golib/errors" - liblog "github.com/nabbar/golib/logger" - montps "github.com/nabbar/golib/monitor/types" - shlcmd "github.com/nabbar/golib/shell/command" - libver "github.com/nabbar/golib/version" -) - -const LogLib = "NutsDB" - -type NutsDB interface { - Listen() liberr.Error - Restart() liberr.Error - Shutdown() liberr.Error - - ForceRestart() - ForceShutdown() - - IsRunning() bool - IsReady(ctx context.Context) bool - IsReadyTimeout(parent context.Context, dur time.Duration) bool - WaitReady(ctx context.Context, tick time.Duration) - - GetLogger() liblog.Logger - SetLogger(l liblog.FuncLog) - - Monitor(ctx libctx.FuncContext, vrs libver.Version) (montps.Monitor, error) - - Cluster() libclu.Cluster - Client(ctx context.Context, tickSync time.Duration) Client - ShellCommand(ctx func() context.Context, tickSync time.Duration) []shlcmd.Command -} - -func New(c Config) NutsDB { - return &ndb{ - c: c, - t: new(atomic.Value), - r: new(atomic.Value), - } -} diff --git a/nutsdb/model.go b/nutsdb/model.go deleted file mode 100644 index 51623bc..0000000 --- a/nutsdb/model.go +++ /dev/null @@ -1,352 +0,0 @@ -//go:build !386 && !arm && !mips && !mipsle -// +build !386,!arm,!mips,!mipsle - -/*********************************************************************************************************************** - * - * MIT License - * - * Copyright (c) 2021 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * - **********************************************************************************************************************/ - -package nutsdb - -import ( - "context" - "sync" - "sync/atomic" - "time" - - dgbstm "github.com/lni/dragonboat/v3/statemachine" - libclu "github.com/nabbar/golib/cluster" - liberr "github.com/nabbar/golib/errors" - liblog "github.com/nabbar/golib/logger" - shlcmd "github.com/nabbar/golib/shell/command" -) - -type ndb struct { - m sync.Mutex - c Config - l liblog.FuncLog - e liberr.Error - t *atomic.Value // cluster - r *atomic.Value // status -} - -func (n *ndb) createNodeMachine(node uint64, cluster uint64) dgbstm.IOnDiskStateMachine { - var ( - err liberr.Error - opt Options - ) - - if opt, err = n.c.GetOptions(); err != nil { - panic(err) - } - - return newNode(node, cluster, opt, n.setRunning) -} - -func (n *ndb) newCluster() liberr.Error { - var ( - clu libclu.Cluster - err liberr.Error - cfg libclu.Config - ) - - if c := n.Cluster(); c != nil { - if err = n.Shutdown(); err != nil { - return err - } - } - - if cfg, err = n.c.GetConfigCluster(); err != nil { - return err - } - - clu, err = libclu.NewCluster(cfg, nil) - - if err != nil { - return err - } - - clu.SetFctCreateSTMOnDisk(n.createNodeMachine) - n.setCluster(clu) - - return nil -} - -func (n *ndb) GetLogger() liblog.Logger { - n.m.Lock() - defer n.m.Unlock() - - if n.l != nil { - return n.l() - } - - var l = liblog.New(context.Background) - n.l = func() liblog.Logger { - return l - } - - return l -} - -func (n *ndb) SetLogger(l liblog.FuncLog) { - n.m.Lock() - defer n.m.Unlock() - - n.l = l -} - -func (n *ndb) IsRunning() bool { - n.m.Lock() - defer n.m.Unlock() - - if i := n.r.Load(); i == nil { - return false - } else if b, ok := i.(bool); !ok { - return false - } else { - return b - } -} - -func (n *ndb) setRunning(state bool) { - n.m.Lock() - defer n.m.Unlock() - - if n == nil || n.r == nil { - return - } else { - n.r.Store(state) - } -} - -func (n *ndb) IsReady(ctx context.Context) bool { - if m, e := n.Cluster().SyncGetClusterMembership(ctx); e != nil || m == nil || len(m.Nodes) < 1 { - return false - } - - if _, ok, e := n.Cluster().GetLeaderID(); e != nil || !ok { - return false - } else { - return true - } -} - -func (n *ndb) IsReadyTimeout(parent context.Context, dur time.Duration) bool { - ctx, cnl := context.WithTimeout(parent, dur) - defer cnl() - - if n.IsRunning() && n.IsReady(ctx) { - return true - } - - return false -} - -func (n *ndb) WaitReady(ctx context.Context, tick time.Duration) { - for { - if n.IsRunning() && n.IsReady(ctx) { - return - } - - time.Sleep(tick) - } -} - -func (n *ndb) Listen() liberr.Error { - var ( - c libclu.Cluster - e liberr.Error - ) - - if c = n.Cluster(); c == nil { - if e = n.newCluster(); e != nil { - n._SetError(e) - return e - } else if c = n.Cluster(); c == nil { - n._SetError(e) - return ErrorClusterInit.Error(nil) - } - } - - if e = c.ClusterStart(len(n.c.Cluster.InitMember) < 1); e != nil { - n._SetError(e) - return e - } - - n._SetError(nil) - n.setCluster(c) - - return nil -} - -func (n *ndb) Restart() liberr.Error { - return n.Listen() -} - -func (n *ndb) ForceRestart() { - n.ForceShutdown() - _ = n.Listen() -} - -func (n *ndb) Shutdown() liberr.Error { - if c := n.Cluster(); c == nil { - return nil - } else if !c.HasNodeInfo(0) { - return nil - } else if err := c.NodeStop(0); err != nil { - return err - } else { - n.setCluster(c) - return nil - } -} - -func (n *ndb) ForceShutdown() { - if err := n.Shutdown(); err == nil { - return - } else if c := n.Cluster(); c == nil { - return - } else if !c.HasNodeInfo(0) { - return - } else { - _ = c.ClusterStop(true) - n.setCluster(c) - } -} - -func (n *ndb) Cluster() libclu.Cluster { - n.m.Lock() - defer n.m.Unlock() - - if i := n.t.Load(); i == nil { - return nil - } else if c, ok := i.(libclu.Cluster); !ok { - return nil - } else { - return c - } -} - -func (n *ndb) setCluster(clu libclu.Cluster) { - n.m.Lock() - defer n.m.Unlock() - - n.t.Store(clu) -} - -func (n *ndb) Client(ctx context.Context, tickSync time.Duration) Client { - return &clientNutDB{ - x: ctx, - t: tickSync, - c: n.Cluster, - w: n.WaitReady, - } -} - -func (n *ndb) ShellCommand(ctx func() context.Context, tickSync time.Duration) []shlcmd.Command { - var ( - res = make([]shlcmd.Command, 0) - cli func() Client - ) - - cli = func() Client { - x := ctx() - - if x.Err() != nil { - return nil - } - - return n.Client(x, tickSync) - } - - res = append(res, newShellCommand(CmdPut, cli)) - res = append(res, newShellCommand(CmdPutWithTimestamp, cli)) - res = append(res, newShellCommand(CmdGet, cli)) - res = append(res, newShellCommand(CmdGetAll, cli)) - res = append(res, newShellCommand(CmdRangeScan, cli)) - res = append(res, newShellCommand(CmdPrefixScan, cli)) - res = append(res, newShellCommand(CmdPrefixSearchScan, cli)) - res = append(res, newShellCommand(CmdDelete, cli)) - res = append(res, newShellCommand(CmdFindTxIDOnDisk, cli)) - res = append(res, newShellCommand(CmdFindOnDisk, cli)) - res = append(res, newShellCommand(CmdFindLeafOnDisk, cli)) - res = append(res, newShellCommand(CmdSAdd, cli)) - res = append(res, newShellCommand(CmdSRem, cli)) - res = append(res, newShellCommand(CmdSAreMembers, cli)) - res = append(res, newShellCommand(CmdSIsMember, cli)) - res = append(res, newShellCommand(CmdSMembers, cli)) - res = append(res, newShellCommand(CmdSHasKey, cli)) - res = append(res, newShellCommand(CmdSPop, cli)) - res = append(res, newShellCommand(CmdSCard, cli)) - res = append(res, newShellCommand(CmdSDiffByOneBucket, cli)) - res = append(res, newShellCommand(CmdSDiffByTwoBuckets, cli)) - res = append(res, newShellCommand(CmdSMoveByOneBucket, cli)) - res = append(res, newShellCommand(CmdSMoveByTwoBuckets, cli)) - res = append(res, newShellCommand(CmdSUnionByOneBucket, cli)) - res = append(res, newShellCommand(CmdSUnionByTwoBuckets, cli)) - res = append(res, newShellCommand(CmdRPop, cli)) - res = append(res, newShellCommand(CmdRPeek, cli)) - res = append(res, newShellCommand(CmdRPush, cli)) - res = append(res, newShellCommand(CmdLPush, cli)) - res = append(res, newShellCommand(CmdLPop, cli)) - res = append(res, newShellCommand(CmdLPeek, cli)) - res = append(res, newShellCommand(CmdLSize, cli)) - res = append(res, newShellCommand(CmdLRange, cli)) - res = append(res, newShellCommand(CmdLRem, cli)) - res = append(res, newShellCommand(CmdLSet, cli)) - res = append(res, newShellCommand(CmdLTrim, cli)) - res = append(res, newShellCommand(CmdZAdd, cli)) - res = append(res, newShellCommand(CmdZMembers, cli)) - res = append(res, newShellCommand(CmdZCard, cli)) - res = append(res, newShellCommand(CmdZCount, cli)) - res = append(res, newShellCommand(CmdZPopMax, cli)) - res = append(res, newShellCommand(CmdZPopMin, cli)) - res = append(res, newShellCommand(CmdZPeekMax, cli)) - res = append(res, newShellCommand(CmdZPeekMin, cli)) - res = append(res, newShellCommand(CmdZRangeByScore, cli)) - res = append(res, newShellCommand(CmdZRangeByRank, cli)) - res = append(res, newShellCommand(CmdZRem, cli)) - res = append(res, newShellCommand(CmdZRemRangeByRank, cli)) - res = append(res, newShellCommand(CmdZRank, cli)) - res = append(res, newShellCommand(CmdZRevRank, cli)) - res = append(res, newShellCommand(CmdZScore, cli)) - res = append(res, newShellCommand(CmdZGetByKey, cli)) - - return res -} - -func (n *ndb) _SetError(e liberr.Error) { - n.m.Lock() - defer n.m.Unlock() - - n.e = e -} - -func (n *ndb) _GetError() liberr.Error { - n.m.Lock() - defer n.m.Unlock() - - return n.e -} diff --git a/nutsdb/monitor.go b/nutsdb/monitor.go deleted file mode 100644 index d7a16a2..0000000 --- a/nutsdb/monitor.go +++ /dev/null @@ -1,110 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2022 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * - */ - -package nutsdb - -import ( - "context" - "fmt" - "runtime" - "time" - - libctx "github.com/nabbar/golib/context" - libmon "github.com/nabbar/golib/monitor" - moninf "github.com/nabbar/golib/monitor/info" - montps "github.com/nabbar/golib/monitor/types" - libver "github.com/nabbar/golib/version" -) - -const ( - defaultNameMonitor = "NutsDB Server" -) - -func (n *ndb) HealthCheck(ctx context.Context) error { - for i := 0; i < 5; i++ { - if n.IsRunning() { - if n.IsReadyTimeout(context.Background(), time.Second) { - return nil - } - } - - time.Sleep(time.Second) - } - - if e := n._GetError(); e != nil { - return e - } - - return fmt.Errorf("node not ready") -} - -func (n *ndb) Monitor(ctx libctx.FuncContext, vrs libver.Version) (montps.Monitor, error) { - - var ( - e error - inf moninf.Info - mon montps.Monitor - cfg Config - res = make(map[string]interface{}, 0) - ) - - n.m.Lock() - cfg = n.c - n.m.Unlock() - - res["runtime"] = runtime.Version()[2:] - res["release"] = vrs.GetRelease() - res["build"] = vrs.GetBuild() - res["date"] = vrs.GetDate() - res["nodId"] = n.c.Cluster.Cluster.NodeID - - if inf, e = moninf.New(defaultNameMonitor); e != nil { - return nil, e - } else { - inf.RegisterName(func() (string, error) { - return fmt.Sprintf("%s [%s]", defaultNameMonitor, cfg.Cluster.Node.RaftAddress), nil - }) - inf.RegisterInfo(func() (map[string]interface{}, error) { - return res, nil - }) - } - - if mon, e = libmon.New(ctx, inf); e != nil { - return nil, e - } - - mon.SetHealthCheck(n.HealthCheck) - - if e = mon.SetConfig(ctx, cfg.Monitor); e != nil { - return nil, e - } - - if e = mon.Start(ctx()); e != nil { - return nil, e - } - - return mon, nil -} diff --git a/nutsdb/node.go b/nutsdb/node.go deleted file mode 100644 index 150453c..0000000 --- a/nutsdb/node.go +++ /dev/null @@ -1,427 +0,0 @@ -//go:build !386 && !arm && !mips && !mipsle -// +build !386,!arm,!mips,!mipsle - -/*********************************************************************************************************************** - * - * MIT License - * - * Copyright (c) 2021 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * - **********************************************************************************************************************/ - -package nutsdb - -import ( - "context" - "errors" - "io" - "strings" - "sync" - "sync/atomic" - - liblog "github.com/nabbar/golib/logger" - - dgbstm "github.com/lni/dragonboat/v3/statemachine" - liberr "github.com/nabbar/golib/errors" - "github.com/nutsdb/nutsdb" -) - -const ( - _RaftBucket = "_raft" - _RaftKeyAppliedIndex = "_raft_applied_index" - _WordByteTrue = 0xff -) - -func newNode(node uint64, cluster uint64, opt Options, fct func(state bool)) dgbstm.IOnDiskStateMachine { - if fct == nil { - fct = func(state bool) {} - } - - o := new(atomic.Value) - o.Store(opt) - - return &nutsNode{ - n: node, - c: cluster, - o: o, - r: fct, - d: new(atomic.Value), - } -} - -type nutsNode struct { - m sync.Mutex // mutex for struct var - n uint64 // nodeId - c uint64 // clusterId - r func(state bool) // is running - o *atomic.Value // options nutsDB - d *atomic.Value // nutsDB database pointer - l liblog.FuncLog // logger -} - -func (n *nutsNode) SetLogger(l liblog.FuncLog) { - n.m.Lock() - defer n.m.Unlock() - - if l != nil { - n.l = l - } -} - -func (n *nutsNode) GetLogger() liblog.Logger { - n.m.Lock() - defer n.m.Unlock() - - if n.l != nil { - return n.l() - } - - var l = liblog.New(context.Background) - n.l = func() liblog.Logger { - return l - } - - return l -} - -func (n *nutsNode) setRunning(state bool) { - n.m.Lock() - defer n.m.Unlock() - - if n != nil && n.r != nil { - n.r(state) - } -} - -func (n *nutsNode) newTx(writable bool) (*nutsdb.Tx, liberr.Error) { - if db := n.getDb(); db == nil { - return nil, ErrorDatabaseClosed.Error(nil) - } else if tx, e := db.Begin(writable); e != nil { - return nil, ErrorTransactionInit.Error(e) - } else { - return tx, nil - } -} - -func (n *nutsNode) getRaftLogIndexLastApplied() (idxRaftlog uint64, err error) { - var ( - tx *nutsdb.Tx - en *nutsdb.Entry - ) - - if tx, err = n.newTx(false); err != nil { - return 0, err - } - - defer func() { - _ = tx.Rollback() - }() - - if en, err = tx.Get(_RaftBucket, []byte(_RaftKeyAppliedIndex)); err != nil && errors.Is(err, nutsdb.ErrBucketNotFound) { - return 0, nil - } else if err != nil && errors.Is(err, nutsdb.ErrBucketEmpty) { - return 0, nil - } else if err != nil && errors.Is(err, nutsdb.ErrNotFoundKey) { - return 0, nil - } else if err != nil && errors.Is(err, nutsdb.ErrKeyNotFound) { - return 0, nil - } else if err != nil && errors.Is(err, nutsdb.ErrKeyEmpty) { - return 0, nil - } else if err != nil && strings.HasPrefix(err.Error(), "not found bucket") { - return 0, nil - } else if err != nil { - return 0, err - } else if en.IsZero() { - return 0, nil - } else { - return n.btoi64(en.Value), nil - } -} - -func (n *nutsNode) i64tob(val uint64) []byte { - r := make([]byte, 8) - for i := uint64(0); i < 8; i++ { - r[i] = byte((val >> (i * 8)) & _WordByteTrue) - } - return r -} - -func (n *nutsNode) btoi64(val []byte) uint64 { - r := uint64(0) - for i := uint64(0); i < 8; i++ { - r |= uint64(val[i]) << (8 * i) - } - return r -} - -func (n *nutsNode) applyRaftLogIndexLastApplied(idx uint64) error { - var ( - e error - tx *nutsdb.Tx - err liberr.Error - ) - - if tx, err = n.newTx(true); err != nil { - return err - } - - defer func() { - _ = tx.Rollback() - }() - - if e = tx.Put(_RaftBucket, []byte(_RaftKeyAppliedIndex), n.i64tob(idx), 0); e != nil { - return ErrorTransactionPutKey.Error(e) - } else if e = tx.Commit(); e != nil { - return ErrorTransactionCommit.Error(e) - } else { - return nil - } -} - -// Open @TODO : analyze channel role !! -func (n *nutsNode) Open(stopc <-chan struct{}) (idxRaftlog uint64, err error) { - var ( - opt Options - db *nutsdb.DB - ) - - if opt = n.getOptions(); opt == nil { - return 0, ErrorValidateConfig.Error(nil) - } - - if db, err = nutsdb.Open(opt.NutsDBOptions()); err != nil { - return 0, err - } else { - n.setDb(db) - n.setRunning(true) - - if idxRaftlog, err = n.getRaftLogIndexLastApplied(); err != nil { - _ = n.Close() - } - - return - } -} - -func (n *nutsNode) Close() error { - defer n.setRunning(false) - - if db := n.getDb(); db != nil { - err := db.Close() - n.setDb(db) - return err - } - - return nil -} - -func (n *nutsNode) Update(logEntry []dgbstm.Entry) ([]dgbstm.Entry, error) { - var ( - e error - - tx *nutsdb.Tx - kv *CommandRequest - - err liberr.Error - res []byte - idx int - ent dgbstm.Entry - ) - - if tx, err = n.newTx(true); err != nil { - return nil, err - } - - for idx, ent = range logEntry { - if kv, err = NewCommandByDecode(n.GetLogger, ent.Cmd); err != nil { - logEntry[idx].Result = dgbstm.Result{ - Value: 0, - Data: nil, - } - - _ = tx.Rollback() - return logEntry, err - } - - if res, err = kv.Run(tx); err != nil { - logEntry[idx].Result = dgbstm.Result{ - Value: 0, - Data: nil, - } - - _ = tx.Rollback() - return logEntry, err - } else { - logEntry[idx].Result = dgbstm.Result{ - Value: uint64(idx), - Data: res, - } - } - } - - if e = tx.Commit(); e != nil { - _ = tx.Rollback() - return logEntry, ErrorTransactionCommit.Error(e) - } - - return logEntry, n.applyRaftLogIndexLastApplied(logEntry[len(logEntry)-1].Index) -} - -func (n *nutsNode) Lookup(query interface{}) (value interface{}, err error) { - var ( - t *nutsdb.Tx - r *CommandResponse - c *CommandRequest - e liberr.Error - - ok bool - ) - - if t, e = n.newTx(true); e != nil { - return nil, e - } - - defer func() { - if t != nil { - _ = t.Rollback() - } - }() - - if c, ok = query.(*CommandRequest); !ok { - return nil, ErrorCommandInvalid.Error(nil) - } else if r, e = c.RunLocal(t); e != nil { - return nil, e - } else { - return r, nil - } -} - -func (n *nutsNode) Sync() error { - return nil -} - -func (n *nutsNode) PrepareSnapshot() (interface{}, error) { - var sh = newSnap() - - if opt := n.getOptions(); opt == nil { - return nil, ErrorValidateConfig.Error(nil) - } else if db := n.getDb(); db == nil { - sh.Finish() - return nil, ErrorDatabaseClosed.Error(nil) - } else if err := sh.Prepare(opt, db); err != nil { - sh.Finish() - return nil, ErrorDatabaseBackup.Error(err) - } else { - return sh, nil - } -} - -func (n *nutsNode) SaveSnapshot(i interface{}, writer io.Writer, c <-chan struct{}) error { - if i == nil { - return ErrorParamEmpty.Error(nil) - } else if sh, ok := snapCast(i); !ok { - return ErrorParamMismatching.Error(nil) - } else if opt := n.getOptions(); opt == nil { - return ErrorValidateConfig.Error(nil) - } else if err := sh.Save(opt, writer); err != nil { - sh.Finish() - return err - } else { - sh.Finish() - } - - return nil -} - -func (n *nutsNode) RecoverFromSnapshot(reader io.Reader, c <-chan struct{}) error { - var ( - sh = newSnap() - opt = n.getOptions() - ) - - defer sh.Finish() - - if opt == nil { - return ErrorValidateConfig.Error(nil) - } - - if err := sh.Load(opt, reader); err != nil { - return err - } - - if db := n.getDb(); db != nil { - _ = db.Close() - n.setDb(db) - } - - if err := sh.Apply(opt); err != nil { - return err - } - - //@TODO : check channel is ok.... - if _, err := n.Open(nil); err != nil { - return err - } - - return nil -} - -func (n *nutsNode) getDb() *nutsdb.DB { - n.m.Lock() - defer n.m.Unlock() - - if n.d == nil { - return nil - } else if i := n.d.Load(); i == nil { - return nil - } else if db, ok := i.(*nutsdb.DB); !ok { - return nil - } else { - return db - } -} - -func (n *nutsNode) setDb(db *nutsdb.DB) { - n.m.Lock() - defer n.m.Unlock() - - if n.d == nil { - n.d = new(atomic.Value) - } - - n.d.Store(db) -} - -func (n *nutsNode) getOptions() Options { - n.m.Lock() - defer n.m.Unlock() - - if n.o == nil { - return nil - } else if i := n.o.Load(); i == nil { - return nil - } else if opt, ok := i.(Options); !ok { - return nil - } else { - return opt - } -} diff --git a/nutsdb/options.go b/nutsdb/options.go deleted file mode 100644 index a363494..0000000 --- a/nutsdb/options.go +++ /dev/null @@ -1,210 +0,0 @@ -//go:build !386 && !arm && !mips && !mipsle -// +build !386,!arm,!mips,!mipsle - -/*********************************************************************************************************************** - * - * MIT License - * - * Copyright (c) 2021 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * - **********************************************************************************************************************/ - -package nutsdb - -import ( - "bytes" - "fmt" - "os" - "path/filepath" - "runtime" - "strconv" - "strings" - "time" - - liberr "github.com/nabbar/golib/errors" - nutsdb "github.com/nutsdb/nutsdb" - xujufs "github.com/xujiajun/utils/filesystem" -) - -type Options interface { - NutsDBOptions() nutsdb.Options - - NewBackup(db *nutsdb.DB) (string, liberr.Error) - NewBackupTemp(db *nutsdb.DB) (string, liberr.Error) - - NewTempFolder() (string, liberr.Error) - NewTempFilePattern(extension string) string - GetTempDir() string - - CleanBackup() liberr.Error - Permission() os.FileMode - - RestoreBackup(dir string) liberr.Error -} - -func NewOptions(cfgNuts NutsDBOptions, cfgFs NutsDBFolder) (Options, liberr.Error) { - if _, err := cfgFs.GetDirectoryBase(); err != nil { - return nil, err - } - - o := &options{ - limit: cfgFs.LimitNumberBackup, - perm: cfgFs.Permission, - } - - if fs, err := cfgFs.GetDirectoryData(); err != nil { - return nil, err - } else { - o.dirs.data = fs - } - - if fs, err := cfgFs.GetDirectoryBackup(); err != nil { - return nil, err - } else { - o.dirs.backup = fs - } - - if fs, err := cfgFs.GetDirectoryTemp(); err != nil { - return nil, err - } else { - o.dirs.temp = fs - } - - o.nuts = cfgNuts.GetNutsDBOptions(o.dirs.data) - - return o, nil -} - -type options struct { - nuts nutsdb.Options - dirs struct { - data string - backup string - temp string - } - limit uint8 - perm os.FileMode -} - -func (o options) NutsDBOptions() nutsdb.Options { - return o.nuts -} - -func (o options) NewBackup(db *nutsdb.DB) (string, liberr.Error) { - fld := o.getBackupDirName() - - if e := os.MkdirAll(filepath.Join(o.dirs.backup, fld), o.perm); e != nil { - return "", ErrorFolderCreate.Error(e) - } else if err := o.newBackupDir(fld, db); err != nil { - return "", err - } else { - return fld, nil - } -} - -func (o options) NewBackupTemp(db *nutsdb.DB) (string, liberr.Error) { - if fld, err := o.NewTempFolder(); err != nil { - return "", err - } else if err = o.newBackupDir(fld, db); err != nil { - return "", err - } else { - return fld, nil - } -} - -func (o options) NewTempFolder() (string, liberr.Error) { - if p, e := os.MkdirTemp(o.dirs.temp, o.getTempPrefix()); e != nil { - return "", ErrorFolderCreate.Error(e) - } else { - _ = os.Chmod(p, o.perm) - return p, nil - } -} - -func (o options) NewTempFilePattern(extension string) string { - pattern := o.getTempPrefix() + "-*" - - if extension != "" { - pattern = pattern + "." + extension - } - - return pattern -} - -func (o options) GetTempDir() string { - return o.dirs.temp -} - -func (o options) CleanBackup() liberr.Error { - panic("implement me") -} - -func (o options) Permission() os.FileMode { - return o.perm -} - -func (o options) RestoreBackup(dir string) liberr.Error { - if err := os.RemoveAll(o.dirs.data); err != nil { - return ErrorFolderDelete.Error(err) - } else if err = xujufs.CopyDir(dir, o.dirs.data); err != nil { - return ErrorFolderCopy.Error(err) - } else { - _ = os.Chmod(o.dirs.data, o.perm) - } - - return nil -} - -/// private - -func (o options) newBackupDir(dir string, db *nutsdb.DB) liberr.Error { - if err := db.Backup(dir); err != nil { - return ErrorDatabaseBackup.Error(err) - } - - return nil -} - -func (o options) getTempPrefix() string { - b := make([]byte, 64) - - b = b[:runtime.Stack(b, false)] - b = bytes.TrimPrefix(b, []byte("goroutine ")) - b = b[:bytes.IndexByte(b, ' ')] - - //nolint #nosec - /* #nosec */ - n, _ := strconv.ParseUint(string(b), 10, 64) - - return fmt.Sprintf("%d", n) -} - -func (o options) getBackupDirName() string { - part := strings.Split(time.Now().Format(time.RFC3339), "T") - dt := part[0] - - part = strings.Split(part[1], "Z") - tm := strings.Replace(part[0], ":", "-", -1) - tz := strings.Replace(part[1], ":", "", -1) - - return dt + "T" + tm + "Z" + tz -} diff --git a/nutsdb/shell.go b/nutsdb/shell.go deleted file mode 100644 index 7d632fd..0000000 --- a/nutsdb/shell.go +++ /dev/null @@ -1,152 +0,0 @@ -//go:build !386 && !arm && !mips && !mipsle -// +build !386,!arm,!mips,!mipsle - -/*********************************************************************************************************************** - * - * MIT License - * - * Copyright (c) 2021 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * - **********************************************************************************************************************/ - -package nutsdb - -import ( - "encoding/json" - "fmt" - "io" - - shlcmd "github.com/nabbar/golib/shell/command" - "github.com/nutsdb/nutsdb" -) - -type shellCommand struct { - n CmdCode - c func() Client -} - -func newShellCommand(code CmdCode, cli func() Client) shlcmd.Command { - if code == CmdUnknown { - return nil - } - - return &shellCommand{ - c: cli, - n: code, - } -} - -func (s *shellCommand) Name() string { - return s.n.Name() -} - -func (s *shellCommand) Describe() string { - return s.n.Desc() -} - -func (s *shellCommand) Run(buf io.Writer, err io.Writer, args []string) { - if s.n == CmdUnknown { - _, _ = fmt.Fprintf(err, "error: %v\n", ErrorClientCommandInvalid.Error(nil).GetError()) - } - - var cli Client - - if s.c == nil { - _, _ = fmt.Fprintf(err, "error: %v\n", ErrorClientCommandCommit.Error(nil).GetError()) - } else if cli = s.c(); cli == nil { - _, _ = fmt.Fprintf(err, "error: %v\n", ErrorClientCommandCommit.Error(nil).GetError()) - } else if r, e := cli.Run(s.n, args); e != nil { - _, _ = fmt.Fprintf(err, "error: %v\n", e) - } else if len(r.Value) < 1 { - _, _ = fmt.Fprintf(buf, "No result.\n") - } else { - for i, val := range r.Value { - if val == nil { - continue - } - s.parse(buf, err, r.Value[i]) - } - } -} - -func (s *shellCommand) json(buf, err io.Writer, val interface{}) { - if p, e := json.MarshalIndent(val, "", " "); e != nil { - _, _ = fmt.Fprintf(err, "error: %v\n", e) - } else { - _, _ = buf.Write(p) - } -} - -func (s *shellCommand) parse(buf, err io.Writer, val interface{}) { - if values, ok := val.(*nutsdb.Entries); ok { - for _, v := range *values { - _, _ = fmt.Fprintf(buf, "Key: %s\n", string(v.Key)) - _, _ = fmt.Fprintf(buf, "Val: %s\n", string(v.Value)) - _, _ = fmt.Fprintf(buf, "\n") - } - return - } - - if values, ok := val.(nutsdb.Entries); ok { - for _, v := range values { - _, _ = fmt.Fprintf(buf, "Key: %s\n", string(v.Key)) - _, _ = fmt.Fprintf(buf, "Val: %s\n", string(v.Value)) - _, _ = fmt.Fprintf(buf, "\n") - } - return - } - - if values, ok := val.(*nutsdb.Entry); ok { - _, _ = fmt.Fprintf(buf, "Key: %s\n", string(values.Key)) - _, _ = fmt.Fprintf(buf, "Val: %s\n", string(values.Value)) - _, _ = fmt.Fprintf(buf, "\n") - return - } - - if values, ok := val.(nutsdb.Entry); ok { - _, _ = fmt.Fprintf(buf, "Key: %s\n", string(values.Key)) - _, _ = fmt.Fprintf(buf, "Val: %s\n", string(values.Value)) - _, _ = fmt.Fprintf(buf, "\n") - return - } - - if values, ok := val.(map[string]*nutsdb.SortedSetMember); ok { - for _, v := range values { - _, _ = fmt.Fprintf(buf, "Val: %s\n", string(v.Value)) - _, _ = fmt.Fprintf(buf, "Score: %v\n", v.Score) - _, _ = fmt.Fprintf(buf, "\n") - } - return - } - - if values, ok := val.([]*nutsdb.SortedSetMember); ok { - for _, v := range values { - _, _ = fmt.Fprintf(buf, "Val: %s\n", string(v.Value)) - _, _ = fmt.Fprintf(buf, "Score: %v\n", v.Score) - _, _ = fmt.Fprintf(buf, "\n") - } - return - } - - s.json(buf, err, val) - return -} diff --git a/nutsdb/snap.go b/nutsdb/snap.go deleted file mode 100644 index a1d6c9e..0000000 --- a/nutsdb/snap.go +++ /dev/null @@ -1,148 +0,0 @@ -//go:build !386 && !arm && !mips && !mipsle -// +build !386,!arm,!mips,!mipsle - -/*********************************************************************************************************************** - * - * MIT License - * - * Copyright (c) 2021 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * - **********************************************************************************************************************/ - -package nutsdb - -import ( - "io" - "os" - "strings" - - arcarc "github.com/nabbar/golib/archive/archive" - arctps "github.com/nabbar/golib/archive/archive/types" - - libarc "github.com/nabbar/golib/archive" - arccmp "github.com/nabbar/golib/archive/compress" - liberr "github.com/nabbar/golib/errors" - "github.com/nutsdb/nutsdb" -) - -type Snapshot interface { - Prepare(opt Options, db *nutsdb.DB) liberr.Error - - Save(opt Options, writer io.Writer) liberr.Error - Load(opt Options, reader io.Reader) liberr.Error - - Apply(opt Options) liberr.Error - - Finish() -} - -func newSnap() Snapshot { - return &snap{} -} - -func snapCast(i interface{}) (Snapshot, bool) { - if sp, ok := i.(*snap); ok { - return sp, true - } else if ss, ok := i.(snap); ok { - return &ss, true - } else if si, ok := i.(Snapshot); ok { - return si, true - } else { - return nil, false - } -} - -type snap struct { - path string -} - -func (s *snap) Prepare(opt Options, db *nutsdb.DB) liberr.Error { - if dir, err := opt.NewBackupTemp(db); err != nil { - return err - } else { - s.path = dir - } - - return nil -} - -func (s *snap) Save(opt Options, writer io.Writer) liberr.Error { - var ( - e error - g io.WriteCloser - t arctps.Writer - f = func(str string) string { - return strings.TrimPrefix(str, s.path) - } - ) - - defer func() { - if t != nil { - _ = t.Close() - } - if g != nil { - _ = g.Close() - } - }() - - if g, e = arccmp.Gzip.Writer(libarc.NopWriteCloser(writer)); e != nil { - return ErrorDatabaseSnapshot.Error(e) - } else if t, e = arcarc.Tar.Writer(g); e != nil { - return ErrorDatabaseSnapshot.Error(e) - } else if e = t.FromPath(s.path, "", f); e != nil { - return ErrorDatabaseSnapshot.Error(e) - } - - return nil -} - -func (s *snap) Load(opt Options, reader io.Reader) liberr.Error { - var ( - e error - d string - ) - - defer func() { - }() - - if d, e = opt.NewTempFolder(); e != nil { - return ErrorDatabaseSnapshot.Error(e) - } else if e = libarc.ExtractAll(io.NopCloser(reader), "unknown", d); e != nil { - return ErrorDatabaseSnapshot.Error(e) - } else { - s.path = d - } - - return nil -} - -func (s *snap) Apply(opt Options) liberr.Error { - if e := opt.RestoreBackup(s.path); e != nil { - return ErrorDatabaseSnapshot.Error(e) - } - - return nil -} - -func (s *snap) Finish() { - _ = os.RemoveAll(s.path) -} diff --git a/static/index.go b/static/index.go index dcae187..bbda3f8 100644 --- a/static/index.go +++ b/static/index.go @@ -27,7 +27,7 @@ package static import ( - "golang.org/x/exp/slices" + "slices" ) func (s *staticHandler) SetIndex(group, route, pathFile string) { diff --git a/status/listmandatory/model.go b/status/listmandatory/model.go index 1b871c5..d1b9c9b 100644 --- a/status/listmandatory/model.go +++ b/status/listmandatory/model.go @@ -27,13 +27,13 @@ package listmandatory import ( + "slices" "sort" "sync" "sync/atomic" stsctr "github.com/nabbar/golib/status/control" stsmdt "github.com/nabbar/golib/status/mandatory" - "golang.org/x/exp/slices" ) type model struct { diff --git a/status/mandatory/model.go b/status/mandatory/model.go index 8437187..493744c 100644 --- a/status/mandatory/model.go +++ b/status/mandatory/model.go @@ -27,10 +27,10 @@ package mandatory import ( + "slices" "sync/atomic" stsctr "github.com/nabbar/golib/status/control" - "golang.org/x/exp/slices" ) type model struct { diff --git a/status/model.go b/status/model.go index 5b75005..3dff7f9 100644 --- a/status/model.go +++ b/status/model.go @@ -27,6 +27,7 @@ package status import ( + "slices" "sync" "time" @@ -35,7 +36,6 @@ import ( monsts "github.com/nabbar/golib/monitor/status" montps "github.com/nabbar/golib/monitor/types" stsctr "github.com/nabbar/golib/status/control" - "golang.org/x/exp/slices" ) type fctGetName func() string diff --git a/test/test-nutsdb/main.go b/test/test-nutsdb/main.go deleted file mode 100644 index 95a5597..0000000 --- a/test/test-nutsdb/main.go +++ /dev/null @@ -1,422 +0,0 @@ -//go:build examples -// +build examples - -/*********************************************************************************************************************** - * - * MIT License - * - * Copyright (c) 2021 Nicolas JUHEL - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * - **********************************************************************************************************************/ - -package main - -import ( - "bytes" - "context" - "fmt" - "os" - "runtime" - "strings" - "sync/atomic" - "time" - - logcfg "github.com/nabbar/golib/logger/config" - loglvl "github.com/nabbar/golib/logger/level" - semtps "github.com/nabbar/golib/semaphore/types" - - "github.com/c-bata/go-prompt" - "github.com/c-bata/go-prompt/completer" - libclu "github.com/nabbar/golib/cluster" - liberr "github.com/nabbar/golib/errors" - liblog "github.com/nabbar/golib/logger" - libndb "github.com/nabbar/golib/nutsdb" - libpwd "github.com/nabbar/golib/password" - libsem "github.com/nabbar/golib/semaphore" - libsh "github.com/nabbar/golib/shell" - libvrs "github.com/nabbar/golib/version" - "github.com/nutsdb/nutsdb" - "github.com/vbauerster/mpb/v8" -) - -const ( - BaseDirPattern = "/nutsdb/node-%d" - NbInstances = 3 - NbEntries = 1000 - LoggerFile = "/nutsdb/nutsdb.log" - AllowPut = false - AllowGet = true -) - -var ( - bg = new(atomic.Value) - bp = new(atomic.Value) - log = new(atomic.Value) - ctx context.Context - cnl context.CancelFunc -) - -func init() { - ctx, cnl = context.WithCancel(context.Background()) - liberr.SetModeReturnError(liberr.ErrorReturnCodeErrorTraceFull) - log.Store(liblog.New(func() context.Context { - return ctx - })) - initLogger() -} - -type EmptyStruct struct{} - -func main() { - defer func() { - if cnl != nil { - cnl() - } - }() - - println(fmt.Sprintf("Running test with %d threads...", runtime.GOMAXPROCS(0))) - println(fmt.Sprintf("Init cluster...")) - tStart := time.Now() - cluster := Start(ctx) - - getLogger().SetLevel(loglvl.WarnLevel) - defer func() { - Stop(ctx, cluster) - }() - - if AllowPut || AllowGet { - println(strings.Join(Inject(ctx, tStart, cluster), "\n")) - os.Exit(0) - } - - vs := libvrs.NewVersion(libvrs.License_MIT, "Test Raft DB Nuts", "Tools to test a raft cluster of nutsDB", time.Now().Format(time.RFC3339), "0000000", "v0.0.0", "No one", "pfx", EmptyStruct{}, 0) - vs.PrintLicense() - vs.PrintInfo() - - _, _ = fmt.Fprintf(os.Stdout, "Please use `exit` or `Ctrl-D` to exit this program.\n") - - sh := libsh.New() - sh.Add("", cluster[0].ShellCommand(func() context.Context { - return ctx - }, 200*time.Millisecond)...) - sh.RunPrompt(os.Stdout, os.Stderr, - prompt.OptionTitle(fmt.Sprintf("%s: %s", vs.GetPackage(), vs.GetDescription())), - prompt.OptionPrefix(">>> "), - prompt.OptionInputTextColor(prompt.Yellow), - prompt.OptionCompletionWordSeparator(completer.FilePathCompletionSeparator), - ) -} - -func Inject(ctx context.Context, tStart time.Time, cluster []libndb.NutsDB) []string { - getLogger().SetLevel(loglvl.WarnLevel) - - tInit := time.Since(tStart) - mInit := fmt.Sprintf("Memory used after Init: \n%s", strings.Join(GetMemUsage(), "\n")) - runtime.GC() - println(fmt.Sprintf("Init done. \n")) - - pgb := libsem.New(ctx, 0, true, mpb.WithWidth(64), mpb.WithRefreshRate(200*time.Millisecond)) - barPut := pgb.BarNumber("PutEntry", "", int64(NbEntries), true, nil) - defer barPut.DeferMain() - - tStart = time.Now() - for i := 0; i < NbEntries; i++ { - if e := barPut.NewWorker(); e != nil { - continue - } - - go func(ctx context.Context, bar semtps.SemBar, clu libndb.NutsDB, num int) { - defer bar.DeferWorker() - if AllowPut { - Put(ctx, clu, fmt.Sprintf("key-%03d", num), fmt.Sprintf("val-%03d|%s|%s|%s", num, libpwd.Generate(50), libpwd.Generate(50), libpwd.Generate(50))) - } - }(ctx, barPut, cluster[i%NbInstances], i+1) - } - - if e := barPut.WaitAll(); e != nil { - panic(e) - } - tPut := time.Since(tStart) - mPut := fmt.Sprintf("Memory used after Put entries: \n%s", strings.Join(GetMemUsage(), "\n")) - runtime.GC() - - barGet := pgb.BarNumber("GetEntry", "", int64(NbEntries), true, nil) - defer barGet.DeferMain() - - tStart = time.Now() - for i := 0; i < NbEntries; i++ { - if e := barGet.NewWorker(); e != nil { - continue - } - - c := i%NbInstances + 1 - if c == NbInstances { - c = 0 - } - - go func(ctx context.Context, bar semtps.SemBar, clu libndb.NutsDB, num int) { - defer bar.DeferWorker() - if AllowGet { - Get(ctx, clu, fmt.Sprintf("key-%03d", num), fmt.Sprintf("val-%03d", num)) - } - }(ctx, barGet, cluster[c], i+1) - } - - if e := barGet.WaitAll(); e != nil { - panic(e) - } - tGet := time.Since(tStart) - mGet := fmt.Sprintf("Memory used after Get entries: \n%s", strings.Join(GetMemUsage(), "\n")) - runtime.GC() - - pgb = nil - res := []string{ - fmt.Sprintf("Time for init cluster: %s", tInit.String()), - fmt.Sprintf("Time for %d Put in DB: %s ( %s by entry )", NbEntries, tPut.String(), (tPut / NbEntries).String()), - fmt.Sprintf("Time for %d Get in DB: %s ( %s by entry )", NbEntries, tGet.String(), (tGet / NbEntries).String()), - mInit, - mPut, - mGet, - } - runtime.GC() - getLogger().SetLevel(loglvl.InfoLevel) - getLogger().Info("Results testing: \n%s", nil, strings.Join(res, "\n")) - return res -} - -func GetMemUsage() []string { - var m runtime.MemStats - runtime.ReadMemStats(&m) - return []string{ - fmt.Sprintf("\t - Alloc = %v MiB", m.Alloc/1024/1024), - fmt.Sprintf("\t - TotalAlloc = %v MiB", m.TotalAlloc/1024/1024), - fmt.Sprintf("\t - Sys = %v MiB", m.Sys/1024/1024), - fmt.Sprintf("\t - NumGC = %v\n", m.NumGC), - } -} - -func Put(ctx context.Context, c libndb.NutsDB, key, val string) { - _ = c.Client(ctx, 100*time.Microsecond).Put("myBucket", []byte(key), []byte(val), 0) - //res := c.Client(ctx, 100*time.Microsecond).Put("myBucket", []byte(key), []byte(val), 0) - //fmt.Printf("Cmd Put(%s, %s) : %v\n", key, val, res) -} - -func Get(ctx context.Context, c libndb.NutsDB, key, val string) { - //_, _ = c.Client(ctx, 100*time.Microsecond).Get("myBucket", []byte(key)) - v, e := c.Client(ctx, 100*time.Microsecond).Get("myBucket", []byte(key)) - if e != nil { - getLogger().Error("Cmd Get for key '%s', error : %v", nil, key, e) - fmt.Printf("Cmd Get for key '%s', error : %v", key, e) - } else if !bytes.HasPrefix(v.Value, []byte(val)) { - getLogger().Error("Cmd Get for key '%s', awaiting value start with '%s', but find : %s", nil, key, val, string(v.Value)) - fmt.Printf("Cmd Get for key '%s', awaiting value start with '%s', but find : %s", key, val, string(v.Value)) - } -} - -func Start(ctx context.Context) []libndb.NutsDB { - var clusters = make([]libndb.NutsDB, NbInstances) - - for i := 0; i < NbInstances; i++ { - clusters[i] = initNutDB(i + 1) - clusters[i].SetLogger(func() liblog.Logger { - l := getLogger() - l.SetFields(l.GetFields().Add("lib", libndb.LogLib).Add("instance", i)) - return l - }) - - getLogger().Info("Starting node ID #%d...", nil, i+1) - if err := clusters[i].Listen(); err != nil { - panic(err) - } - - time.Sleep(5 * time.Second) - } - - return clusters -} - -func Stop(ctx context.Context, clusters []libndb.NutsDB) { - for i := 0; i < NbInstances; i++ { - getLogger().Info("Stopping node ID #%d...", nil, i+1) - if err := clusters[i].Shutdown(); err != nil { - panic(err) - } - - time.Sleep(5 * time.Second) - } -} - -func initNutDB(num int) libndb.NutsDB { - cfg := configNutDB() - cfg.Cluster.Cluster.NodeID = uint64(num) - cfg.Cluster.Node.RaftAddress = cfg.Cluster.InitMember[uint64(num)] - cfg.Directory.Base = fmt.Sprintf(BaseDirPattern, num) - - return libndb.New(cfg) -} - -func configNutDB() libndb.Config { - cfg := libndb.Config{ - DB: libndb.NutsDBOptions{ - EntryIdxMode: nutsdb.HintKeyAndRAMIdxMode, - RWMode: nutsdb.FileIO, - SegmentSize: 64 * 1024, - SyncEnable: true, - }, - - Cluster: libclu.Config{ - Node: libclu.ConfigNode{ - DeploymentID: 0, - WALDir: "", - NodeHostDir: "", - RTTMillisecond: 200, - RaftAddress: "", - AddressByNodeHostID: false, - ListenAddress: "", - MutualTLS: false, - CAFile: "", - CertFile: "", - KeyFile: "", - EnableMetrics: true, - MaxSendQueueSize: 0, - MaxReceiveQueueSize: 0, - MaxSnapshotSendBytesPerSecond: 0, - MaxSnapshotRecvBytesPerSecond: 0, - NotifyCommit: false, - Gossip: libclu.ConfigGossip{ - BindAddress: "", - AdvertiseAddress: "", - Seed: nil, - }, - Expert: libclu.ConfigExpert{ - Engine: libclu.ConfigEngine{ - ExecShards: 0, - CommitShards: 0, - ApplyShards: 0, - SnapshotShards: 0, - CloseShards: 0, - }, - TestNodeHostID: 0, - TestGossipProbeInterval: 0, - }, - }, - Cluster: libclu.ConfigCluster{ - NodeID: 0, - ClusterID: 1, - CheckQuorum: true, - ElectionRTT: 15, - HeartbeatRTT: 1, - SnapshotEntries: 10, - CompactionOverhead: 0, - OrderedConfigChange: false, - MaxInMemLogSize: 0, - SnapshotCompressionType: 0, - EntryCompressionType: 0, - DisableAutoCompactions: true, - IsObserver: false, - IsWitness: false, - Quiesce: false, - }, - InitMember: map[uint64]string{ - 1: "localhost:9001", - 2: "localhost:9002", - 3: "localhost:9003", - 4: "localhost:9004", - }, - }, - - Directory: libndb.NutsDBFolder{ - Base: "", - Data: "data", - Backup: "backup", - Temp: "temp", - LimitNumberBackup: 5, - Permission: 0770, - }, - } - - return cfg -} - -func getLogger() liblog.Logger { - if log == nil { - return liblog.New(context.Background) - } else if i := log.Load(); i == nil { - return liblog.New(context.Background) - } else if l, ok := i.(liblog.Logger); !ok { - return liblog.New(context.Background) - } else { - return l - } -} - -func getLoggerDgb() liblog.Logger { - l := getLogger() - l.SetFields(l.GetFields().Add("lib", libclu.LogLib)) - return l -} - -func setLogger(l liblog.Logger) { - if log == nil { - log = new(atomic.Value) - } - - log.Store(l) -} - -func initLogger() { - l := getLogger() - l.SetLevel(loglvl.InfoLevel) - if err := l.SetOptions(&logcfg.Options{ - InheritDefault: false, - TraceFilter: "", - Stdout: nil, - LogFileExtend: false, - LogFile: []logcfg.OptionsFile{ - { - LogLevel: []string{ - "panic", - "fatal", - "error", - "warning", - "info", - "debug", - }, - Filepath: LoggerFile, - Create: true, - CreatePath: true, - FileMode: 0644, - PathMode: 0755, - DisableStack: false, - DisableTimestamp: false, - EnableTrace: true, - }, - }, - LogSyslogExtend: false, - LogSyslog: nil, - }); err != nil { - panic(err) - } - - setLogger(l) - libclu.SetLoggerFactory(getLoggerDgb) -}