Commit 71c8613d authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 7547a4d2
......@@ -221,6 +221,12 @@ def TreesSrv(zstor, r):
xprint("%s" % ashex(head))
continue
# øf command to delete the file
if treetxt == "øf":
head = commitDelete(zfile, subj)
xprint("%s" % ashex(head))
continue
# t... D... commands to natively commit updates to tree and values
if treetxt.startswith('t'):
t, D = treetxt.split()
......
......@@ -46,12 +46,14 @@ type setOid = set.Oid
//
// δF:
// .rev↑
// {} file -> {}blk
// {} file -> {}blk | EPOCH
//
// Only files and blocks explicitly requested to be tracked are guaranteed to
// be present. In particular a block that was not explicitly requested to be
// tracked, even if it was changed in δZ, is not guaranteed to be present in δF.
//
// XXX after epoch previous track requests has no effects
//
// ΔFtail provides the following operations:
//
// .Track(file, blk, path, zblk) - add file and block reached via BTree path to tracked set.
......@@ -96,6 +98,7 @@ type ΔF struct {
// ΔFile represents a change to one file.
type ΔFile struct {
Rev zodb.Tid
Epoch bool // whether file changed completely
Blocks setI64 // changed blocks XXX -> ΔBlocks ?
Size bool // whether file size changed XXX -> ΔSize?
}
......@@ -278,7 +281,7 @@ func (δFtail *ΔFtail) Update(δZ *zodb.EventCommit) (_ ΔF, err error) {
for _, oid := range δZ.Changev {
if δFtail.trackSetZFile.Has(oid) {
// TODO check that .blksize and .blktab (it is only
// persistent reference) do not change.
// persistent reference) do not change. XXX -> EPOCH
return ΔF{}, fmt.Errorf("ZBigFile<%s> changed @%s", oid, δZ.Tid)
}
......
......@@ -97,6 +97,9 @@ func TestΔFtail(t *testing.T) {
{δT{5:e}, δD()},
{δT{}, δD(i)},
// XXX text
{nil, nil},
// XXX more
// ---- found by TestΔFtailRandom ----
......@@ -234,11 +237,28 @@ func testΔFtail(t_ *testing.T, testq chan ΔFTestEntry) {
i := 0
delfilePrev := false
for test := range testq {
i++
δblk := setI64{}
δtree := false
delfile := false
// command to delete zfile
if test.δblkTab == nil && test.δdataTab == nil {
delfile = true
}
epoch := delfile || (!delfile && delfilePrev && !delfilePrev)
delfilePrev = delfile
// epoch -> reset
if epoch {
blkTab = map[int64]string{}
Zinblk = map[string]setI64{}
}
// XXX else?
// rebuild blkTab/Zinblk
for blk, zblk := range test.δblkTab {
zprev, ok := blkTab[blk]
......@@ -282,10 +302,16 @@ func testΔFtail(t_ *testing.T, testq chan ΔFTestEntry) {
}
}
// commit updated blkTab + dataTab
tTxt := "t" + xbtreetest.KVTxt(blkTab)
dTxt := "D" + dataTabTxt(dataTab)
commit := t.CommitTree(tTxt + " " + dTxt)
// commit updated zfile / blkTab + dataTab
var req string
if delfile {
req = "øf"
} else {
tTxt := "t" + xbtreetest.KVTxt(blkTab)
dTxt := "D" + dataTabTxt(dataTab)
req = tTxt + " " + dTxt
}
commit := t.CommitTree(req)
// update blkRevAt
var blkRevPrev map[int64]zodb.Tid
......@@ -294,7 +320,11 @@ func testΔFtail(t_ *testing.T, testq chan ΔFTestEntry) {
}
blkRev := map[int64]zodb.Tid{}
for blk, rev := range blkRevPrev {
blkRev[blk] = rev
if epoch {
blkRev[blk] = commit.At
} else {
blkRev[blk] = rev
}
}
for blk := range δblk {
blkRev[blk] = commit.At
......@@ -310,6 +340,7 @@ func testΔFtail(t_ *testing.T, testq chan ΔFTestEntry) {
if len(δblk) != 0 {
δfok = &ΔFile{
Rev: commit.At,
Epoch: epoch, // XXX epoch -> blocks/size = nil ?
Blocks: δblk,
Size: δtree, // not strictly ok, but matches current ΔFtail code
}
......@@ -317,7 +348,8 @@ func testΔFtail(t_ *testing.T, testq chan ΔFTestEntry) {
}
xat[commit.At] = fmt.Sprintf("at%d", i)
t.Logf("# → @%s (%s) δT%s δD%s\t; %s\tδ%s", xat[commit.At], commit.At, xbtreetest.KVTxt(test.δblkTab), test.δdataTab, tTxt, δblk)
// t.Logf("# → @%s (%s) δT%s δD%s\t; %s\tδ%s", xat[commit.At], commit.At, xbtreetest.KVTxt(test.δblkTab), test.δdataTab, tTxt, δblk)
t.Logf("# → @%s (%s) δT%s δD%s\t; %s\tδ%s", xat[commit.At], commit.At, xbtreetest.KVTxt(test.δblkTab), test.δdataTab, commit.Tree, δblk)
//t.Logf("# vδf: %s", vδfstr(vδf))
//fmt.Printf("Zinblk: %v\n", Zinblk)
......
......@@ -882,28 +882,35 @@ retry:
sort.Slice(blkv, func(i, j int) bool {
return blkv[i] < blkv[j]
})
size := " "
flags := ""
if δfile.Size {
size = "S"
flags += "S"
}
log.Infof("S: \t- %s\t%s %v\n", foid, size, blkv)
if δfile.Epoch {
flags += "E"
}
log.Infof("S: \t- %s\t%s%2s %v\n", foid, flags, blkv)
}
log.Infof("\n\n")
}
// invalidate kernel cache for file data
wg := xsync.NewWorkGroup(ctx)
for foid, δfile := range δF.ByFile {
// // XXX needed?
// // XXX even though δBtail is complete, not all ZBlk are present here
// file.δtail.Append(δF.Rev, δfile.Blocks.Elements())
// file was requested to be tracked -> it must be present in fileTab
file := bfdir.fileTab[foid]
for blk := range δfile.Blocks {
blk := blk
if δfile.Epoch {
wg.Go(func(ctx context.Context) error {
return file.invalidateBlk(ctx, blk)
return file.invalidateAll() // NOTE does not accept ctx
})
} else {
for blk := range δfile.Blocks {
blk := blk
wg.Go(func(ctx context.Context) error {
return file.invalidateBlk(ctx, blk)
})
}
}
}
err = wg.Wait()
......@@ -1112,6 +1119,21 @@ func (f *BigFile) invalidateAttr() (err error) {
return nil
}
// invalidateAll invalidates file attributes and all file data in kernel cache.
//
// complements invalidateAttr and invalidateBlk and is used to completely reset
// kernel file cache on ΔFtail epoch.
// called with zheadMu wlocked.
func (f *BigFile) invalidateAll() (err err) {
defer xerr.Contextf(&err, "%s: invalidate all", f.path())
fsconn := gfsconn
st := fsconn.FileNotify(f.Inode(), 0, -1) // metadata + all data
if st != fuse.OK {
return syscall.Errno(st)
}
return nil
}
// lockRevFile makes sure inode ID of /@<rev>/bigfile/<fid> is known to kernel
// and won't change until unlock.
......
......@@ -1132,7 +1132,8 @@ def _expectPin(twlink, ctx, zf, expect): # -> []SrvReq
# _blkDataAt returns expected zf[blk] data and its revision as of @at database state.
#
# If the block is hole - (b'', at0) is returned. XXX -> @z64?
# XXX ret for when the file did not existed at all? blk was after file size?
# XXX ret for when the file did not existed at all?
# XXX ret ----//---- blk was after file size?
@func(tDB)
def _blkDataAt(t, zf, blk, at): # -> (data, rev)
if at is None:
......@@ -1417,7 +1418,7 @@ def test_wcfs_watch_robust():
wl.close()
# verify that `watch file @at` -> error, for @at when file did not existed.
@xfail # check that file exists @at
@xfail # check that file exists @at XXX
@func
def test_wcfs_watch_before_create():
t = tDB(); zf = t.zfile
......
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