btree的實現(xiàn)

package tree

//#include <sys/mman.h>
//import "C"
import (
    "errors"
    "fmt"
    "os"
    "reflect"
    "sort"
    //"strconv"
    "syscall"
    "unsafe"
)

const (
    tmeta     uint8 = 1
    tinterior uint8 = 2 // iterior node
    tleaf     uint8 = 3 // left node
)

const pagesize int64 = 1024 * 4 * 2

const pageheadOffset int64 = int64(unsafe.Offsetof(((*page)(nil)).elementsptr))
const elementSize int64 = int64(unsafe.Sizeof(element{}))
const maxitems int64 = 100
const pageheaadlen int64 = pageheadOffset + elementSize*maxitems //4*8 + 80*100
const maxkeylen uint32 = 64

type element struct {
    bkey  [maxkeylen]byte
    ksize uint32
    value uint64
}

func (e *element) key() string { return string(e.bkey[:e.ksize]) }
func (e *element) setkv(key string, value uint64) {
    if len(key) > int(maxkeylen) {
        copy(e.bkey[:], []byte(key)[:maxkeylen])
        e.ksize = maxkeylen
        e.value = value
        return
    }
    copy(e.bkey[:len(key)], []byte(key)[:])
    e.ksize = uint32(len(key))
    e.value = value
    return
}

type sorteles []element

func (s sorteles) Len() int           { return len(s) }
func (s sorteles) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
func (s sorteles) Less(i, j int) bool { return s[i].key() > s[j].key() }

//
//  ii, _ := strconv.Atoi(s[i].key())
//  jj, _ := strconv.Atoi(s[j].key())
//  return ii > jj
//}

// page description:頁的基本單位
type page struct {
    curid       uint32
    preid       uint32
    nextid      uint32
    parentpg    uint32
    pgtype      uint8
    count       uint32 //
    used        uint32
    elementsptr uintptr
}

type pagestack struct {
    pageid uint32
    index  int
}

func (p *page) display(bt *btree) {

    elements := p.getElements()
    fmt.Printf("[INFO]==>display :: ELEMENTS ")
    for i := range elements[:p.count] {
        e := &elements[i]

        if p.pgtype == tinterior {
            fmt.Printf("::: key[%v]  %v\n", e.key(), e.value)
            child := bt.getpage(uint32(e.value))
            child.display(bt)
        } else {
            fmt.Printf("::: key[%v]  %v\t", e.key(), e.value)
        }
    }
    fmt.Println()

}

func (p *page) set(key string, value uint64, bt *btree) bool {

    stack := make([]pagestack, 0)

    found, _, idx, err := p.search(key, &stack, bt)

    if err != nil {
        fmt.Printf("[ERROR] can not set key value %v %v %v\n", found, value, idx)
        return false
    }

    //直接更新
    if found {
        bt.getpage(stack[len(stack)-1].pageid).getElement(idx).value = value
        return true
    }

    page := bt.getpage(stack[len(stack)-1].pageid)
    index := stack[len(stack)-1].index
    pg1, pg2, err := page.insertleaf(index, key, value, bt)
    if err != nil {
        return false
    }

    for idx := len(stack) - 2; idx >= 0; idx-- {

        page := bt.getpage(stack[idx].pageid)
        index := stack[idx].index
        pg1, pg2, _ = page.interiorinsert(index, pg1, pg2, bt)
    }

    if pg1 != 0 && pg2 != 0 {

        newroot, _, _ := bt.newpage(0, 0, tinterior)
        p1 := bt.getpage(pg1)
        p2 := bt.getpage(pg2)
        newroot.count = 2
        rooteles := newroot.getElements()
        rooteles[0].setkv(p1.getElement(int(p1.count-1)).key(), uint64(p1.curid))
        rooteles[1].setkv("", uint64(p2.curid))
        bt.root = newroot
        bt.db.setrootid(bt.name)
        bt.rootpgid = newroot.curid
        //bt.rootpg = newroot.curid
        fmt.Printf("new root...%v\n", newroot.curid)
    }

    return true

}

func (p *page) interiorinsert(index int, pg1, pg2 uint32, bt *btree) (uint32, uint32, error) {

    if pg1 != 0 && pg2 == 0 {
        child1 := bt.getpage(pg1)
        elements := p.getElements()
        child1node := child1.getElement(int(child1.count - 1))
        elements[index].value = uint64(child1.curid)
        if elements[index].key() != "" {
            elements[index].setkv(child1node.key(), uint64(child1.curid)) //uintptr(unsafe.Pointer(p)))
        }
        return p.curid, 0, nil
    }

    if pg1 != 0 && pg2 != 0 {
        child1 := bt.getpage(pg1)
        child2 := bt.getpage(pg2)
        elements := p.getElements()
        child1node := child1.getElement(int(child1.count - 1))
        elements[p.count].setkv(child1node.key(), uint64(child1.curid)) //uintptr(unsafe.Pointer(p)))
        p.count++

        child2node := child2.getElement(int(child2.count - 1))
        elements[index].value = uint64(child2.curid)
        if elements[index].key() != "" {
            elements[index].setkv(child2node.key(), uint64(child2.curid)) //uintptr(unsafe.Pointer(p)))
        }

        sort.Sort(sorteles(elements[:p.count]))

        if p.count < uint32(maxitems) {
            return p.curid, 0, nil
        }

        /////////parent := bt.getpage(p.parentpg)
        var newpage *page
        newpage, _, p = bt.newpage(0, p.curid, tinterior)
        newpage.count = 0
        ii := 0
        for i := int(p.count) / 2; i < int(p.count); i++ {
            pele := p.getElement(i)
            ele := newpage.getElement(ii)
            ele.setkv(pele.key(), pele.value)
            newpage.count++
            ii++

        }
        p.count = p.count / 2
        return p.curid, newpage.curid, nil

    }

    return p.curid, 0, nil

}

func makeBufferPage(src *page) *page {
    srcbuf := (*[0xFFFFFF]byte)(unsafe.Pointer(src)) //
    buf := make([]byte, pagesize)
    copy(buf, srcbuf[:pagesize])
    return (*page)(unsafe.Pointer(&buf[0]))

}

func (p *page) split(key string, value uint64, bt *btree) (uint32, uint32, error) {

    elements := p.getElements()
    elements[p.count].setkv(key, value) //uintptr(unsafe.Pointer(p)))
    p.count++
    sort.Sort(sorteles(elements[:p.count]))

    ///////////parent := bt.getpage(p.parentpg)
    var newpage *page
    newpage, _, p = bt.newpage(0, p.curid, tleaf)

    ii := 0
    for i := int(p.count) / 2; i < int(p.count); i++ {
        pele := p.getElement(i)
        ele := newpage.getElement(ii)
        ele.setkv(pele.key(), pele.value)
        newpage.count++
        ii++

    }
    p.count = p.count / 2

    return p.curid, newpage.curid, nil

}

func (p *page) insertleaf(index int, key string, value uint64, bt *btree) (uint32, uint32, error) {

    if p.pgtype == tleaf {

        if p.count == uint32(maxitems) {
            return p.split(key, value, bt) //nil,nil,errors.New("page is full")
        }

        elements := p.getElements()
        elements[p.count].setkv(key, value) //uintptr(unsafe.Pointer(p)))
        p.count++
        sort.Sort(sorteles(elements[:p.count]))
        return p.curid, 0, nil
    }
    return 0, 0, errors.New("insert error")

}

func (p *page) search(key string, stack *[]pagestack, bt *btree) (bool, uint64, int, error) {

    // onl
    if p.pgtype == tleaf {
        if p.count == 0 {
            *stack = append(*stack, pagestack{pageid: p.curid, index: 0})
            return false, 0, 0, nil
        }

        //循環(huán)查找
        elements := p.getElements()
        c := func(i int) bool {
            // ee,_:=strconv.Atoi(elements[i].key())
            //kk,_:=strconv.Atoi(key)
            //return ee<=kk//elements[i].key() <= key
            return elements[i].key() <= key
        }
        idx := sort.Search(int(p.count), c)
        if idx < int(p.count) {
            if elements[idx].key() == key {
                //fmt.Printf("found : %v %v\n",key,elements[idx].value)
                *stack = append(*stack, pagestack{pageid: p.curid, index: idx})
                return true, elements[idx].value, idx, nil
            }
            *stack = append(*stack, pagestack{pageid: p.curid, index: idx})
            return false, elements[idx].value, idx, nil
        }

        *stack = append(*stack, pagestack{pageid: p.curid, index: 0})
        return false, 0, 0, nil //errors.New("found error")
    } else if p.pgtype == tinterior {
        if p.count == 0 {
            *stack = append(*stack, pagestack{pageid: p.curid, index: 0})
            return false, 0, -1, errors.New("ERROR")
        }

        //循環(huán)查找
        elements := p.getElements() // data pointer
        c := func(i int) bool {
            //ee,_:=strconv.Atoi(elements[i].key())
            //kk,_:=strconv.Atoi(key)
            return elements[i].key() <= key
        }
        idx := sort.Search(int(p.count), c)
        if idx < int(p.count) {
            *stack = append(*stack, pagestack{pageid: p.curid, index: idx})
            sub := bt.getpage(uint32(elements[idx].value))
            return sub.search(key, stack, bt)
        }

        //沒有找到,需要添加
        *stack = append(*stack, pagestack{pageid: p.curid, index: -1})
        return false, 0, -1, errors.New("found error")
    }
    fmt.Printf("[ERROR]==>SEARCH :: b+tree error \n")
    return false, 0, -1, errors.New("ERROR")

}

func (p *page) getElements() []element {

    return ((*[0xFFFF]element)(unsafe.Pointer(&p.elementsptr)))[:]
}

func (p *page) getElement(index int) *element {

    return &((*[0xFFFF]element)(unsafe.Pointer(&p.elementsptr)))[index]
}

func (p *page) getfristkv(bt *btree) (string, uint32, uint32, int, bool) {

    if p.pgtype == tinterior {
        child := bt.getpage(uint32(p.getElement(0).value))
        return child.getfristkv(bt)
    }

    if p.pgtype == tleaf && p.count > 0 {
        res := p.getElement(0)
        return res.key(), uint32(res.value), uint32(p.curid), 0, true
    }

    return "", 0, 0, 0, false

}

// btree function description : b+樹
type btree struct {
    db       *BTreedb
    name     string
    root     *page
    rootpgid uint32
    //cache map[uint32]*page
}

func loadbtree(name string, root *page, db *BTreedb) *btree {

    bt := &btree{db: db, name: name, root: root, rootpgid: root.curid}
    return bt

}

func newbtree(name string, db *BTreedb) *btree {
    bt := &btree{db: db, name: name}
    bt.root, _, _ = bt.newpage(0, 0, tinterior)
    var leaf *page
    leaf, bt.root, _ = bt.newpage(bt.root.curid, 0, tleaf)
    ele := bt.root.getElement(0)
    ele.value = uint64(leaf.curid)
    bt.rootpgid = bt.root.curid
    return bt
}

func (bt *btree) Set(key string, value uint64) error {
    bt.root = bt.db.getpage(bt.rootpgid)
    res := bt.root.set(key, value, bt)
    if res {
        //bt.db.Sync()
        return nil
    }

    return errors.New("update fail")
}

func (bt *btree) checkmmap() error {
    return bt.db.checkmmap()
}

func (bt *btree) newpage(parentid, preid uint32, pagetype uint8) (*page, *page, *page) {

    return bt.db.newpage(parentid, preid, pagetype)
}

func (bt *btree) getpage(pgid uint32) *page {

    // if _,ok:=bt.cache[pgid];ok{
    //      return bt.cache[pgid]
    //  }
    //pg:= bt.db.getpage(pgid)
    //  bt.cache[pgid]=pg
    //  return pg
    return bt.db.getpage(pgid)
}

func (bt *btree) Search(key string) (bool, uint64) {
    bt.root = bt.db.getpage(bt.rootpgid)
    stack := make([]pagestack, 0)
    ok, value, _, _ := bt.root.search(key, &stack, bt)

    return ok, value
}

func (bt *btree) Range(start, end string) (bool, []uint64) {

    if len(start) == 0 {
        bt.root = bt.db.getpage(bt.rootpgid) //
        stack1 := make([]pagestack, 0)
        ok, _, _, _ := bt.root.search(end, &stack1, bt)
        if !ok {
            return false, nil
        }
        startpgid := stack1[len(stack1)-1].pageid
        startpg := bt.db.getpage(startpgid)
        res := make([]uint64, 0)
        for idx := stack1[len(stack1)-1].index - 1; idx >= 0; idx-- {
            res = append(res, startpg.getElement(idx).value)
        }

        pgid := startpg.preid
        for pgid != 0 {
            pg := bt.db.getpage(pgid)
            for idx := int(pg.count) - 1; idx > 0; idx-- {
                res = append(res, pg.getElement(idx).value)
            }
            pgid = pg.preid
        }
        return true, res
    }

    if len(end) == 0 {
        bt.root = bt.db.getpage(bt.rootpgid)
        stack1 := make([]pagestack, 0)
        ok, _, _, _ := bt.root.search(start, &stack1, bt)
        if !ok {
            return false, nil
        }
        startpgid := stack1[len(stack1)-1].pageid
        startpg := bt.db.getpage(startpgid)
        res := make([]uint64, 0)
        for idx := stack1[len(stack1)-1].index; idx < int(startpg.count); idx++ {
            res = append(res, startpg.getElement(idx).value)
        }

        pgid := startpg.nextid
        for pgid != 0 {
            pg := bt.db.getpage(pgid)
            for idx := 0; idx < int(pg.count); idx++ {
                res = append(res, pg.getElement(idx).value)
            }
            pgid = pg.nextid
        }
        return true, res
    }

    bt.root = bt.db.getpage(bt.rootpgid)
    stack1 := make([]pagestack, 0)
    ok, _, _, _ := bt.root.search(start, &stack1, bt)
    if !ok {
        return false, nil
    }
    startpgid := stack1[len(stack1)-1].pageid

    stack2 := make([]pagestack, 0)
    ok, _, _, _ = bt.root.search(end, &stack2, bt)
    if !ok {
        return false, nil
    }
    endpgid := stack2[len(stack2)-1].pageid

    res := make([]uint64, 0)
    endpg := bt.db.getpage(endpgid)
    for idx := stack2[len(stack2)-1].index; idx < int(endpg.count); idx++ {
        res = append(res, endpg.getElement(idx).value)
    }

    pgid := endpg.nextid
    for pgid != startpgid && pgid != 0 {
        pg := bt.db.getpage(pgid)
        for idx := 0; idx < int(pg.count); idx++ {
            res = append(res, pg.getElement(idx).value)
        }
        pgid = pg.nextid
    }

    startpg := bt.db.getpage(startpgid)

    for idx := 0; idx < stack1[len(stack1)-1].index; idx++ {
        res = append(res, startpg.getElement(idx).value)
    }

    return true, res

}

func (bt *btree) GetFristKV() (string, uint32, uint32, int, bool) {

    if bt.rootpgid == 0 {
        return "", 0, 0, 0, false
    }

    node := bt.db.getpage(bt.rootpgid)
    return node.getfristkv(bt)

}

func (bt *btree) GetNextKV(pagenum uint32, index int) (string, uint32, uint32, int, bool) {
    if bt.rootpgid == 0 {
        return "", 0, 0, 0, false
    }

    node := bt.db.getpage(pagenum)
    if uint32(index+1) < node.count {
        ele := node.getElement(index + 1)
        return ele.key(), uint32(ele.value), node.curid, index + 1, true
    }
    if node.nextid == 0 {
        return "", 0, 0, 0, false
    }
    next := bt.db.getpage(node.nextid)
    if next.count > 0 {
        ele := node.getElement(0)
        return ele.key(), uint32(ele.value), next.curid, 0, true
    }
    return "", 0, 0, 0, false

}

func (bt *btree) Display() {
    bt.root.display(bt)
}

type metaBT struct {
    btname    [32]byte
    btnamelen uint32
    maxkeylen uint32
    rootpgid  uint32
}

func (mt *metaBT) key() string {
    return string(mt.btname[:mt.btnamelen])
}

func (mt *metaBT) setkey(key string) {
    if len(key) == 0 {
        return
    }
    if len(key) > 32 {
        copy(mt.btname[:], []byte(key)[:32])
        mt.btnamelen = 32
        return
    }
    copy(mt.btname[:len(key)], []byte(key)[:])
    mt.btnamelen = uint32(len(key))
    return
}

type metaInfo struct {
    magic   uint32
    maxpgid uint32
    btnum   uint32
    btinfos [64]metaBT
}

func (mi *metaInfo) addbt(name string, rootpgid uint32) error {

    mi.btinfos[mi.btnum].setkey(name)
    mi.btinfos[mi.btnum].rootpgid = rootpgid
    mi.btnum++
    return nil

}

const magicnum uint32 = 0x9EDFEDFA

type BTreedb struct {
    btmap     map[string]*btree // btree集合
    filename  string
    mmapbytes []byte
    //maxpgid   uint32
    fd   *os.File
    meta *metaInfo
}

func exist(filename string) bool {
    _, err := os.Stat(filename)
    return err == nil || os.IsExist(err)
}

func NewBTDB(dbname string) *BTreedb {

    //fmt.Printf("headoffset : %v \n", pageheadOffset)
    //fmt.Printf("elementSize: %v \n", elementSize)
    //fmt.Printf("pageheaadlen: %v \n", pageheaadlen)
    //fmt.Printf("btdbname : %v \n", dbname)
    file_create_mode := os.O_RDWR | os.O_CREATE | os.O_TRUNC
    this := &BTreedb{filename: dbname, btmap: make(map[string]*btree)}

    if exist(dbname) {
        file_create_mode = os.O_RDWR
    } else {
        file_create_mode = os.O_RDWR | os.O_CREATE | os.O_TRUNC
    }

    f, err := os.OpenFile(dbname, file_create_mode, 0664)
    if err != nil {
        return nil
    }

    fi, _ := f.Stat()
    filelen := fi.Size()
    //fmt.Printf("filelen : %v, %v \n", filelen, pagesize*2)
    if filelen < pagesize*2 {
        syscall.Ftruncate(int(f.Fd()), pagesize*2)
        filelen = pagesize * 2
        this.fd = f
        //var addr = unsafe.Pointer(&this.mmapbytes[0])
        this.mmapbytes, err = syscall.Mmap(int(f.Fd()), 0, int(filelen), syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED)
        //ptr, err := C.mmap(addr, C.size_t(filelen), C.PROT_READ|C.PROT_WRITE, C.MAP_SHARED, C.int(f.Fd()), 0)

        if err != nil {
            fmt.Printf("MAPPING ERROR  %v \n", err)
            return nil
        }
        //this.mmapbytes = ([]byte)(unsafe.Pointer(ptr))
        this.meta = (*metaInfo)(unsafe.Pointer(&this.mmapbytes[0]))
        this.meta.magic = magicnum
        this.meta.maxpgid = 1
        this.meta.btnum = 0
        return this
    }
    this.fd = f
    this.mmapbytes, err = syscall.Mmap(int(f.Fd()), 0, int(filelen), syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED)
    if err != nil {
        fmt.Printf("MAPPING ERROR  %v \n", err)
        return nil
    }
    this.meta = (*metaInfo)(unsafe.Pointer(&this.mmapbytes[0]))
    if this.meta.magic != magicnum {
        fmt.Printf("FILE TYPE ERROR \n")
        return nil
    }

    for i := uint32(0); i < this.meta.btnum; i++ {
        btname := this.meta.btinfos[i].key()
        root := this.getpage(this.meta.btinfos[i].rootpgid)
        this.btmap[btname] = loadbtree(btname, root, this) // this指向了db本身
    }

    return this
}

func (db *BTreedb) AddBTree(name string) error {

    if _, ok := db.btmap[name]; ok {
        fmt.Printf("ERROR:::%v\n", db.filename)
        return nil
    }
    //fmt.Printf("FILE:::%v\n", db.filename)
    bt := newbtree(name, db)
    if bt == nil {
        fmt.Printf("create error:::%v\n", name)
        return errors.New("create error")
    }
    db.btmap[name] = bt
    db.meta.addbt(name, bt.root.curid)
    db.Sync()
    return nil
}

func (db *BTreedb) header() *reflect.SliceHeader {
    return (*reflect.SliceHeader)(unsafe.Pointer(&db.mmapbytes))
}

func (db *BTreedb) Sync() error {
    dh := db.header()
    _, _, err := syscall.Syscall(syscall.SYS_MSYNC, dh.Data, uintptr(dh.Len), syscall.MS_SYNC)
    if err != 0 {
        fmt.Printf("Sync Error ")
        return errors.New("Sync Error")
    }
    return nil
}

func (db *BTreedb) Set(btname, key string, value uint64) error {

    if _, ok := db.btmap[btname]; !ok {
        return errors.New("has one")
    }

    return db.btmap[btname].Set(key, value)

}

func (db *BTreedb) IncValue(btname, key string) error {
    if _, ok := db.btmap[btname]; !ok {
        return errors.New("has one")
    }

    found, value := db.btmap[btname].Search(key)
    if found {
        return db.btmap[btname].Set(key, value+1)
    }
    return db.btmap[btname].Set(key, 1)

}

func (db *BTreedb) Search(btname, key string) (bool, uint64) {
    if _, ok := db.btmap[btname]; !ok {
        return false, 0
    }

    return db.btmap[btname].Search(key)

}

func (db *BTreedb) Range(btname, start, end string) (bool, []uint64) {

    if _, ok := db.btmap[btname]; !ok {
        return false, nil
    }

    if start >= end && len(end) > 0 && len(start) > 0 {
        fmt.Printf("START OVER END\n")
        return false, nil
    }

    return db.btmap[btname].Range(start, end)

}

func (db *BTreedb) GetFristKV(btname string) (string, uint32, uint32, int, bool) {
    if _, ok := db.btmap[btname]; !ok {
        return "", 0, 0, 0, false
    }

    return db.btmap[btname].GetFristKV()

}

func (db *BTreedb) GetNextKV(btname string, pagenum uint32, index int) (string, uint32, uint32, int, bool) {
    if _, ok := db.btmap[btname]; !ok {
        return "", 0, 0, 0, false
    }

    return db.btmap[btname].GetNextKV(pagenum, index)

}

func (db *BTreedb) Close() error {

    syscall.Munmap(db.mmapbytes)
    db.fd.Close()
    return nil
}

func (bt *BTreedb) newpage( /*parent, pre *page*/ parentid, preid uint32, pagetype uint8) (*page, *page, *page) {

    if bt.checkmmap() != nil {
        fmt.Printf("check error \n")
        return nil, nil, nil
    }
    var parent *page
    var pre *page
    lpage := (*page)(unsafe.Pointer(&bt.mmapbytes[(int64(bt.meta.maxpgid) * pagesize)]))
    //fmt.Printf("lapge:%v\n", unsafe.Pointer(lpage))
    lpage.curid = bt.meta.maxpgid
    lpage.pgtype = pagetype
    lpage.nextid = 0
    lpage.preid = 0
    if pagetype == tinterior {
        lpage.count = 1
        ele := (*[0xFFFF]element)(unsafe.Pointer(&bt.mmapbytes[(int64(bt.meta.maxpgid)*pagesize + pageheadOffset)]))
        lpage.used = uint32(pageheaadlen) //
        ele[0].setkv("", 0)
        lpage.elementsptr = uintptr(unsafe.Pointer(ele)) //

    } else {
        lpage.count = 0
        ele := (*[0xFFFF]element)(unsafe.Pointer(&bt.mmapbytes[(int64(bt.meta.maxpgid)*pagesize + pageheadOffset)]))
        lpage.elementsptr = uintptr(unsafe.Pointer(ele))
        lpage.used = uint32(pageheaadlen)
    }
    //fmt.Printf("lapge:%v\n", unsafe.Pointer(lpage))
    //fmt.Printf("parent:%v\n", unsafe.Pointer(parent))
    if parentid != 0 {
        parent = bt.getpage(parentid)
        lpage.parentpg = parent.curid
    } else {
        lpage.parentpg = 0
    }

    if preid != 0 {
        pre = bt.getpage(preid)
        lpage.nextid = pre.nextid
        pre.nextid = lpage.curid
        lpage.preid = pre.curid
    }

    bt.meta.maxpgid++
    return lpage, parent, pre
}

func (bt *BTreedb) checkmmap() error {
    if int(int64(bt.meta.maxpgid)*pagesize) >= len(bt.mmapbytes) {
        err := syscall.Ftruncate(int(bt.fd.Fd()), int64(bt.meta.maxpgid+1)*pagesize)
        if err != nil {
            fmt.Printf("ftruncate error : %v\n", err)
            return err
        }
        maxpgid := bt.meta.maxpgid
        syscall.Munmap(bt.mmapbytes)
        //fmt.Printf(".meta.maxpgid:%v\n",bt.meta.maxpgid)
        bt.mmapbytes, err = syscall.Mmap(int(bt.fd.Fd()), 0, int(int64( /*bt.meta.maxpgid*/ maxpgid+1)*pagesize), syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED)

        if err != nil {
            fmt.Printf("MAPPING ERROR  %v \n", err)
            return err
        }

        bt.meta = (*metaInfo)(unsafe.Pointer(&bt.mmapbytes[0]))

    }
    return nil
}

func (bt *BTreedb) getpage(pgid uint32) *page {
    //fmt.Printf("pgid:%v\n",pgid)
    return (*page)(unsafe.Pointer(&bt.mmapbytes[(int64(pgid) * pagesize)])) //直接在映射到內(nèi)存的文件取到一個page

}

func (db *BTreedb) setrootid(btname string) error {

    if _, ok := db.btmap[btname]; !ok {
        return errors.New("no bt")
    }

    for i := uint32(0); i < db.meta.btnum; i++ {
        if db.meta.btinfos[i].key() == btname {
            db.meta.btinfos[i].rootpgid = db.btmap[btname].root.curid
        }

    }

    return nil
}

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子提陶,更是在濱河造成了極大的恐慌丧荐,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機苏遥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赡模,“玉大人田炭,你說我怎么就攤上這事±旄蹋” “怎么了教硫?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵叨吮,是天一觀的道長。 經(jīng)常有香客問我瞬矩,道長茶鉴,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任景用,我火速辦了婚禮涵叮,結果婚禮上,老公的妹妹穿的比我還像新娘伞插。我一直安慰自己割粮,他們只是感情好,可當我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布媚污。 她就那樣靜靜地躺著舀瓢,像睡著了一般。 火紅的嫁衣襯著肌膚如雪耗美。 梳的紋絲不亂的頭發(fā)上京髓,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天,我揣著相機與錄音商架,去河邊找鬼朵锣。 笑死,一個胖子當著我的面吹牛甸私,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播飞傀,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼皇型,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了砸烦?” 一聲冷哼從身側(cè)響起弃鸦,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎幢痘,沒想到半個月后唬格,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡颜说,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年购岗,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片门粪。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡喊积,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出玄妈,到底是詐尸還是另有隱情乾吻,我是刑警寧澤髓梅,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站绎签,受9級特大地震影響枯饿,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜诡必,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一奢方、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧擒权,春花似錦袱巨、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至剖效,卻和暖如春嫉入,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背璧尸。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工咒林, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人爷光。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓垫竞,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蛀序。 傳聞我的和親對象是個殘疾皇子欢瞪,可洞房花燭夜當晚...
    茶點故事閱讀 44,864評論 2 354

推薦閱讀更多精彩內(nèi)容