Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/geektutu/7days-golang
Browse files Browse the repository at this point in the history
  • Loading branch information
geektutu committed May 16, 2020
2 parents 1a10f5c + b56cf04 commit db1cc60
Show file tree
Hide file tree
Showing 13 changed files with 594 additions and 0 deletions.
18 changes: 18 additions & 0 deletions gee-bolt/day2-mmap/db.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package geebolt

import "os"

type DB struct {
data []byte
file *os.File
}

const maxMapSize = 1 << 31

func (db *DB) mmap(sz int) error {
b, err := syscall.Mmap()
}

func Open(path string) {

}
3 changes: 3 additions & 0 deletions gee-bolt/day2-mmap/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module geebolt

go 1.13
3 changes: 3 additions & 0 deletions gee-bolt/day3-tree/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module geebolt

go 1.13
33 changes: 33 additions & 0 deletions gee-bolt/day3-tree/meta.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package geebolt

import (
"errors"
"hash/fnv"
"unsafe"
)

// Represent a marker value to indicate that a file is a gee-bolt DB
const magic uint32 = 0xED0CDAED

type meta struct {
magic uint32
pageSize uint32
pgid uint64
checksum uint64
}

func (m *meta) sum64() uint64 {
var h = fnv.New64a()
_, _ = h.Write((*[unsafe.Offsetof(meta{}.checksum)]byte)(unsafe.Pointer(m))[:])
return h.Sum64()
}

func (m *meta) validate() error {
if m.magic != magic {
return errors.New("invalid magic number")
}
if m.checksum != m.sum64() {
return errors.New("invalid checksum")
}
return nil
}
53 changes: 53 additions & 0 deletions gee-bolt/day3-tree/node.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package geebolt

import (
"bytes"
"sort"
)

type kv struct {
key []byte
value []byte
}

type node struct {
isLeaf bool
key []byte
parent *node
children []*node
kvs []kv
}

func (n *node) root() *node {
if n.parent == nil {
return n
}
return n.parent.root()
}

func (n *node) index(key []byte) (index int, exact bool) {
index = sort.Search(len(n.kvs), func(i int) bool {
return bytes.Compare(n.kvs[i].key, key) != -1
})
exact = len(n.kvs) > 0 && index < len(n.kvs) && bytes.Equal(n.kvs[index].key, key)
return
}

func (n *node) put(oldKey, newKey, value []byte) {
index, exact := n.index(oldKey)
if !exact {
n.kvs = append(n.kvs, kv{})
copy(n.kvs[index+1:], n.kvs[index:])
}
kv := &n.kvs[index]
kv.key = newKey
kv.value = value
}

func (n *node) del(key []byte) {
index, exact := n.index(key)
if exact {
n.kvs = append(n.kvs[:index], n.kvs[index+1:]...)
}
}

88 changes: 88 additions & 0 deletions gee-bolt/day3-tree/page.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package geebolt

import (
"fmt"
"reflect"
"unsafe"
)

const pageHeaderSize = unsafe.Sizeof(page{})
const branchPageElementSize = unsafe.Sizeof(branchPageElement{})
const leafPageElementSize = unsafe.Sizeof(leafPageElement{})
const maxKeysPerPage = 1024

const (
branchPageFlag uint16 = iota
leafPageFlag
metaPageFlag
freelistPageFlag
)

type page struct {
id uint64
flags uint16
count uint16
overflow uint32
}

type leafPageElement struct {
pos uint32
ksize uint32
vsize uint32
}

type branchPageElement struct {
pos uint32
ksize uint32
pgid uint64
}

func (p *page) typ() string {
switch p.flags {
case branchPageFlag:
return "branch"
case leafPageFlag:
return "leaf"
case metaPageFlag:
return "meta"
case freelistPageFlag:
return "freelist"
}
return fmt.Sprintf("unknown<%02x>", p.flags)
}

func (p *page) meta() *meta {
return (*meta)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + pageHeaderSize))
}

func (p *page) dataPtr() unsafe.Pointer {
return unsafe.Pointer(&reflect.SliceHeader{
Data: uintptr(unsafe.Pointer(p)) + pageHeaderSize,
Len: int(p.count),
Cap: int(p.count),
})
}

func (p *page) leafPageElement(index uint16) *leafPageElement {
off := pageHeaderSize + uintptr(index)*leafPageElementSize
return (*leafPageElement)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + off))
}

func (p *page) leafPageElements() []leafPageElement {
if p.count == 0 {
return nil
}
return *(*[]leafPageElement)(p.dataPtr())
}

func (p *page) branchPageElement(index uint16) *branchPageElement {
off := pageHeaderSize + uintptr(index)*branchPageElementSize
return (*branchPageElement)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + off))
}

func (p *page) branchPageElements() []branchPageElement {
if p.count == 0 {
return nil
}
return *(*[]branchPageElement)(p.dataPtr())
}
3 changes: 3 additions & 0 deletions gee-rpc/day1-encode/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module geerpc

go 1.13
26 changes: 26 additions & 0 deletions gee-rpc/day1-encode/protocol/codec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package protocol

import (
"bytes"
"encoding/json"
)

type Codec interface {
Encode(i interface{}) ([]byte, error)
Decode(data []byte, i interface{}) error
}

// JSONCodec uses json marshaler and unmarshaler.
type JSONCodec struct{}

// Encode encodes an object into slice of bytes.
func (c JSONCodec) Encode(i interface{}) ([]byte, error) {
return json.Marshal(i)
}

// Decode decodes an object from slice of bytes.
func (c JSONCodec) Decode(data []byte, i interface{}) error {
d := json.NewDecoder(bytes.NewBuffer(data))
d.UseNumber()
return d.Decode(i)
}
113 changes: 113 additions & 0 deletions gee-rpc/day1-encode/protocol/message.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package protocol

import (
"bytes"
"encoding/binary"
"fmt"
"io"
"strings"
)

const MagicNumber int32 = 0xECABCD

type SerializeType int8

const (
JSON SerializeType = iota
)

var Codecs = map[SerializeType]Codec{
JSON: &JSONCodec{},
}

type Status int8

const (
OK Status = iota
ExecError
NotFoundError
)

type Header struct {
Magic int32
Status Status
SerializeType SerializeType
ServiceMethodSize int32
PayloadSize int32
}

type Message struct {
*Header
ServiceMethod string
Payload []byte
}

func NewMessage() *Message {
return &Message{
Header: &Header{Magic: MagicNumber},
}
}

func (m *Message) HandleError(status Status, err error) *Message {
m.Status = status
_ = m.SetPayload(err)
return m
}

func (m *Message) SetServiceMethod(name string) {
m.ServiceMethod = name
}

func (m *Message) GetServiceMethod() (service, method string, err error) {
parts := strings.Split(m.ServiceMethod, ".")
if len(parts) != 2 || parts[0] == "" || parts[1] == "" {
return "", "", fmt.Errorf("<service.method> format error")
}
return parts[0], parts[1], nil
}

func (m *Message) GetPayload(i interface{}) error {
return Codecs[m.SerializeType].Decode(m.Payload, i)
}

func (m *Message) SetPayload(i interface{}) (err error) {
m.Payload, err = Codecs[m.SerializeType].Encode(i)
return
}

func (m *Message) Clone() *Message {
m2 := NewMessage()
*m2.Header = *m.Header
m2.ServiceMethod = m.ServiceMethod
return m2
}
func Read(r io.Reader) (*Message, error) {
m := NewMessage()
if err := binary.Read(r, binary.BigEndian, m.Header); err != nil {
return nil, err
}
if m.Magic != MagicNumber {
return nil, fmt.Errorf("invalid message: wrong magic number")
}

buf := make([]byte, m.ServiceMethodSize+m.PayloadSize)
if err := binary.Read(r, binary.BigEndian, buf); err != nil {
return nil, err
}
m.ServiceMethod = string(buf[:m.ServiceMethodSize])
m.Payload = buf[m.ServiceMethodSize:]
return m, nil
}
func (m *Message) Write(w io.Writer) error {
m.PayloadSize = int32(len(m.Payload))
m.ServiceMethodSize = int32(len(m.ServiceMethod))
buf := bytes.NewBufferString(m.ServiceMethod)
buf.Write(m.Payload)
if err := binary.Write(w, binary.BigEndian, m.Header); err != nil {
return err
}
if err := binary.Write(w, binary.BigEndian, buf.Bytes()); err != nil {
return err
}
return nil
}
3 changes: 3 additions & 0 deletions gee-rpc/day1-encode/protocol/path.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package protocol

const DefaultRPCPath = "/_geerpc"
Loading

0 comments on commit db1cc60

Please sign in to comment.