mirror of
https://github.com/Theodor-Springmann-Stiftung/lenz-web.git
synced 2025-10-29 09:15:33 +00:00
Iterators in XMLProvider doing the locking
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
package xmlparsing
|
package xmlparsing
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"iter"
|
||||||
"slices"
|
"slices"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -36,7 +37,6 @@ type XMLParser[T IXMLItem] struct {
|
|||||||
// INFO: map is type map[string]*T
|
// INFO: map is type map[string]*T
|
||||||
Items sync.Map
|
Items sync.Map
|
||||||
// INFO: map is type [string]ItemInfo
|
// INFO: map is type [string]ItemInfo
|
||||||
// It keeps information about parsing status of the items.
|
|
||||||
Infos sync.Map
|
Infos sync.Map
|
||||||
|
|
||||||
// INFO: Resolver is used to resolve references (back-links) between XML items.
|
// INFO: Resolver is used to resolve references (back-links) between XML items.
|
||||||
@@ -44,8 +44,7 @@ type XMLParser[T IXMLItem] struct {
|
|||||||
|
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
// TODO: This array is meant to be for iteration purposes, since iteration over the sync.Map is slow.
|
// TODO: This array is meant to be for iteration purposes, since iteration over the sync.Map is slow.
|
||||||
// It is best for this array to be sorted by key of the corresponding item.
|
array []T
|
||||||
Array []T
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewXMLParser[T IXMLItem]() *XMLParser[T] {
|
func NewXMLParser[T IXMLItem]() *XMLParser[T] {
|
||||||
@@ -59,7 +58,7 @@ func (p *XMLParser[T]) Prepare() {
|
|||||||
p.mu.Lock()
|
p.mu.Lock()
|
||||||
defer p.mu.Unlock()
|
defer p.mu.Unlock()
|
||||||
|
|
||||||
p.Array = make([]T, 0, len(p.Array))
|
p.array = make([]T, 0, len(p.array))
|
||||||
p.Resolver.Clear()
|
p.Resolver.Clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +81,7 @@ func (p *XMLParser[T]) Serialize(dataholder XMLRootElement[T], path string, late
|
|||||||
|
|
||||||
p.mu.Lock()
|
p.mu.Lock()
|
||||||
defer p.mu.Unlock()
|
defer p.mu.Unlock()
|
||||||
p.Array = append(p.Array, newItems...)
|
p.array = append(p.array, newItems...)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,7 +117,7 @@ func (p *XMLParser[T]) Cleanup(latest ParseMeta) {
|
|||||||
p.mu.Lock()
|
p.mu.Lock()
|
||||||
defer p.mu.Unlock()
|
defer p.mu.Unlock()
|
||||||
for _, item := range toappend {
|
for _, item := range toappend {
|
||||||
p.Array = append(p.Array, *item)
|
p.array = append(p.array, *item)
|
||||||
p.addResolvable(*item)
|
p.addResolvable(*item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -151,8 +150,10 @@ func (p *XMLParser[T]) ReverseLookup(item IXMLItem) []Resolved[T] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *XMLParser[T]) String() string {
|
func (a *XMLParser[T]) String() string {
|
||||||
|
a.RLock()
|
||||||
|
defer a.RUnlock()
|
||||||
var s string
|
var s string
|
||||||
for _, item := range a.Array {
|
for _, item := range a.array {
|
||||||
s += item.String()
|
s += item.String()
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
@@ -176,23 +177,41 @@ func (p *XMLParser[T]) Item(id string) *T {
|
|||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *XMLParser[T]) Find(fn func(*T) bool) []T {
|
func (p *XMLParser[T]) Filter(f func(T) bool) iter.Seq[T] {
|
||||||
|
return func(yield func(T) bool) {
|
||||||
p.mu.RLock()
|
p.mu.RLock()
|
||||||
defer p.mu.RUnlock()
|
defer p.mu.RUnlock()
|
||||||
var items []T
|
for _, v := range p.array {
|
||||||
for _, item := range p.Array {
|
if f(v) && !yield(v) {
|
||||||
if fn(&item) {
|
return
|
||||||
items = append(items, item)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return items
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// INFO: These are only reading locks.
|
func (p *XMLParser[T]) Iterate() iter.Seq[T] {
|
||||||
func (p *XMLParser[T]) Lock() {
|
return func(yield func(T) bool) {
|
||||||
|
p.mu.RLock()
|
||||||
|
defer p.mu.RUnlock()
|
||||||
|
for _, v := range p.array {
|
||||||
|
if !yield(v) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *XMLParser[T]) Count() int {
|
||||||
|
p.RLock()
|
||||||
|
defer p.RUnlock()
|
||||||
|
return len(p.array)
|
||||||
|
}
|
||||||
|
|
||||||
|
// INFO: These are reading locks.
|
||||||
|
func (p *XMLParser[T]) RLock() {
|
||||||
p.mu.RLock()
|
p.mu.RLock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *XMLParser[T]) Unlock() {
|
func (p *XMLParser[T]) RUnlock() {
|
||||||
p.mu.RUnlock()
|
p.mu.RUnlock()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ type Letter struct {
|
|||||||
Pages []Page `xml:"page"`
|
Pages []Page `xml:"page"`
|
||||||
Hands []RefElement `xml:"hand"`
|
Hands []RefElement `xml:"hand"`
|
||||||
Content string `xml:",innerxml"`
|
Content string `xml:",innerxml"`
|
||||||
|
Chardata string `xml:",chardata"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l Letter) Keys() []any {
|
func (l Letter) Keys() []any {
|
||||||
|
|||||||
@@ -37,27 +37,37 @@ func (l *Library) String() string {
|
|||||||
sb := strings.Builder{}
|
sb := strings.Builder{}
|
||||||
|
|
||||||
sb.WriteString("Persons: ")
|
sb.WriteString("Persons: ")
|
||||||
sb.WriteString(strconv.Itoa(len(l.Persons.Array)))
|
sb.WriteString(strconv.Itoa(l.Persons.Count()))
|
||||||
sb.WriteString("\n")
|
sb.WriteString("\n")
|
||||||
|
|
||||||
sb.WriteString("Places: ")
|
sb.WriteString("Places: ")
|
||||||
sb.WriteString(strconv.Itoa(len(l.Places.Array)))
|
sb.WriteString(strconv.Itoa(l.Places.Count()))
|
||||||
sb.WriteString("\n")
|
sb.WriteString("\n")
|
||||||
|
|
||||||
sb.WriteString("AppDefs: ")
|
sb.WriteString("AppDefs: ")
|
||||||
sb.WriteString(strconv.Itoa(len(l.AppDefs.Array)))
|
sb.WriteString(strconv.Itoa(l.AppDefs.Count()))
|
||||||
sb.WriteString("\n")
|
sb.WriteString("\n")
|
||||||
|
|
||||||
sb.WriteString("Letters: ")
|
sb.WriteString("Letters: ")
|
||||||
sb.WriteString(strconv.Itoa(len(l.Letters.Array)))
|
sb.WriteString(strconv.Itoa(l.Letters.Count()))
|
||||||
|
filter := func(item Letter) bool {
|
||||||
|
return len(item.Hands) > 0
|
||||||
|
}
|
||||||
|
hands := 0
|
||||||
|
for l := range l.Letters.Filter(filter) {
|
||||||
|
hands += 1
|
||||||
|
sb.WriteString("\n")
|
||||||
|
sb.WriteString(strconv.Itoa(l.Letter) + ": ")
|
||||||
|
sb.WriteString(strconv.Itoa(len(l.Hands)) + " Hände, No " + strconv.Itoa(hands))
|
||||||
|
}
|
||||||
sb.WriteString("\n")
|
sb.WriteString("\n")
|
||||||
|
|
||||||
sb.WriteString("Traditions: ")
|
sb.WriteString("Traditions: ")
|
||||||
sb.WriteString(strconv.Itoa(len(l.Traditions.Array)))
|
sb.WriteString(strconv.Itoa(l.Traditions.Count()))
|
||||||
sb.WriteString("\n")
|
sb.WriteString("\n")
|
||||||
|
|
||||||
sb.WriteString("Metas: ")
|
sb.WriteString("Metas: ")
|
||||||
sb.WriteString(strconv.Itoa(len(l.Metas.Array)))
|
sb.WriteString(strconv.Itoa(l.Metas.Count()))
|
||||||
sb.WriteString("\n")
|
sb.WriteString("\n")
|
||||||
|
|
||||||
return sb.String()
|
return sb.String()
|
||||||
|
|||||||
Reference in New Issue
Block a user