Commit 5909d6a4 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 0d62b05e
// Code generated by gen-rangemap _RangedMap_RebuildJob _RebuildJob; DO NOT EDIT. // Code generated by gen-rangemap _RangedMap_RebuildJob *_RebuildJob; DO NOT EDIT.
// Copyright (C) 2021 Nexedi SA and Contributors. // Copyright (C) 2021 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com> // Kirill Smelkov <kirr@nexedi.com>
...@@ -33,7 +33,7 @@ import ( ...@@ -33,7 +33,7 @@ import (
const trace_RangedMap_RebuildJob = false const trace_RangedMap_RebuildJob = false
const debug_RangedMap_RebuildJob = false const debug_RangedMap_RebuildJob = false
// _RangedMap_RebuildJob is Key->_RebuildJob map with adjacent keys mapped to the same value coalesced into Ranges. // _RangedMap_RebuildJob is Key->*_RebuildJob map with adjacent keys mapped to the same value coalesced into Ranges.
// //
// Zero value represents empty map. // Zero value represents empty map.
type _RangedMap_RebuildJob struct { type _RangedMap_RebuildJob struct {
...@@ -45,19 +45,19 @@ type _RangedMap_RebuildJob struct { ...@@ -45,19 +45,19 @@ type _RangedMap_RebuildJob struct {
// _RangedMap_RebuildJobEntry represents one entry in _RangedMap_RebuildJob. // _RangedMap_RebuildJobEntry represents one entry in _RangedMap_RebuildJob.
type _RangedMap_RebuildJobEntry struct { type _RangedMap_RebuildJobEntry struct {
Value _RebuildJob Value *_RebuildJob
blib.KeyRange blib.KeyRange
} }
// Get returns value associated with key k. // Get returns value associated with key k.
func (M *_RangedMap_RebuildJob) Get(k Key) _RebuildJob { func (M *_RangedMap_RebuildJob) Get(k Key) *_RebuildJob {
v, _ := M.Get_(k) v, _ := M.Get_(k)
return v return v
} }
// Set changes M to map key k to value v. // Set changes M to map key k to value v.
func (M *_RangedMap_RebuildJob) Set(k Key, v _RebuildJob) { func (M *_RangedMap_RebuildJob) Set(k Key, v *_RebuildJob) {
M.SetRange(blib.KeyRange{Lo: k, Hi_: k}, v) M.SetRange(blib.KeyRange{Lo: k, Hi_: k}, v)
} }
...@@ -75,7 +75,7 @@ func (M *_RangedMap_RebuildJob) Has(k Key) bool { ...@@ -75,7 +75,7 @@ func (M *_RangedMap_RebuildJob) Has(k Key) bool {
// Get_ is comma-ok version of Get. // Get_ is comma-ok version of Get.
func (M *_RangedMap_RebuildJob) Get_(k Key) (v _RebuildJob, ok bool) { func (M *_RangedMap_RebuildJob) Get_(k Key) (v *_RebuildJob, ok bool) {
if trace_RangedMap_RebuildJob { if trace_RangedMap_RebuildJob {
fmt.Printf("\n\nGet_:\n") fmt.Printf("\n\nGet_:\n")
fmt.Printf(" M: %s\n", M) fmt.Printf(" M: %s\n", M)
...@@ -108,7 +108,7 @@ func (M *_RangedMap_RebuildJob) Get_(k Key) (v _RebuildJob, ok bool) { ...@@ -108,7 +108,7 @@ func (M *_RangedMap_RebuildJob) Get_(k Key) (v _RebuildJob, ok bool) {
} }
// SetRange changes M to map key range r to value v. // SetRange changes M to map key range r to value v.
func (M *_RangedMap_RebuildJob) SetRange(r blib.KeyRange, v _RebuildJob) { func (M *_RangedMap_RebuildJob) SetRange(r blib.KeyRange, v *_RebuildJob) {
e := _RangedMap_RebuildJobEntry{v,r} e := _RangedMap_RebuildJobEntry{v,r}
if trace_RangedMap_RebuildJob { if trace_RangedMap_RebuildJob {
fmt.Printf("\n\nSetRange:\n") fmt.Printf("\n\nSetRange:\n")
...@@ -390,7 +390,7 @@ func (M *_RangedMap_RebuildJob) verify() { ...@@ -390,7 +390,7 @@ func (M *_RangedMap_RebuildJob) verify() {
}() }()
hi_Prev := KeyMin hi_Prev := KeyMin
var v_Prev _RebuildJob var v_Prev *_RebuildJob
for i, e := range M.entryv { for i, e := range M.entryv {
hiPrev := hi_Prev + 1 hiPrev := hi_Prev + 1
if i > 0 { if i > 0 {
......
...@@ -67,13 +67,19 @@ package xbtree ...@@ -67,13 +67,19 @@ package xbtree
// //
// XXX concurrency // XXX concurrency
// //
// trackSet, ktrackNew, krebuildJobs + explain rebuild algo (query lock, check ktrackNew, krebuildJob, go/merge/...)
//
// This locking organization allows non-overlapping queries/track-requests to
// run simultaneously. Without this property WCFS would not be able to serve
// several non-overlapping READ requests to one file in parallel.
// //
// -------- // --------
// //
// (*) implemented in treediff.go // (*) implemented in treediff.go
// (+) full database scan // (+) full database scan
//go:generate ./blib/gen-rangemap _RangedMap_RebuildJob _RebuildJob zrangemap_rebuildjob.go ////go:generate ./blib/gen-rangemap _RangedMap_Path []zodbOid zrangemap_path.go
//go:generate ./blib/gen-rangemap _RangedMap_RebuildJob *_RebuildJob zrangemap_rebuildjob.go
import ( import (
"context" "context"
...@@ -89,6 +95,7 @@ import ( ...@@ -89,6 +95,7 @@ import (
"lab.nexedi.com/nexedi/wendelin.core/wcfs/internal/xtail" "lab.nexedi.com/nexedi/wendelin.core/wcfs/internal/xtail"
) )
//type zodbOid = zodb.Oid XXX kill probably
const traceΔBtail = false const traceΔBtail = false
const debugΔBtail = false const debugΔBtail = false
...@@ -141,11 +148,11 @@ type ΔBtail struct { ...@@ -141,11 +148,11 @@ type ΔBtail struct {
// set of tracked nodes as of @head state. // set of tracked nodes as of @head state.
// For this set all vδT are fully computed. // For this set all vδT are fully computed.
// The set of nodes that were requested to be tracked, but were not yet // The set of keys(nodes) that were requested to be tracked, but were
// taken into account, is kept in _ΔTtail.trackNew & co. // not yet taken into account, is kept in _ΔTtail.ktrackNew & co.
trackSet blib.PPTreeSubSet trackSet blib.PPTreeSubSet
// set of trees for which _ΔTtail.trackNew is non-empty // set of trees for which _ΔTtail.ktrackNew is non-empty
trackNewRoots setOid trackNewRoots setOid
// handle to make connections to access database. // handle to make connections to access database.
...@@ -159,13 +166,18 @@ type ΔBtail struct { ...@@ -159,13 +166,18 @@ type ΔBtail struct {
type _ΔTtail struct { type _ΔTtail struct {
vδT []ΔTree // changes to tree keys; rev↑. covers keys ∈ tracked subset vδT []ΔTree // changes to tree keys; rev↑. covers keys ∈ tracked subset
// set of nodes that were requested to be tracked in this tree, but for // // set of keys(nodes) that were requested to be tracked in this tree,
// which vδT was not yet rebuilt // // but for which vδT rebuild was not yet started
// ktrackNew _RangedMap_Path // {} keycov -> path
// set of keys that were requested to be tracked in this tree,
// but for which vδT rebuild was not yet started
ktrackNew blib.RangedKeySet // {keycov}
// set of nodes corresponding to ktrackNew
trackNew blib.PPTreeSubSet trackNew blib.PPTreeSubSet
// XXX + trackNewKeys RangedKeySet (concurrency) // set of keys(nodes) for which rebuild is in progress
// XXX + trackSetKeys RangedKeySet krebuildJobs _RangedMap_RebuildJob // {} keycov -> job
rebuildNew _RangedMap_RebuildJob // keycov -> _RebuildJob
} }
// _ΔBroots represents roots-only part of ΔB. // _ΔBroots represents roots-only part of ΔB.
...@@ -189,9 +201,11 @@ type ΔTree struct { ...@@ -189,9 +201,11 @@ type ΔTree struct {
} }
// _RebuildJob represents currently in-progress rebuilding job. XXX
// XXX place // XXX place
type _RebuildJob struct { type _RebuildJob struct {
// XXX ready chan struct{} // closed when job completes
err error
} }
...@@ -407,6 +421,87 @@ func (δBtail *ΔBtail) rebuild1IfNeeded(root zodb.Oid) error { ...@@ -407,6 +421,87 @@ func (δBtail *ΔBtail) rebuild1IfNeeded(root zodb.Oid) error {
return δBtail.rebuild1(root) return δBtail.rebuild1(root)
} }
// rebuild1KeyIfNeeded rebuilds ΔBtail for single root if that root[key] needs rebuilding.
func (δBtail *ΔBtail) rebuild1KeyIfNeeded(root zodb.Oid, key Key) error {
// XXX δBtail.lock
_, ok := δBtail.trackNewRoots[root]
if !ok {
// XXX δBtail.unlock
return nil
}
// XXX move -> ΔTtail.rebuild1KeyIfNeeded?
δTtail := δBtail.byRoot[root] // must be there
// XXX δTtail.lock
// _, inNew := δTtail.ktrackNew.Get_(key)
inNew := δTtail.ktrackNew.Has(key)
if !inNew {
// key ∉ ktrackNew
job, inJobs := δTtail.krebuildJobs.Get_(key)
if !inJobs {
// key ∉ krebuildJobs -> it should be already in trackSet
// XXX δTtail.unlock
// XXX δBtail.unlock
return nil
}
// rebuild for root[key] is in progress -> wait for corresponding job to complete
// XXX δTtail.unlock
// XXX δBtail.unlock
<-job.ready
return job.err
}
// key ∈ ktrackNew -> this goroutine becomes responsible to start rebuilding vδT for it
// lauch rebuild job for all keys queued in ktrackNew so far
job := &_RebuildJob{ready: make(chan struct{})}
/*
trackNewSet := blib.PPTreeSubSet{} // trackNew corresponding to ktrackNew
rebuildKeys := blib.RangedKeySet{} // keys(ktrackNew)
for _, e := range δTtail.ktrackNew.AllRanges() {
trackNewSet.AddPath(e.Value)
rebuildKeys.AddRange(e.KeyRange)
}
*/
trackNew := δTtail.trackNew
rebuildKeys := δTtail.ktrackNew
δTtail.trackNew = blib.PPTreeSubSet{}
δTtail.ktrackNew = blib.RangedKeySet{}
// krebuildJobs += rebuildKeys
for _, r := range rebuildKeys.AllRanges() {
// XXX assert !krebuildJobs.IntersectsRange(e.KeyRange)
δTtail.krebuildJobs.SetRange(r, job)
}
delete(δBtail.trackNewRoots, root)
// XXX δTtail.unlock
// XXX δBtail.unlock
// XXX δTtail.rebuild(for trackNew) -> err
_ = trackNew
// XXX δBtail.lock ? (to update vδBroots)
// XXX δTtail.lock
// XXX merge rebuild result
// krebuildJobs -= rebuildKeys
for _, r := range rebuildKeys.AllRanges() {
// XXX assert krebuildJobs[r] == job
δTtail.krebuildJobs.DelRange(r)
}
// we are done
job.err = nil // XXX stub
close(job.ready)
// XXX unlock
return job.err
}
// rebuild1 rebuilds ΔBtail for single root. // rebuild1 rebuilds ΔBtail for single root.
func (δBtail *ΔBtail) rebuild1(root zodb.Oid) error { func (δBtail *ΔBtail) rebuild1(root zodb.Oid) error {
// XXX locking // XXX locking
...@@ -895,6 +990,7 @@ func (δBtail *ΔBtail) GetAt(root zodb.Oid, key Key, at zodb.Tid) (value Value, ...@@ -895,6 +990,7 @@ func (δBtail *ΔBtail) GetAt(root zodb.Oid, key Key, at zodb.Tid) (value Value,
// XXX need to rebuild only if key was not rebuilt yet // XXX need to rebuild only if key was not rebuilt yet
// XXX need to rebuild only for key, not for whole trackNew // XXX need to rebuild only for key, not for whole trackNew
// err = δBtail.rebuild1KeyIfNeeded(root, key) XXX reenable
err = δBtail.rebuild1IfNeeded(root) err = δBtail.rebuild1IfNeeded(root)
if err != nil { if err != nil {
return value, rev, valueExact, revExact, err return value, rev, valueExact, revExact, err
...@@ -904,11 +1000,12 @@ func (δBtail *ΔBtail) GetAt(root zodb.Oid, key Key, at zodb.Tid) (value Value, ...@@ -904,11 +1000,12 @@ func (δBtail *ΔBtail) GetAt(root zodb.Oid, key Key, at zodb.Tid) (value Value,
if δTtail == nil { if δTtail == nil {
panicf("δBtail: root<%s> not tracked", root) panicf("δBtail: root<%s> not tracked", root)
} }
vδT := δTtail.vδT
// TODO key not tracked -> panic (check key ∈ lastRevOf -- see vvv) // TODO key not tracked -> panic (check key ∈ lastRevOf -- see vvv)
// TODO -> index lastRevOf(key) | linear scan ↓ looking for change ≤ at // TODO -> index lastRevOf(key) | linear scan ↓ looking for change ≤ at
for i := len(δTtail.vδT)-1; i >= 0; i-- { for i := len(vδT)-1; i >= 0; i-- {
δT := δTtail.vδT[i] δT := vδT[i]
δvalue, ok_ := δT.KV[key] δvalue, ok_ := δT.KV[key]
if ok_ { if ok_ {
valueExact = true valueExact = true
...@@ -951,7 +1048,7 @@ func (δBtail *ΔBtail) SliceByRootRev(root zodb.Oid, lo, hi zodb.Tid) /*readonl ...@@ -951,7 +1048,7 @@ func (δBtail *ΔBtail) SliceByRootRev(root zodb.Oid, lo, hi zodb.Tid) /*readonl
δTtail, ok := δBtail.byRoot[root] δTtail, ok := δBtail.byRoot[root]
if !ok { if !ok {
return []ΔTree{} return []ΔTree{} // XXX -> panic (root must be tracked)
} }
vδT := δTtail.vδT vδT := δTtail.vδT
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment