Commit 9374de2a authored by Luke Champine's avatar Luke Champine

add header to journal file

parent 71f05cb7
......@@ -27,9 +27,15 @@ import (
"github.com/NebulousLabs/Sia/build"
"github.com/NebulousLabs/Sia/crypto"
"github.com/NebulousLabs/Sia/modules"
"github.com/NebulousLabs/Sia/persist"
"github.com/NebulousLabs/Sia/types"
)
var journalMeta = persist.Metadata{
Header: "Contractor Journal",
Version: "1.0.0",
}
// A journal is a log of updates to a JSON object.
type journal struct {
f *os.File
......@@ -53,7 +59,11 @@ func (j *journal) checkpoint(data contractorPersist) error {
if err != nil {
return err
}
if err := json.NewEncoder(tmp).Encode(data); err != nil {
enc := json.NewEncoder(tmp)
if err := enc.Encode(journalMeta); err != nil {
return err
}
if err := enc.Encode(data); err != nil {
return err
}
if err := tmp.Sync(); err != nil {
......@@ -88,8 +98,13 @@ func newJournal(filename string) (*journal, error) {
if err != nil {
return nil, err
}
var initObj contractorPersist
if err := json.NewEncoder(f).Encode(initObj); err != nil {
// write metadata
enc := json.NewEncoder(f)
if err := enc.Encode(journalMeta); err != nil {
return nil, err
}
// write empty contractorPersist
if err := enc.Encode(contractorPersist{}); err != nil {
return nil, err
}
if err := f.Sync(); err != nil {
......@@ -107,8 +122,16 @@ func openJournal(filename string, data *contractorPersist) (*journal, error) {
return nil, err
}
// decode the initial object
// decode metadata
dec := json.NewDecoder(f)
var meta persist.Metadata
if err = dec.Decode(&meta); err != nil {
return nil, err
} else if meta.Version != journalMeta.Version {
return nil, errors.New("incompatible version")
}
// decode the initial object
if err = dec.Decode(data); err != nil {
return nil, err
}
......
......@@ -8,6 +8,7 @@ import (
"testing"
"github.com/NebulousLabs/Sia/build"
"github.com/NebulousLabs/Sia/crypto"
"github.com/NebulousLabs/Sia/types"
)
......@@ -86,53 +87,59 @@ func TestJournalCheckpoint(t *testing.T) {
}
}
func TestJournalMalformed(t *testing.T) {
f, cleanup := tempFile(t, "TestJournalMalformed")
func TestJournalMalformedJSON(t *testing.T) {
j, cleanup := tempJournal(t, "TestJournalMalformed")
defer cleanup()
// write a partially-malformed log
f.WriteString(`{"cachedrevisions":{}}
[{"t":"cachedDownloadRevision","d":{"revision":{"parentid":"1000000000000000000000000000000000000000000000000000000000000000"}},"c":"24cf20c26569ade37fc8948532bbcb113f8550d00ee01ab530026f44f4d6f1b4"}]
[{"t":"cachedDownloadRevision","d":{"revision":{"parentid":"2000000000000000000000000000000000000000000000000000000000000000"
`)
f.Close()
// write a valid update
err := j.update(updateSet{updateCachedDownloadRevision{}})
if err != nil {
t.Fatal(err)
}
// write a partially-malformed update
j.f.WriteString(`[{"t":"cachedDownloadRevision","d":{"revision":{"parentid":"1000000000000000000000000000000000000000000000000000000000000000"`)
// load log
var data contractorPersist
j, err := openJournal(f.Name(), &data)
j, err = openJournal(j.filename, &data)
if err != nil {
t.Fatal(err)
}
j.Close()
// the last update set should have been discarded
if _, ok := data.CachedRevisions["1000000000000000000000000000000000000000000000000000000000000000"]; !ok {
t.Fatal("log was not applied correctly:", data)
if _, ok := data.CachedRevisions[crypto.Hash{}.String()]; !ok {
t.Fatal("log was not applied correctly:", data.CachedRevisions)
}
}
// write a log with a bad checksum
f, cleanup = tempFile(t, "TestJournalMalformed2")
func TestJournalBadChecksum(t *testing.T) {
// test bad checksum
j, cleanup := tempJournal(t, "TestJournalMalformed2")
defer cleanup()
// write a partially-malformed log
f.WriteString(`{"cachedrevisions":{}}
[{"t":"cachedDownloadRevision","d":{"revision":{"parentid":"1000000000000000000000000000000000000000000000000000000000000000"}},"c":"24cf20c26569ade37fc8948532bbcb113f8550d00ee01ab530026f44f4d6f1b4"}]
[{"t":"cachedDownloadRevision","d":{"revision":{"parentid":"2000000000000000000000000000000000000000000000000000000000000000"}},"c":"bad checksum"}]
`)
f.Close()
// write a valid update
err := j.update(updateSet{updateCachedDownloadRevision{}})
if err != nil {
t.Fatal(err)
}
// write an update with a bad checksum
j.f.WriteString(`[{"t":"cachedDownloadRevision","d":{"revision":{"parentid":"2000000000000000000000000000000000000000000000000000000000000000"}},"c":"bad checksum"}]`)
// load log
j, err = openJournal(f.Name(), &data)
var data contractorPersist
j, err = openJournal(j.filename, &data)
if err != nil {
t.Fatal(err)
}
j.Close()
// the last update set should have been discarded
if _, ok := data.CachedRevisions["1000000000000000000000000000000000000000000000000000000000000000"]; !ok {
if _, ok := data.CachedRevisions[crypto.Hash{}.String()]; !ok {
t.Fatal("log was not applied correctly:", data)
}
}
func BenchmarkUpdateJournal(b *testing.B) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment