Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
HouzuoGuo committed May 26, 2013
1 parent bec6bfc commit 7e4e0c7
Show file tree
Hide file tree
Showing 10 changed files with 218 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ _cgo_export.*
_testmain.go

*.exe
bin
17 changes: 17 additions & 0 deletions .project
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>tiedot</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.googlecode.goclipse.goBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>goclipse.goNature</nature>
</natures>
</projectDescription>
82 changes: 82 additions & 0 deletions src/houzuo.net/tiedot/data/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package data

import (
"encoding/binary"
"errors"
"fmt"
)

type DocFile struct {
File
}

const (
DOC_FILE_GROWTH = uint64(67108864)
DOC_MAX_SIZE = uint64(16777216)
DOC_MAX_ROOM = uint64(16777216 * 2)
DOC_HEADER = uint64(9) // validity (uint8), room (uint64)
DOC_VALID = byte(1)
DOC_INVALID = byte(0)
)

// Retrieve and return document given its ID
func (file *DocFile) Read(id uint64) (data []byte, err error) {
if id < 0 || id > file.Append {
err = errors.New(fmt.Sprintf("Collection file %s does not have document %d", file.Name, id))
return
}
if file.Buf[id] == DOC_INVALID {
return
}
if file.Buf[id] != DOC_VALID {
err = errors.New(fmt.Sprintf("Collection file %s does not have document %d", file.Name, id))
return
}
roomI64, ierr := binary.Varint(file.Buf[id+1 : id+4])
room := uint64(roomI64)
if ierr <= 0 || room > DOC_MAX_ROOM {
err = errors.New(fmt.Sprintf("Document %d is corrupted in file %s", id, file.Name))
return
}
data = file.Buf[id+DOC_HEADER : id+DOC_HEADER+room]
return
}

// Insert a document
func (file *DocFile) Insert(data []byte) (id uint64) {
len64 := uint64(len(data))
newAppend := file.Append
file.Buf[id] = DOC_VALID
newAppend += 1
copy(file.Buf[newAppend:newAppend+len64], data)
newAppend += len64
copy(file.Buf[newAppend:newAppend+len64], make([]byte, len(data)))
file.Append = newAppend
return
}

// Replace a document by new content; or delete and re-insert the document if there is not enough room left
func (file *DocFile) Update(id uint64, data []byte) (newID uint64, err error) {
if id < 0 || id > file.Append {
err = errors.New(fmt.Sprintf("Collection file %s does not have document %d", file.Name, id))
return
}
roomI64, ierr := binary.Varint(file.Buf[id+1 : id+4])
room, len64 := uint64(roomI64), uint64(len(data))
if ierr <= 0 || room > DOC_MAX_ROOM {
err = errors.New(fmt.Sprintf("Document %d is corrupted in file %s", id, file.Name))
return
}
if len64 > DOC_MAX_ROOM {
}
if room >= len64 {
copy(file.Buf[id+DOC_HEADER:id+DOC_HEADER+len64], data)
copy(file.Buf[id+DOC_HEADER+len64:id+DOC_HEADER+len64*2], make([]byte, len(data)))
}
return
}

// Delete a document
func (file *DocFile) Delete(id int) {
file.Buf[id] = 0
}
109 changes: 109 additions & 0 deletions src/houzuo.net/tiedot/data/file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package data

import (
"errors"
"fmt"
"os"
"syscall"
)

type File struct {
Name string
Size uint64
Growth uint64
Append uint64
Buf []byte
Fh *os.File
}

// Open or create a File
func Open(name string, growth uint64) (file *File, err error) {
if growth < 1 {
err = errors.New(fmt.Sprintf("File growth must be > 0 (%d given)", growth))
return
}
file = &File{Name: name, Growth: growth}
if file.Fh, err = os.OpenFile(name, os.O_RDWR, 0); err != nil {
return
}
fsize, err := file.Fh.Seek(0, os.SEEK_END)
if err != nil {
return
}
file.Size = uint64(fsize)
if int(fsize) < 0 {
panic(fmt.Sprintf("File %s is too large to open", file.Name))
}
if file.Buf, err = syscall.Mmap(int(file.Fh.Fd()), 0, int(fsize), syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED); err != nil {
return
}

// find append position (closest byte 0 to position 0)
if file.Size == 0 {
err = file.Ensure(file.Growth)
return
}
for low, high, mid := uint64(0), file.Size, file.Size/2; ; {
if high-mid == 1 {
if file.Buf[mid] == 0 {
file.Append = mid
return
}
if high == file.Size {
err = file.Ensure(file.Growth)
return
}
file.Append = high
return
}
if file.Buf[mid] == 0 {
high = mid
mid = low + (mid-low)/2
} else {
low = mid
mid = mid + (high-mid)/2
}
}
return
}

// Ensure the File has room for more data
func (file *File) Ensure(more uint64) (err error) {
if file.Append+more < file.Size {
return
}

// there is not enough room
if err = syscall.Munmap(file.Buf); err != nil {
return
}
if _, err = file.Fh.Seek(0, os.SEEK_END); err != nil {
return
}
if _, err = file.Fh.Write(make([]byte, file.Growth)); err != nil {
return
}
if err = file.Fh.Sync(); err != nil {
return
}
if newLength := int(file.Size + file.Growth); newLength < 0 {
panic(fmt.Sprintf("File %s is becoming too large", file.Name))
} else if file.Buf, err = syscall.Mmap(int(file.Fh.Fd()), 0, newLength, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED); err != nil {
return
}
file.Size += file.Growth
fmt.Fprintf(os.Stderr, "File %s has grown %d bytes", file.Name, file.Growth)
if err = file.Ensure(more); err != nil {
return
}
return
}

// Close the file
func (file *File) Close() (err error) {
if err = syscall.Munmap(file.Buf); err != nil {
return
}
err = file.Fh.Close()
return
}
1 change: 1 addition & 0 deletions src/houzuo.net/tiedot/data/hash.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package data
1 change: 1 addition & 0 deletions src/houzuo.net/tiedot/logic/collection.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package logic
1 change: 1 addition & 0 deletions src/houzuo.net/tiedot/logic/db.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package logic
1 change: 1 addition & 0 deletions src/houzuo.net/tiedot/logic/query.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package logic
4 changes: 4 additions & 0 deletions src/houzuo.net/tiedot/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package main

func main() {
}
1 change: 1 addition & 0 deletions src/houzuo.net/tiedot/srv/rest.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package srv

0 comments on commit 7e4e0c7

Please sign in to comment.