golang/leveldb

open() does only work with the Reader not with the writer

GoogleCodeExporter opened this issue · 3 comments


package main

import (
    "code.google.com/p/leveldb-go/leveldb/db"
    "code.google.com/p/leveldb-go/leveldb/table"
    "runtime"
)


const (
    DBFILE = "/tmp/leveldb2.db"
)

var DBFS = db.DefaultFileSystem 


func main() {
    Connection, e := DBFS.Create(DBFILE); Check(e)
    w := table.NewWriter(Connection,nil)
    defer w.Close()

    e = w.Set([]byte("1"), []byte("red"),nil); Check(e)
    e = w.Set([]byte("2"), []byte("yellow"),nil); Check(e)
    e = w.Set([]byte("3"), []byte("red"),nil); Check(e) 
    w.Close()
    w = nil
    Connection, e = DBFS.Open(DBFILE); Check(e)
    w = table.NewWriter(Connection,nil)
    defer w.Close() 
    e = w.Set([]byte("4"), []byte("red"),nil); Check(e)
    e = w.Set([]byte("5"), []byte("yellow"),nil); Check(e)
    e = w.Set([]byte("6"), []byte("red"),nil); Check(e)
    w.Close()
    read()
}

func read() {
    Connection, e := DBFS.Open(DBFILE); Check(e)
    b := []byte("0")
    r := table.NewReader(Connection,nil)
    iter := r.Find(b, nil)
    for iter.Next() {
        p(iter.Value(), nil)
    }
    r.Close()
}

func Check(e error) {
    if e != nil {
        _, file, line, _ := runtime.Caller(0)
        println(line, " File: ", file, "Error: ", e)
    }
}

func p(r []byte, e error) {
    if e != nil {
        println("Error: ", e)
    }
    println(string(r))      
}

Original issue reported on code.google.com by grues...@gmail.com on 29 Aug 2012 at 6:54

I'm not sure exactly what the problem is. I ran your example program and I get 
"red\nyellow\nred\n" with no error messages. I'll make a couple of points.

One is that you're not checking the error returned from w.Close or from r.Close.

Two is that the leveldb-go docs are admittedly incomplete, but DBFS.Open and 
DBFS.Create are like os.Open and os.Create. The docs at 
http://golang.org/pkg/os/#Open and http://golang.org/pkg/os/#Create say that 
Open returns a read-only file and Create returns a writable file. For example, 
this program:

--------
package main

import (
    "os"
)

func main(){
    f, err := os.Open("/tmp/leveldb2.db")
    if err != nil {
        println(err.Error())
    }
    _, err = f.Write([]byte("abc"))
    if err != nil {
        println(err.Error())
    }
}
--------

yields an error when run:
$ go run main.go 
write /tmp/leveldb2.db: bad file descriptor

I'm going to close this issue, but please re-open it if you think there's still 
a problem.

Original comment by nigel...@golang.org on 30 Aug 2012 at 2:22

  • Changed state: WontFix
First I like to thank you for your work, your pointers, and for your patience 
with me; since I am just a hobby programmer.

I did try it first the Go way with create, but that seams to be overwriting the 
whole database.
Here is  an improved example:

package main

import (
    "code.google.com/p/leveldb-go/leveldb/db"
    "code.google.com/p/leveldb-go/leveldb/table"
    "runtime"
)

func Check(e error) {
    if e != nil {
        _, file, line, _ := runtime.Caller(1)
        println(line, " File: ", file, "Error: ", e)
    }
}

func p(r []byte, e error) {
    if e != nil {
        println("Error: ", e)
    }
    println(string(r))      
}

const (
    DBFILE = "/tmp/leveldb2.db"
)

var DBFS = db.DefaultFileSystem 


func main() {
    Connection, e := DBFS.Create(DBFILE); Check(e)
    w := table.NewWriter(Connection,nil)
    defer w.Close()

    e = w.Set([]byte("1"), []byte("red"),nil); Check(e)
    e = w.Set([]byte("2"), []byte("yellow"),nil); Check(e)
    e = w.Set([]byte("3"), []byte("blue"),nil); Check(e)    
    e = w.Close(); Check(e)
    w = nil
    Connection, e = DBFS.Create(DBFILE); Check(e)
    w = table.NewWriter(Connection,nil)
    defer w.Close() 
    e = w.Set([]byte("4"), []byte("green"),nil); Check(e)
    e = w.Set([]byte("5"), []byte("white"),nil); Check(e)
    e = w.Set([]byte("6"), []byte("black"),nil); Check(e)
    e = w.Close(); Check(e)
    read()
}

func read() {
    Connection, e := DBFS.Open(DBFILE); Check(e)
    b := []byte("0")
    r := table.NewReader(Connection,nil)
    iter := r.Find(b, nil)
    for iter.Next() {
        p(iter.Value(), nil)
    }
    e = r.Close(); Check(e)
}

Original comment by grues...@gmail.com on 30 Aug 2012 at 3:04

Like os.Create, DBFS.Create will truncate the file if it already exists.

Running "godoc code.google.com/p/leveldb-go/leveldb/table" says that "Tables 
are either opened for reading or created for writing but not both."

The table format can only be written once. You cannot add entries to an 
existing on-disk table after it has been finalized (i.e. after w.Close has been 
called). When building a table, key/value pairs also have to be added in 
increasing key order.

If you want to add entries in random key order, or add entries to an existing 
DB, or delete entries from an existing DB, then you want the top-level 
c.g.c/p/l/leveldb package, not c.g.c/p/l/leveldb/table. However, that top-level 
package is not finished yet: this is issue 4.

Original comment by nigel...@golang.org on 30 Aug 2012 at 5:23