mirror of
https://github.com/terorie/od-database-crawler.git
synced 2025-12-12 14:58:51 +00:00
Beta task resuming
This commit is contained in:
@@ -15,7 +15,10 @@ package redblackhash
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"sync"
|
||||
)
|
||||
|
||||
@@ -43,6 +46,13 @@ type Node struct {
|
||||
Parent *Node
|
||||
}
|
||||
|
||||
type nodeHeader struct {
|
||||
Key *Key
|
||||
Color color
|
||||
}
|
||||
|
||||
var o = binary.BigEndian
|
||||
|
||||
func (k *Key) Compare(o *Key) int {
|
||||
return bytes.Compare(k[:], o[:])
|
||||
}
|
||||
@@ -233,7 +243,7 @@ func (tree *Tree) String() string {
|
||||
}
|
||||
|
||||
func (node *Node) String() string {
|
||||
return fmt.Sprintf("%v", node.Key)
|
||||
return hex.EncodeToString(node.Key[:16]) + "..."
|
||||
}
|
||||
|
||||
func output(node *Node, prefix string, isTail bool, str *string) {
|
||||
@@ -481,6 +491,119 @@ func (tree *Tree) deleteCase6(node *Node) {
|
||||
}
|
||||
}
|
||||
|
||||
func (tree *Tree) Marshal(w io.Writer) (err error) {
|
||||
tree.Lock()
|
||||
defer tree.Unlock()
|
||||
|
||||
err = binary.Write(w, o, uint64(0x617979797979790A))
|
||||
if err != nil { return err }
|
||||
|
||||
err = marshal(tree.Root, w)
|
||||
if err != nil { return err }
|
||||
|
||||
err = binary.Write(w, o, uint64(0x6C6D616F6F6F6F0A))
|
||||
if err != nil { return err }
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func marshal(n *Node, w io.Writer) (err error) {
|
||||
if n == nil {
|
||||
err = binary.Write(w, o, uint64(0x796565656565740A))
|
||||
return err
|
||||
}
|
||||
|
||||
err = binary.Write(w, o, uint64(0xF09F85B1EFB88F0A))
|
||||
if err != nil { return err }
|
||||
|
||||
_, err = w.Write(n.Key[:])
|
||||
if err != nil { return err }
|
||||
|
||||
var colorI uint64
|
||||
if n.color {
|
||||
colorI = 0x7468652D6579657C
|
||||
} else {
|
||||
colorI = 0x6865782B7465727C
|
||||
}
|
||||
|
||||
err = binary.Write(w, o, colorI)
|
||||
if err != nil { return err }
|
||||
|
||||
err = marshal(n.Left, w)
|
||||
if err != nil { return err }
|
||||
|
||||
err = marshal(n.Right, w)
|
||||
if err != nil { return err }
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tree *Tree) Unmarshal(r io.Reader) (err error) {
|
||||
tree.Lock()
|
||||
defer tree.Unlock()
|
||||
|
||||
var sof uint64
|
||||
err = binary.Read(r, o, &sof)
|
||||
if err != nil { return err }
|
||||
if sof != 0x617979797979790A {
|
||||
return fmt.Errorf("redblack: wrong format")
|
||||
}
|
||||
|
||||
tree.Root, tree.size, err = unmarshal(r)
|
||||
if err != nil { return err }
|
||||
|
||||
var eof uint64
|
||||
err = binary.Read(r, o, &eof)
|
||||
if err != nil { return err }
|
||||
if eof != 0x6C6D616F6F6F6F0A {
|
||||
return fmt.Errorf("redblack: end of file missing")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func unmarshal(r io.Reader) (n *Node, size int, err error) {
|
||||
var head uint64
|
||||
err = binary.Read(r, o, &head)
|
||||
if err != nil { return nil, 0, err }
|
||||
|
||||
size = 1
|
||||
|
||||
switch head {
|
||||
case 0x796565656565740A:
|
||||
return nil, 0, nil
|
||||
case 0xF09F85B1EFB88F0A:
|
||||
n = new(Node)
|
||||
|
||||
_, err = io.ReadFull(r, n.Key[:])
|
||||
if err != nil { return nil, 0, err }
|
||||
|
||||
var colorInt uint64
|
||||
err = binary.Read(r, o, &colorInt)
|
||||
if err != nil { return nil, 0, err }
|
||||
switch colorInt {
|
||||
case 0x7468652D6579657C:
|
||||
n.color = true
|
||||
case 0x6865782B7465727C:
|
||||
n.color = false
|
||||
default:
|
||||
return nil, 0, fmt.Errorf("redblack: corrupt node color")
|
||||
}
|
||||
default:
|
||||
return nil, 0, fmt.Errorf("redblack: corrupt node info")
|
||||
}
|
||||
|
||||
var s2 int
|
||||
n.Left, s2, err = unmarshal(r)
|
||||
size += s2
|
||||
if err != nil { return nil, 0, err }
|
||||
n.Right, s2, err = unmarshal(r)
|
||||
size += s2
|
||||
if err != nil { return nil, 0, err }
|
||||
|
||||
return n, size, nil
|
||||
}
|
||||
|
||||
func nodeColor(node *Node) color {
|
||||
if node == nil {
|
||||
return black
|
||||
|
||||
47
ds/redblackhash/redblack_test.go
Normal file
47
ds/redblackhash/redblack_test.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package redblackhash
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"math/rand"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTree_Marshal(t *testing.T) {
|
||||
var t1, t2 Tree
|
||||
|
||||
// Generate 1000 random values to insert
|
||||
for i := 0; i < 1000; i++ {
|
||||
var key Key
|
||||
rand.Read(key[:])
|
||||
t1.Put(&key)
|
||||
}
|
||||
|
||||
// Marshal tree
|
||||
var wr bytes.Buffer
|
||||
err := t1.Marshal(&wr)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
buf := wr.Bytes()
|
||||
rd := bytes.NewBuffer(buf)
|
||||
|
||||
// Unmarshal tree
|
||||
err = t2.Unmarshal(rd)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
if !compare(t1.Root, t2.Root) {
|
||||
t.Error("trees are not equal")
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
func compare(n1, n2 *Node) bool {
|
||||
return n1.Key.Compare(&n2.Key) == 0 &&
|
||||
(n1.Left == nil || compare(n1.Left, n2.Left)) &&
|
||||
(n1.Right == nil || compare(n1.Right, n2.Right))
|
||||
}
|
||||
Reference in New Issue
Block a user