Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,18 @@ on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

jobs:

build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
Comment on lines 12 to +13

- name: Set up Go
uses: actions/setup-go@v2
uses: actions/setup-go@v5
with:
go-version: 1.15
go-version: '1.21'

- name: Build
run: go build -v ./...
Expand Down
14 changes: 0 additions & 14 deletions .travis.yml

This file was deleted.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Maglev: A Google Maglev Hashing Algorithm implement in Golang
==============

[![GoDoc](https://godoc.org/github.com/kkdai/maglev?status.svg)](https://godoc.org/github.com/kkdai/maglev) [![Build Status](https://travis-ci.org/kkdai/maglev.svg?branch=master)](https://travis-ci.org/kkdai/maglev) [![](https://goreportcard.com/badge/github.com/kkdai/maglev)](https://goreportcard.com/badge/github.com/kkdai/maglev) ![Go](https://github.com/kkdai/maglev/workflows/Go/badge.svg)
[![GoDoc](https://godoc.org/github.com/kkdai/maglev?status.svg)](https://godoc.org/github.com/kkdai/maglev) [![](https://goreportcard.com/badge/github.com/kkdai/maglev)](https://goreportcard.com/badge/github.com/kkdai/maglev) ![Go](https://github.com/kkdai/maglev/workflows/Go/badge.svg)


![](http://www.evanlin.com/images/2016/maglev1.png)
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module github.com/kkdai/maglev

go 1.15
go 1.21

require github.com/dchest/siphash v1.2.2
require github.com/cespare/xxhash/v2 v2.3.0
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
github.com/dchest/siphash v1.2.2 h1:9DFz8tQwl9pTVt5iok/9zKyzA1Q6bRGiF3HPiEEVr9I=
github.com/dchest/siphash v1.2.2/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
41 changes: 26 additions & 15 deletions maglev.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import (
"sort"
"sync"

"github.com/dchest/siphash"
"github.com/cespare/xxhash/v2"
)

const (
bigM uint64 = 65537
)

//Maglev :
// Maglev :
type Maglev struct {
n uint64 //size of VIP backends
m uint64 //size of the lookup table
Expand All @@ -23,10 +23,10 @@ type Maglev struct {
lock *sync.RWMutex
}

//NewMaglev :
// NewMaglev :
func NewMaglev(backends []string, m uint64) (*Maglev, error) {
if !big.NewInt(0).SetUint64(m).ProbablyPrime(1) {
return nil, errors.New("Lookup table size is not a prime number")
return nil, errors.New("lookup table size is not a prime number")
}
mag := &Maglev{m: m, lock: &sync.RWMutex{}}
if err := mag.Set(backends); err != nil {
Expand All @@ -35,19 +35,19 @@ func NewMaglev(backends []string, m uint64) (*Maglev, error) {
return mag, nil
}

//Add : Return nil if add success, otherwise return error
// Add : Return nil if add success, otherwise return error
func (m *Maglev) Add(backend string) error {
m.lock.Lock()
defer m.lock.Unlock()

// Use binary search since nodeList is always sorted after generatePopulation
index := sort.SearchStrings(m.nodeList, backend)
if index < len(m.nodeList) && m.nodeList[index] == backend {
return errors.New("Exist already")
return errors.New("backend already exists")
}

if m.m == m.n {
return errors.New("Number of backends would be greater than lookup table")
return errors.New("number of backends would be greater than lookup table")
}

m.nodeList = append(m.nodeList, backend)
Expand All @@ -57,14 +57,14 @@ func (m *Maglev) Add(backend string) error {
return nil
}

//Remove :
// Remove :
func (m *Maglev) Remove(backend string) error {
m.lock.Lock()
defer m.lock.Unlock()

index := sort.SearchStrings(m.nodeList, backend)
if index >= len(m.nodeList) || m.nodeList[index] != backend {
return errors.New("Not found")
return errors.New("backend not found")
}

m.nodeList = append(m.nodeList[:index], m.nodeList[index+1:]...)
Expand All @@ -81,7 +81,7 @@ func (m *Maglev) Set(backends []string) error {

n := uint64(len(backends))
if m.m < n {
return errors.New("Number of backends is greater than lookup table")
return errors.New("number of backends is greater than lookup table")
}
m.nodeList = make([]string, n)
copy(m.nodeList, backends) // Copy to avoid modifying original input afterwards
Expand All @@ -100,20 +100,31 @@ func (m *Maglev) Clear() {
m.lookup = nil
}

//Get :Get node name by object string.
// Get :Get node name by object string.
func (m *Maglev) Get(obj string) (string, error) {
m.lock.RLock()
defer m.lock.RUnlock()

if len(m.nodeList) == 0 {
return "", errors.New("Empty")
return "", errors.New("empty")
}
key := m.hashKey(obj)
return m.nodeList[m.lookup[key%m.m]], nil
}

func (m *Maglev) hashKey(obj string) uint64 {
return siphash.Hash(0xdeadbabe, 0, []byte(obj))
return xxhash.Sum64([]byte(obj))
}

// saltedHash mixes salt into the hash so that offset and skip below are
// derived from independent hash values, mirroring the two distinct
// SipHash keys used previously. Reusing a single unsalted hash for both
// would correlate offset and skip and weaken the permutation.
func saltedHash(salt byte, data []byte) uint64 {
d := xxhash.New()
d.Write([]byte{salt})
d.Write(data)
return d.Sum64()
}
Comment on lines +123 to 128

func (m *Maglev) generatePopulation() {
Expand All @@ -130,8 +141,8 @@ func (m *Maglev) generatePopulation() {
for i := 0; i < len(m.nodeList); i++ {
bData := []byte(m.nodeList[i])

offset := siphash.Hash(0xdeadbabe, 0, bData) % m.m
skip := (siphash.Hash(0xdeadbeef, 0, bData) % (m.m - 1)) + 1
offset := saltedHash(0xba, bData) % m.m
skip := (saltedHash(0xbe, bData) % (m.m - 1)) + 1

iRow := make([]uint64, m.m)
var j uint64
Expand Down
10 changes: 10 additions & 0 deletions maglev_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ import (
const sizeN = 5
const lookupSizeM = 13 //need prime and

func TestRequiresPrime(t *testing.T) {
var names []string
names = append(names, "testing")

_, err := NewMaglev(names, 4)
if err == nil {
t.Error("Should disallow non-prime lookup table size")
}
}

func TestSimple(t *testing.T) {
var names []string
for i := 0; i < sizeN; i++ {
Expand Down
10 changes: 0 additions & 10 deletions vendor/github.com/dchest/siphash/.travis.yml

This file was deleted.

69 changes: 0 additions & 69 deletions vendor/github.com/dchest/siphash/README.md

This file was deleted.

Loading
Loading