Skip to content

Commit

Permalink
re-implement collision expansion; closes #13
Browse files Browse the repository at this point in the history
  • Loading branch information
lrstanley committed Nov 19, 2019
1 parent fd1fb3b commit 7221d4a
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 17 deletions.
25 changes: 20 additions & 5 deletions database.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,22 @@ import (
"reflect"
"strings"
"sync"
"sync/atomic"
"time"

"github.com/timshannon/bolthold"
bolt "go.etcd.io/bbolt"
)

const collisionMax = 20

func init() {
rand.Seed(time.Now().UnixNano())
}

const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

func uuid(n int) string {
func uuid(n int64) string {
b := make([]byte, n)
for i := range b {
b[i] = letterBytes[rand.Intn(len(letterBytes))]
Expand Down Expand Up @@ -89,7 +92,7 @@ func updateGlobalStats(db *bolthold.Store) {

// Link represents a url that we are shortening.
type Link struct {
UID string `boltholdKey`
UID string `boltholdKey:"UID"`
URL string // The URL we're expanding.
Created time.Time // When the link was submitted.
Hits int // How many times we've expanded for users.
Expand Down Expand Up @@ -128,13 +131,24 @@ func (l *Link) Create(db *bolthold.Store) error {
return db.Insert(l.UID, l)
}

var collisionCount int
for {
l.UID = uuid(4)
l.UID = uuid(atomic.LoadInt64(&conf.KeyLength))
err = db.Insert(l.UID, l)
if err != nil {
if err == bolthold.ErrKeyExists {
// Keep looping through until we're able to store one which
// doesn't collide with a pre-existing key.
collisionCount++
if collisionCount >= collisionMax {
// If we continue to get collisions in a row, bump the global
// key value to one higher. Worst case if the collision max is
// hit, it will only be computationally difficult on the first
// shortened link upon restart.
collisionCount = 0
newKeyLength := atomic.AddInt64(&conf.KeyLength, 1)
debug.Printf("collision maximum hit (count: %d); increasing global key length from %d to %d", collisionMax, newKeyLength-1, newKeyLength)
}
continue
}

Expand Down Expand Up @@ -180,8 +194,9 @@ func hash(input string) string {

func newDB(readOnly bool) *bolthold.Store {
store, err := bolthold.Open(conf.DBPath, 0660, &bolthold.Options{Options: &bolt.Options{
ReadOnly: readOnly,
Timeout: 10 * time.Second,
FreelistType: bolt.FreelistMapType,
ReadOnly: readOnly,
Timeout: 25 * time.Second,
}})
if err != nil {
panic(fmt.Sprintf("unable to open db: %s", err))
Expand Down
4 changes: 1 addition & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,11 @@ require (
github.com/daaku/go.zipexe v1.0.1 // indirect
github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4 // indirect
github.com/go-chi/chi v4.0.2+incompatible
github.com/gorilla/context v1.1.1 // indirect
github.com/gorilla/sessions v1.2.0 // indirect
github.com/jessevdk/go-flags v1.4.1-0.20180331124232-1c38ed7ad0cc
github.com/juju/errors v0.0.0-20190806202954-0232dcc7464d // indirect
github.com/lrstanley/go-sempool v0.0.0-20181215043219-1ee81530e9dd
github.com/lrstanley/pt v0.0.0-20180304040151-203b3db5ff8f
github.com/timshannon/bolthold v0.0.0-20190812165541-a85bcc049a2e
github.com/timshannon/bolthold v0.0.0-20191009161117-ccb01ed9dec4
go.etcd.io/bbolt v1.3.3
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 // indirect
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd // indirect
Expand Down
10 changes: 2 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,6 @@ github.com/go-check/check v0.0.0-20180628173108-788fd7840127 h1:0gkP6mzaMqkmpcJY
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
github.com/go-chi/chi v4.0.2+incompatible h1:maB6vn6FqCxrpz4FqWdh4+lwpyZIQS7YEAUcHlgXVRs=
github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.2.0 h1:S7P+1Hm5V/AT9cjEcUD5uDaQSX0OE577aCXgoaKpYbQ=
github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jessevdk/go-flags v1.4.1-0.20180331124232-1c38ed7ad0cc h1:unqembev+qAeQDOhvsahBm2Xla2M/cfQvjl+0MhkpOM=
github.com/jessevdk/go-flags v1.4.1-0.20180331124232-1c38ed7ad0cc/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
Expand All @@ -42,8 +36,8 @@ github.com/lrstanley/pt v0.0.0-20180304040151-203b3db5ff8f/go.mod h1:WMa0QbIny3K
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229 h1:E2B8qYyeSgv5MXpmzZXRNp8IAQ4vjxIjhpAf5hv/tAg=
github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E=
github.com/timshannon/bolthold v0.0.0-20190812165541-a85bcc049a2e h1:FC5JjwU5y5ZBR/vH8LhmPman3k5dep45jRyCpR1VDVQ=
github.com/timshannon/bolthold v0.0.0-20190812165541-a85bcc049a2e/go.mod h1:jUigdmrbdCxcIDEFrq82t4X9805XZfwFZoYUap0ET/U=
github.com/timshannon/bolthold v0.0.0-20191009161117-ccb01ed9dec4 h1:JeRtUr5bj3JRsI9AEE4ouxodTge24lW7PnrDvWVjrgY=
github.com/timshannon/bolthold v0.0.0-20191009161117-ccb01ed9dec4/go.mod h1:jUigdmrbdCxcIDEFrq82t4X9805XZfwFZoYUap0ET/U=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.0.1 h1:tY9CJiPnMXf1ERmG2EyK7gNUd+c6RKGD0IfU8WdUSz8=
Expand Down
3 changes: 2 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ type Config struct {
Key string `short:"k" long:"key" description:"path to ssl key file"`
} `group:"TLS Options" namespace:"tls"`
DBPath string `short:"d" long:"db" default:"store.db" description:"path to database file"`
KeyLength int `long:"key-length" default:"4" description:"default length of key (uuid) for generated urls"`
KeyLength int64 `long:"key-length" default:"4" description:"default length of key (uuid) for generated urls"`
HTTPPreInclude string `long:"http-pre-include" description:"HTTP include which is included directly after css is included (near top of the page)"`
HTTPPostInclude string `long:"http-post-include" description:"HTTP include which is included directly after js is included (near bottom of the page)"`

Expand Down Expand Up @@ -80,6 +80,7 @@ func main() {
if conf.KeyLength < 4 {
conf.KeyLength = 4
}

conf.Site = strings.TrimRight(conf.Site, "/")

initLogger()
Expand Down

0 comments on commit 7221d4a

Please sign in to comment.