Created
October 30, 2014 19:25
-
-
Save calmh/10c2b3737346505ac8b6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package files_test | |
import ( | |
"crypto/rand" | |
"log" | |
"os" | |
"sync" | |
"testing" | |
"time" | |
"github.com/syndtr/goleveldb/leveldb" | |
"github.com/syndtr/goleveldb/leveldb/opt" | |
"github.com/syndtr/goleveldb/leveldb/util" | |
) | |
var keys [][]byte | |
func init() { | |
for i := 0; i < nItems; i++ { | |
keys = append(keys, randomData(1)) | |
} | |
} | |
const nItems = 10000 | |
func randomData(prefix byte) []byte { | |
data := make([]byte, 1+32+64+32) | |
_, err := rand.Reader.Read(data) | |
if err != nil { | |
panic(err) | |
} | |
return append([]byte{prefix}, data...) | |
} | |
func setItems(db *leveldb.DB) error { | |
batch := new(leveldb.Batch) | |
for _, k1 := range keys { | |
k2 := randomData(2) | |
// k2 -> data | |
batch.Put(k2, randomData(42)) | |
// k1 -> k2 | |
batch.Put(k1, k2) | |
} | |
log.Printf("batch write (set) %p", batch) | |
return db.Write(batch, nil) | |
} | |
func scanItems(db *leveldb.DB) error { | |
snap, err := db.GetSnapshot() | |
log.Printf("snap create %p", snap) | |
if err != nil { | |
return err | |
} | |
defer func() { | |
log.Printf("snap release %p", snap) | |
snap.Release() | |
}() | |
// Iterate from the start of k2 space to the end | |
it := snap.NewIterator(util.BytesPrefix([]byte{1}), nil) | |
defer it.Release() | |
i := 0 | |
for it.Next() { | |
// k1 => k2 => data | |
k1 := it.Key() | |
k2 := it.Value() | |
_, err := snap.Get(k2, nil) | |
if err != nil { | |
log.Printf("k1: %x", k1) | |
log.Printf(" -> k2: %x", k2) | |
log.Println(" -> missing") | |
return err | |
} | |
i++ | |
} | |
log.Println(i) | |
return nil | |
} | |
func TestConcurrentPutGet(t *testing.T) { | |
if testing.Short() { | |
return | |
} | |
dur := 60 * time.Second | |
t0 := time.Now() | |
var wg sync.WaitGroup | |
os.RemoveAll("testdata/concurrent-set-only.db") | |
db, err := leveldb.OpenFile("testdata/concurrent-set-only.db", &opt.Options{CachedOpenFiles: 10}) | |
if err != nil { | |
t.Fatal(err) | |
} | |
defer os.RemoveAll("testdata/concurrent-set-only.db") | |
errChan := make(chan error, 3) | |
wg.Add(1) | |
go func() { | |
defer wg.Done() | |
for time.Since(t0) < dur { | |
if err := setItems(db); err != nil { | |
errChan <- err | |
return | |
} | |
} | |
}() | |
wg.Add(1) | |
go func() { | |
defer wg.Done() | |
for time.Since(t0) < dur { | |
if err := scanItems(db); err != nil { | |
errChan <- err | |
return | |
} | |
} | |
}() | |
go func() { | |
wg.Wait() | |
errChan <- nil | |
}() | |
err = <-errChan | |
if err != nil { | |
t.Error(err) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment