1
0
mirror of https://github.com/osmarks/mycorrhiza.git synced 2024-12-16 06:50:26 +00:00
mycorrhiza/hyphae/hyphae.go

143 lines
2.9 KiB
Go
Raw Normal View History

2021-02-20 14:03:54 +00:00
// The `hyphae` package is for the Hypha type, hypha storage and stuff like that. It shall not depend on mycorrhiza modules other than util.
package hyphae
import (
2021-02-17 18:41:35 +00:00
"log"
"regexp"
"sync"
)
2021-02-17 18:41:35 +00:00
// HyphaPattern is a pattern which all hyphae must match.
var HyphaPattern = regexp.MustCompile(`[^?!:#@><*|"\'&%{}]+`)
type Hypha struct {
sync.RWMutex
Name string
Exists bool
TextPath string
BinaryPath string
2021-02-19 09:23:57 +00:00
OutLinks []*Hypha
BackLinks []*Hypha
2021-02-17 18:41:35 +00:00
}
var byNames = make(map[string]*Hypha)
var byNamesMutex = sync.Mutex{}
// EmptyHypha returns an empty hypha struct with given name.
func EmptyHypha(hyphaName string) *Hypha {
return &Hypha{
Name: hyphaName,
Exists: false,
TextPath: "",
BinaryPath: "",
OutLinks: make([]*Hypha, 0),
BackLinks: make([]*Hypha, 0),
}
}
// ByName returns a hypha by name. If h.Exists, the returned hypha pointer is known to be part of the hypha index (byNames map).
func ByName(hyphaName string) (h *Hypha) {
h, exists := byNames[hyphaName]
if exists {
return h
}
return EmptyHypha(hyphaName)
}
2021-02-17 18:41:35 +00:00
// Insert inserts the hypha into the storage. It overwrites the previous record, if there was any, and returns false. If the was no previous record, return true.
func (h *Hypha) Insert() (justCreated bool) {
hp := ByName(h.Name)
2021-02-17 18:41:35 +00:00
byNamesMutex.Lock()
defer byNamesMutex.Unlock()
if hp.Exists {
hp = h
2021-02-17 18:41:35 +00:00
} else {
h.Exists = true
byNames[h.Name] = h
IncrementCount()
}
2021-02-17 18:41:35 +00:00
return !hp.Exists
}
2021-02-17 18:41:35 +00:00
func (h *Hypha) InsertIfNew() (justCreated bool) {
if !h.Exists {
2021-02-17 18:41:35 +00:00
return h.Insert()
}
return false
}
2021-02-19 09:23:57 +00:00
func (h *Hypha) InsertIfNewKeepExistence() {
hp := ByName(h.Name)
byNamesMutex.Lock()
defer byNamesMutex.Unlock()
if hp.Exists {
hp = h
} else {
byNames[h.Name] = h
}
}
2021-02-20 14:03:54 +00:00
func (h *Hypha) Delete() {
2021-02-17 18:41:35 +00:00
byNamesMutex.Lock()
h.Lock()
delete(byNames, h.Name)
DecrementCount()
byNamesMutex.Unlock()
h.Unlock()
}
2021-02-20 14:03:54 +00:00
func (h *Hypha) RenameTo(newName string) {
2021-02-17 18:41:35 +00:00
byNamesMutex.Lock()
h.Lock()
2021-02-17 18:41:35 +00:00
delete(byNames, h.Name)
h.Name = newName
byNames[h.Name] = h
byNamesMutex.Unlock()
h.Unlock()
}
2021-02-17 18:41:35 +00:00
// MergeIn merges in content file paths from a different hypha object. Prints warnings sometimes.
func (h *Hypha) MergeIn(oh *Hypha) {
if h.TextPath == "" && oh.TextPath != "" {
h.TextPath = oh.TextPath
}
if oh.BinaryPath != "" {
if h.BinaryPath != "" {
log.Println("There is a file collision for binary part of a hypha:", h.BinaryPath, "and", oh.BinaryPath, "-- going on with the latter")
}
h.BinaryPath = oh.BinaryPath
}
}
2021-02-20 14:03:54 +00:00
// Link related stuff:
func (h *Hypha) AddOutLink(oh *Hypha) (added bool) {
h.Lock()
defer h.Unlock()
for _, outlink := range h.OutLinks {
if outlink == oh {
return false
}
}
h.OutLinks = append(h.OutLinks, oh)
return true
}
func (h *Hypha) AddBackLink(bh *Hypha) (added bool) {
h.Lock()
defer h.Unlock()
for _, backlink := range h.BackLinks {
if backlink == h {
return false
}
}
h.BackLinks = append(h.BackLinks, bh)
return true
}