Skip to content

Commit

Permalink
start implementing fileblockdevice
Browse files Browse the repository at this point in the history
  • Loading branch information
Knio committed Mar 9, 2015
1 parent dc561e4 commit 118ec09
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 3 deletions.
6 changes: 6 additions & 0 deletions README.md
Expand Up @@ -4,6 +4,12 @@
[![Coverage Status](https://coveralls.io/repos/Knio/everdb-go/badge.svg)](https://coveralls.io/r/Knio/everdb-go)


`EverDB-go` is a `Go` language port of [EverDB](https://github.com/Knio/everdb)


`EverDB-go` is currently a work in progress and is *unfinished* and *not fit for use*.


## Docs

http://godoc.org/github.com/Knio/everdb-go
4 changes: 2 additions & 2 deletions everdb.go
@@ -1,8 +1,8 @@
package everdb

type Helloer struct {
type Database struct {
}

func (h Helloer) HelloWorld() int {
func (h Database) HelloWorld() int {
return 5
}
2 changes: 1 addition & 1 deletion everdb_test.go
Expand Up @@ -5,7 +5,7 @@ import "testing"
func TestHelloer(t *testing.T) {
t.Parallel()

h := Helloer{}
h := Database{}
if val := h.HelloWorld(); val != 5 {
t.Error("Value was wrong:", val)
}
Expand Down
81 changes: 81 additions & 0 deletions fileblockdevice.go
@@ -0,0 +1,81 @@
package everdb

import "errors"
import "os"

const BLOCK_SIZE = 4096

type FileBlockDevice struct {
file *os.File
len uint32
}

func NewFileBlockDevice(fname string, readonly bool, overwrite bool) (*FileBlockDevice, error) {
if readonly && overwrite {
return nil, errors.New("Both overwrite and readonly specified")
}

f := new(FileBlockDevice)
var err error

if readonly {
f.file, err = os.OpenFile(fname, os.O_RDONLY, 0)
} else if overwrite {
f.file, err = os.OpenFile(fname, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0666)
} else {
f.file, err = os.OpenFile(fname, os.O_CREATE|os.O_RDWR, 0666)
}

if nil != err {
return nil, err
}

fi, err := f.file.Stat()
if nil != err {
return nil, errors.New("Failed to stat file")
}

if fi.Size()%BLOCK_SIZE != 0 {
return nil, errors.New("File is corrupt (not a multiple of BLOCK_SIZE")
}

f.len = (uint32)(fi.Size() / BLOCK_SIZE)

return f, nil
}

func (f *FileBlockDevice) Len() uint32 {
return f.len
}

func (f *FileBlockDevice) Resize(len uint32) error {
sz := (int64)(len) * BLOCK_SIZE

err := f.file.Truncate(sz)
if nil != err {
return err
}

fi, err := f.file.Stat()
if nil != err {
return errors.New("Failed to stat file")
}
if fi.Size() != sz {
return errors.New("Failed to reize file")
}
f.len = len

return nil
}

func (f *FileBlockDevice) Get(block int) ([]byte, error) {
b := make([]byte, BLOCK_SIZE)
n, err := f.file.ReadAt(b, (int64)(block)*BLOCK_SIZE)
if nil != err {
return nil, err
}
if n != BLOCK_SIZE {
return nil, errors.New("Failed to read BLOCK_SIZE bytes")
}
return b, nil
}
64 changes: 64 additions & 0 deletions fileblockdevice_test.go
@@ -0,0 +1,64 @@
package everdb

import "testing"
import "os"

func TestMain(m *testing.M) {
code := m.Run()

os.Remove("test.db")
os.Exit(code)
}

func equals(a, b []byte) bool {
l := len(a)
if l != len(b) {
return false
}
for i := 0; i < l; i++ {
if a[i] != b[i] {
return false
}
}
return true
}

func TestFileBlockDevice(t *testing.T) {
t.Parallel()

h, err := NewFileBlockDevice("test.db", false, true)

if nil != err {
t.Error(err)
}

if val := h.Len(); val != 0 {
t.Error("Initial block device was not empty", val)
}

err = h.Resize(1)

if nil != err {
t.Errorf("Resize failed: %v", err)
}

if h.Len() != 1 {
t.Error("Resize failed")
}

zero := make([]byte, BLOCK_SIZE)
for i := 0; i < BLOCK_SIZE; i++ {
zero[i] = 0
}

b, err := h.Get(0)

if nil != err {
t.Error("Failed to get block")
}

if !equals(b, zero) {
t.Error("fresh block is not zeroed")
}

}

0 comments on commit 118ec09

Please sign in to comment.