package zones import ( "io/fs" "sort" ) func (m *Zones) scan() error { for _, fn := range []func() error{ m.scanDirectory, m.scanMachines, m.scanZoneIDs, m.scanSort, } { if err := fn(); err != nil { return err } } return nil } func (m *Zones) scanDirectory() error { // each directory is a zone entries, err := fs.ReadDir(m.dir, ".") if err != nil { return err } for _, e := range entries { if e.IsDir() { z := &Zone{ zones: m, Name: e.Name(), } if err := z.scan(); err != nil { return err } m.Zones = append(m.Zones, z) } } return nil } func (m *Zones) scanMachines() error { var err error m.ForEachMachine(func(p *Machine) bool { err = p.scan() return err != nil }) return err } func (m *Zones) scanZoneIDs() error { var hasMissing bool var lastZoneID int m.ForEachZone(func(z *Zone) bool { switch { case z.ID == 0: hasMissing = true case z.ID > lastZoneID: lastZoneID = z.ID } return false }) if hasMissing { next := lastZoneID + 1 m.ForEachZone(func(z *Zone) bool { if z.ID == 0 { z.ID, next = next, next+1 } return false }) } return nil } func (m *Zones) scanSort() error { sort.SliceStable(m.Zones, func(i, j int) bool { id1 := m.Zones[i].ID id2 := m.Zones[j].ID return id1 < id2 }) m.ForEachZone(func(z *Zone) bool { sort.SliceStable(z.Machines, func(i, j int) bool { id1 := z.Machines[i].ID() id2 := z.Machines[j].ID() return id1 < id2 }) return false }) m.ForEachMachine(func(p *Machine) bool { sort.SliceStable(p.RingAddresses, func(i, j int) bool { ri1 := p.RingAddresses[i] ri2 := p.RingAddresses[j] return ri1.Ring < ri2.Ring }) return false }) return nil } func (z *Zone) scan() error { // each directory is a machine entries, err := fs.ReadDir(z.zones.dir, z.Name) if err != nil { return err } for _, e := range entries { if e.IsDir() { m := &Machine{ zone: z, Name: e.Name(), } if err := m.init(); err != nil { return err } z.Machines = append(z.Machines, m) } } return nil }