示例#1
0
文件: restore.go 项目: maruel/dumbcas
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
}
示例#2
0
文件: info.go 项目: maruel/dumbcas
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
}
示例#3
0
文件: gc.go 项目: maruel/dumbcas
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
}
示例#4
0
文件: fsck.go 项目: maruel/dumbcas
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
}