func (c *restoreRun) main(a DumbcasApplication, nodeArg string) error { if err := c.Parse(a, true); err != nil { return err } // Load the Node and process it. // Do it serially for now, assuming that it is I/O bound on magnetic disks. // For a network CAS, it would be good to implement concurrent fetches. f, err := c.nodes.Open(nodeArg) if err != nil { return err } defer func() { _ = f.Close() }() node := &dumbcaslib.Node{} if err := dumbcaslib.LoadReaderAsJSON(f, node); err != nil { return err } entry, err := dumbcaslib.LoadEntry(c.cas, node.Entry) if err != nil { return err } // TODO(maruel): Progress bar. count, err := restoreEntry(a.GetLog(), c.cas, entry, c.Out) fmt.Fprintf(a.GetOut(), "Restored %d files in %s\n", count, c.Out) return err }
func (c *infoRun) main(a DumbcasApplication, nodeArg string) error { if err := c.Parse(a, true); err != nil { return err } // Load the Node and process it. f, err := c.nodes.Open(nodeArg) if err != nil { return err } defer func() { _ = f.Close() }() node := &dumbcaslib.Node{} if err := dumbcaslib.LoadReaderAsJSON(f, node); err != nil { return err } entry, err := dumbcaslib.LoadEntry(c.cas, node.Entry) if err != nil { return err } count := printEntry(a.GetOut(), entry, "") fmt.Fprintf(a.GetOut(), "Total %d\n", count) return nil }
func (c *gcRun) main(a DumbcasApplication) error { if err := c.Parse(a, false); err != nil { return err } entries := map[string]bool{} for item := range c.cas.Enumerate() { if item.Error != nil { // TODO(maruel): Leaks channel. c.cas.SetFsckBit() return fmt.Errorf("Failed enumerating the CAS table %s", item.Error) } entries[item.Item] = false } a.GetLog().Printf("Found %d entries", len(entries)) // Load all the nodes. for item := range c.nodes.Enumerate() { if item.Error != nil { // TODO(maruel): Leaks channel. return item.Error } f, err := c.nodes.Open(item.Item) if err != nil { // TODO(maruel): Leaks channel. c.cas.SetFsckBit() return fmt.Errorf("Failed opening node %s: %s", item.Item, err) } defer func() { _ = f.Close() }() node := &dumbcaslib.Node{} if err := dumbcaslib.LoadReaderAsJSON(f, node); err != nil { // TODO(maruel): Leaks channel. c.cas.SetFsckBit() return fmt.Errorf("Failed opening node %s: %s", item.Item, err) } entries[node.Entry] = true entry, err := dumbcaslib.LoadEntry(c.cas, node.Entry) if err != nil { return err } tagRecurse(entries, entry) } orphans := []string{} for entry, tagged := range entries { if !tagged { orphans = append(orphans, entry) } } a.GetLog().Printf("Found %d orphan", len(orphans)) for _, orphan := range orphans { if err := c.cas.Remove(orphan); err != nil { c.cas.SetFsckBit() return fmt.Errorf("Internal error while removing %s: %s", orphan, err) } } return nil }
func (c *fsckRun) main(a DumbcasApplication) error { if err := c.Parse(a, true); err != nil { return err } count := 0 corrupted := 0 for item := range c.cas.Enumerate() { if item.Error != nil { a.GetLog().Printf("While enumerating the CAS table: %s", item.Error) continue } count++ f, err := c.cas.Open(item.Item) if err != nil { // TODO(maruel): Leaks channel. return fmt.Errorf("Failed to open %s: %s", item.Item, err) } defer func() { _ = f.Close() }() actual, err := sha1Reader(f) if err != nil { // Probably Disk error. // TODO(maruel): Leaks channel. return fmt.Errorf("Aborting! Failed to calcultate the sha1 of %s: %s. Please find a valid copy of your CAS table ASAP.", item.Item, err) } if actual != item.Item { corrupted++ a.GetLog().Printf("Found corrupted object, %s != %s", item.Item, actual) if err := c.cas.Remove(item.Item); err != nil { // TODO(maruel): Leaks channel. return fmt.Errorf("Failed to trash object %s: %s", item.Item, err) } } } a.GetLog().Printf("Scanned %d entries in CasTable; found %d corrupted.", count, corrupted) // TODO(maruel): Get the value from CasTable. hashLength := 40 resha1 := regexp.MustCompile(fmt.Sprintf("^([a-f0-9]{%d})$", hashLength)) count = 0 corrupted = 0 for item := range c.nodes.Enumerate() { // TODO(maruel): Can't differentiate between an I/O error or a corrupted node. // NodesTable.Enumerate() automatically clears corrupted nodes. // TODO(maruel): This is a layering error. if item.Error != nil { a.GetLog().Printf("While enumerating the Nodes table: %s", item.Error) continue } count++ f, err := c.nodes.Open(item.Item) if err != nil { a.GetLog().Printf("Failed opening node %s: %s", item.Item, err) _ = c.nodes.Remove(item.Item) corrupted++ continue } defer func() { _ = f.Close() }() node := &dumbcaslib.Node{} if err := dumbcaslib.LoadReaderAsJSON(f, node); err != nil { a.GetLog().Printf("Failed opening node %s: %s", item.Item, err) _ = c.nodes.Remove(item.Item) corrupted++ continue } if !resha1.MatchString(node.Entry) { a.GetLog().Printf("Node %s is corrupted: %v", item.Item, node) _ = c.nodes.Remove(item.Item) corrupted++ continue } } a.GetLog().Printf("Scanned %d entries in NodesTable; found %d corrupted.", count, corrupted) c.cas.ClearFsckBit() return nil }