package forgepb // TODO: autogen this? (probably not feasible. need go-arglike tricks in proto) import ( "fmt" "os" "sort" sync "sync" "time" ) // bad global lock until I figure out some other plan var forgeConfigsLock sync.RWMutex type ForgeConfigIterator struct { sync.RWMutex packs []*ForgeConfig index int } // newForgeConfigIterator initializes a new iterator. func newForgeConfigIterator(packs []*ForgeConfig) *ForgeConfigIterator { return &ForgeConfigIterator{packs: packs} } // Scan moves to the next element and returns false if there are no more packs. func (it *ForgeConfigIterator) Scan() bool { if it.index >= len(it.packs) { return false } it.index++ return true } // ForgeConfig returns the current forgeConfig. func (it *ForgeConfigIterator) Next() *ForgeConfig { if it.packs[it.index-1] == nil { for i, d := range it.packs { fmt.Println("i =", i, d) } fmt.Println("len =", len(it.packs)) fmt.Println("forgeConfig == nil", it.index, it.index-1) os.Exit(-1) } return it.packs[it.index-1] } // Use Scan() in a loop, similar to a while loop // // for iterator.Scan() { // d := iterator.ForgeConfig() // fmt.Println("ForgeConfig UUID:", d.Uuid) // } func (r *ForgeConfigs) All() *ForgeConfigIterator { forgeConfigPointers := r.selectAllForgeConfigs() iterator := newForgeConfigIterator(forgeConfigPointers) return iterator } func (r *ForgeConfigs) SortByPath() *ForgeConfigIterator { packs := r.selectAllForgeConfigs() sort.Sort(byForgeConfigPath(packs)) iterator := newForgeConfigIterator(packs) return iterator } // enforces no duplicate forgeConfig paths func (r *ForgeConfigs) Append(newP *ForgeConfig) bool { forgeConfigsLock.Lock() defer forgeConfigsLock.Unlock() for _, p := range r.ForgeConfigs { if p.GoPath == newP.GoPath { return false } } r.ForgeConfigs = append(r.ForgeConfigs, newP) return true } // returns time.Duration since last Update() func (r *ForgeConfig) Age(newP *ForgeConfig) time.Duration { t := time.Since(r.Verstamp.AsTime()) return t } // find a forgeConfig by path func (r *ForgeConfigs) FindByPath(gopath string) *ForgeConfig { forgeConfigsLock.RLock() defer forgeConfigsLock.RUnlock() for _, p := range r.ForgeConfigs { if p.GoPath == gopath { return p } } return nil } func (r *ForgeConfigs) Len() int { forgeConfigsLock.RLock() defer forgeConfigsLock.RUnlock() return len(r.ForgeConfigs) } type byForgeConfigPath []*ForgeConfig func (a byForgeConfigPath) Len() int { return len(a) } func (a byForgeConfigPath) Less(i, j int) bool { return a[i].GoPath < a[j].GoPath } func (a byForgeConfigPath) Swap(i, j int) { a[i], a[j] = a[j], a[i] } func (all *ForgeConfigs) DeleteByPath(gopath string) *ForgeConfig { forgeConfigsLock.Lock() defer forgeConfigsLock.Unlock() var newr ForgeConfig for i, _ := range all.ForgeConfigs { if all.ForgeConfigs[i].GoPath == gopath { newr = *all.ForgeConfigs[i] all.ForgeConfigs[i] = all.ForgeConfigs[len(all.ForgeConfigs)-1] all.ForgeConfigs = all.ForgeConfigs[:len(all.ForgeConfigs)-1] return &newr } } return nil } // safely returns a slice of pointers to the ForgeConfig protobufs func (r *ForgeConfigs) selectAllForgeConfigs() []*ForgeConfig { forgeConfigsLock.RLock() defer forgeConfigsLock.RUnlock() // Create a new slice to hold pointers to each ForgeConfig var allPacks []*ForgeConfig allPacks = make([]*ForgeConfig, len(r.ForgeConfigs)) for i, p := range r.ForgeConfigs { allPacks[i] = p // Copy pointers for safe iteration } return allPacks }