swarm/storage: fix garbage collector index skew (#18080)

On file access LDBStore's tryAccessIdx() function created a faulty
GC Index Data entry, because not indexing the ikey correctly.
That caused the chunk addresses/hashes to start with '00' and the last
two digits were dropped. => Incorrect chunk address.

Besides the fix, the commit also contains a schema change which will
run the CleanGCIndex() function to clean the GC index from erroneous
entries.

Note: CleanGCIndex() rebuilds the index from scratch which can take
a really-really long time with a huge DB (possibly an hour).
This commit is contained in:
Ferenc Szabo
2018-11-13 15:22:53 +01:00
committed by Anton Evangelatov
parent 4fecc7a3b1
commit c41e1bd1eb
4 changed files with 271 additions and 57 deletions

View File

@@ -196,31 +196,48 @@ func (ls *LocalStore) Close() {
// Migrate checks the datastore schema vs the runtime schema, and runs migrations if they don't match
func (ls *LocalStore) Migrate() error {
schema, err := ls.DbStore.GetSchema()
actualDbSchema, err := ls.DbStore.GetSchema()
if err != nil {
log.Error(err.Error())
return err
}
log.Debug("found schema", "schema", schema, "runtime-schema", CurrentDbSchema)
if schema != CurrentDbSchema {
// run migrations
log.Debug("running migrations for", "schema", actualDbSchema, "runtime-schema", CurrentDbSchema)
if schema == "" {
log.Debug("running migrations for", "schema", schema, "runtime-schema", CurrentDbSchema)
// delete chunks that are not valid, i.e. chunks that do not pass any of the ls.Validators
ls.DbStore.Cleanup(func(c *chunk) bool {
return !ls.isValid(c)
})
err := ls.DbStore.PutSchema(DbSchemaPurity)
if err != nil {
log.Error(err.Error())
return err
}
}
if actualDbSchema == CurrentDbSchema {
return nil
}
if actualDbSchema == DbSchemaNone {
ls.migrateFromNoneToPurity()
actualDbSchema = DbSchemaPurity
}
if err := ls.DbStore.PutSchema(actualDbSchema); err != nil {
return err
}
if actualDbSchema == DbSchemaPurity {
if err := ls.migrateFromPurityToHalloween(); err != nil {
return err
}
actualDbSchema = DbSchemaHalloween
}
if err := ls.DbStore.PutSchema(actualDbSchema); err != nil {
return err
}
return nil
}
func (ls *LocalStore) migrateFromNoneToPurity() {
// delete chunks that are not valid, i.e. chunks that do not pass
// any of the ls.Validators
ls.DbStore.Cleanup(func(c *chunk) bool {
return !ls.isValid(c)
})
}
func (ls *LocalStore) migrateFromPurityToHalloween() error {
return ls.DbStore.CleanGCIndex()
}