Commit b3163ad6 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent be0fed1e
......@@ -882,13 +882,13 @@ retry:
// XXX -> parallel
// XXX locking
for file := range toinvalidate {
size, treePath, err := file.zfile.Size(ctx)
size, sizePath, err := file.zfile.Size(ctx)
if err != nil {
panic(err) // XXX
}
file.size = size
bfdir.δFtail.Track(file, treePath)
bfdir.δFtail.Track(file, -1, sizePath, nil)
file.rev = zhead.At()
}
......@@ -1173,16 +1173,18 @@ func (f *BigFile) updateWatchers(ctx context.Context, blk int64, treepath []btre
return
}
// update δbtree index
// update δFtail index
bfdir := f.head.bfdir
bfdir.δFmu.Lock() // XXX locking correct?
bfdir.δFtail.Track(f, treepath) // XXX pass in zblk.oid / zblk.rev here?
bfdir.δFmu.Lock() // XXX locking correct? XXX -> better push down?
bfdir.δFtail.Track(f, blk, treepath, zblk) // XXX pass in zblk.rev here?
bfdir.δFmu.Unlock()
/* XXX kill
// associate zblk with file, if data was not hole
if zblk != nil {
zblk.bindFile(f, blk)
}
*/
// makes sure that file[blk] on clients side stays as of @w.at state.
......@@ -1743,7 +1745,7 @@ func (head *Head) bigopen(ctx context.Context, oid zodb.Oid) (_ *BigFile, err er
rev := zfile.PSerial()
zfile.PDeactivate()
size, treePath, err := zfile.Size(ctx)
size, sizePath, err := zfile.Size(ctx)
if err != nil {
return nil, err
}
......@@ -1764,7 +1766,7 @@ func (head *Head) bigopen(ctx context.Context, oid zodb.Oid) (_ *BigFile, err er
// only head/ needs δFtail & f.δtail.
if head.rev == 0 {
head.bfdir.δFmu.Lock() // XXX locking ok?
head.bfdir.δFtail.Track(f, treePath)
head.bfdir.δFtail.Track(f, -1, sizePath, nil)
head.bfdir.δFmu.Unlock()
f.δtail = NewΔTailI64(zconn.At())
......
......@@ -67,6 +67,10 @@ type zBlk interface {
// returns data and revision of ZBlk.
loadBlkData(ctx context.Context) (data []byte, rev zodb.Tid, _ error)
// inΔFtail returns pointer to struct zblkInΔFtail embedded into this ZBlk.
inΔFtail() *zblkInΔFtail
/*
// bindFile associates ZBlk as being used by file to store block #blk.
//
// A ZBlk may be bound to several blocks inside one file, and to
......@@ -90,11 +94,13 @@ type zBlk interface {
//
// blkBoundTo must not be called simultaneously wrt bindFile.
blkBoundTo() map[*BigFile]SetI64
*/
}
var _ zBlk = (*ZBlk0)(nil)
var _ zBlk = (*ZBlk1)(nil)
/*
// ---- zBlkBase ----
// zBlkBase provides common functionality to implement ZBlk* -> zfile, #blk binding.
......@@ -103,7 +109,7 @@ var _ zBlk = (*ZBlk1)(nil)
// persistent state.
type zBlkBase struct {
bindMu sync.Mutex // used only for binding to support multiple loaders
infile map[*BigFile]SetI64 // {} zfile -> set(#blk)
infile map[*BigFile]SetI64 // {} file -> set(#blk)
}
// bindFile implements zBlk.
......@@ -126,12 +132,13 @@ func (zb *zBlkBase) bindFile(file *BigFile, blk int64) {
func (zb *zBlkBase) blkBoundTo() map[*BigFile]SetI64 {
return zb.infile
}
*/
// ---- ZBlk0 ----
// ZBlk0 mimics ZBlk0 from python.
type ZBlk0 struct {
zBlkBase
zblkInΔFtail
zodb.Persistent
// XXX py source uses bytes(buf) but on python2 it still results in str
......@@ -204,7 +211,7 @@ func (zd *zDataState) PySetState(pystate interface{}) error {
// ZBlk1 mimics ZBlk1 from python.
type ZBlk1 struct {
zBlkBase
zblkInΔFtail
zodb.Persistent
chunktab *btree.IOBTree // {} offset -> ZData(chunk)
......@@ -501,7 +508,7 @@ func (bf *ZBigFile) LoadBlk(ctx context.Context, blk int64) (_ []byte, treePath
// Size returns whole file size.
//
// it also returns BTree path scaned to obtain size.
// it also returns BTree path scaned to obtain the size.
func (bf *ZBigFile) Size(ctx context.Context) (_ int64, treePath []btree.LONode, err error) {
defer xerr.Contextf(&err, "bigfile %s: size", bf.POid())
......
......@@ -22,6 +22,7 @@ package main
import (
"context"
"runtime"
"sync"
"lab.nexedi.com/kirr/neo/go/zodb"
"lab.nexedi.com/kirr/neo/go/zodb/btree"
......@@ -79,6 +80,20 @@ type Δfile struct {
Change SetI64 // changed blocks
}
// zblkInΔFtail is ΔFtail knowledge embedded into ZBlk*.
//
// The data stored by zBlkBase is transient - it is _not_ included into
// persistent state.
type zblkInΔFtail struct {
mu sync.Mutex // used only for binding to support multiple loaders
// with which files/blocks this ZBlk is associated.
infile map[*BigFile]SetI64 // {} file -> set(#blk)
}
func (z *zblkInΔFtail) inΔFtail() *zblkInΔFtail { return z }
// NewΔFtail creates new ΔFtail object.
//
// Initial tracked set is empty.
......@@ -95,12 +110,17 @@ func (δFtail *ΔFtail) Head() zodb.Tid { return δFtail.δBtail.Head() }
func (δFtail *ΔFtail) Tail() zodb.Tid { return δFtail.δBtail.Tail() }
// Track adds tree path to tracked set and associates path root with file.
// Track associates file[blk] with tree path and zblk object there.
//
// zblk can be nil, which represents a hole.
// XXX blk=-1 is used for tracking after Size (no zblk is accessed at all).
//
// XXX Track adds tree path to tracked set and associates path root with file.
//
// XXX text
//
// A root can be associated with several files (each provided on different Track call).
func (δFtail *ΔFtail) Track(file *BigFile, path []btree.LONode) {
func (δFtail *ΔFtail) Track(file *BigFile, blk int64, path []btree.LONode, zblk zBlk) {
δFtail.δBtail.Track(path)
root := path[0].(*btree.LOBTree)
files, ok := δFtail.fileIdx[root]
......@@ -110,6 +130,22 @@ func (δFtail *ΔFtail) Track(file *BigFile, path []btree.LONode) {
}
files.Add(file)
// associate zblk with file, if it was not hole
if zblk != nil {
z := zblk.inΔFtail()
z.mu.Lock()
blocks, ok := z.infile[file]
if !ok {
blocks = make(SetI64, 1)
if z.infile == nil {
z.infile = make(map[*BigFile]SetI64)
}
z.infile[file] = blocks
}
blocks.Add(blk)
z.mu.Unlock()
}
// XXX mark something dirty so that LastBlkRev and Slice* know what to rebuild?
// XXX debug
......@@ -167,21 +203,18 @@ func (δFtail *ΔFtail) Update(δZ *zodb.EventCommit) ΔF {
continue // object not related to any bigfile
case zBlk: // ZBlk*
// blkBoundTo locking: no other bindFile are running,
// since we write-locked head.zconnMu and bindFile is
// run when loading objects - thus when head.zconnMu is
// read-locked. XXX comment -> proper place?
//
// bfdir locking: similarly not needed, since we are
// exclusively holding head lock.
for file, objBlk := range obj.blkBoundTo() {
// z.infile locking: since we write-locked head.zconnMu
// - no other fuse reads are running, and thus no one
// is mutating z.infile. XXX recheck
z := obj.inΔFtail()
for file, blocks := range z.infile {
δfile, ok := δF.Change[file]
if !ok {
δfile = make(SetI64)
δF.Change[file] = δfile
}
δfile.Update(objBlk)
δfile.Update(blocks)
}
case *ZBigFile:
......
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