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

.

parent 7547a4d2
...@@ -221,6 +221,12 @@ def TreesSrv(zstor, r): ...@@ -221,6 +221,12 @@ def TreesSrv(zstor, r):
xprint("%s" % ashex(head)) xprint("%s" % ashex(head))
continue 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 # t... D... commands to natively commit updates to tree and values
if treetxt.startswith('t'): if treetxt.startswith('t'):
t, D = treetxt.split() t, D = treetxt.split()
......
...@@ -46,12 +46,14 @@ type setOid = set.Oid ...@@ -46,12 +46,14 @@ type setOid = set.Oid
// //
// δF: // δF:
// .rev↑ // .rev↑
// {} file -> {}blk // {} file -> {}blk | EPOCH
// //
// Only files and blocks explicitly requested to be tracked are guaranteed to // 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 // 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. // 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: // ΔFtail provides the following operations:
// //
// .Track(file, blk, path, zblk) - add file and block reached via BTree path to tracked set. // .Track(file, blk, path, zblk) - add file and block reached via BTree path to tracked set.
...@@ -96,6 +98,7 @@ type ΔF struct { ...@@ -96,6 +98,7 @@ type ΔF struct {
// ΔFile represents a change to one file. // ΔFile represents a change to one file.
type ΔFile struct { type ΔFile struct {
Rev zodb.Tid Rev zodb.Tid
Epoch bool // whether file changed completely
Blocks setI64 // changed blocks XXX -> ΔBlocks ? Blocks setI64 // changed blocks XXX -> ΔBlocks ?
Size bool // whether file size changed XXX -> ΔSize? Size bool // whether file size changed XXX -> ΔSize?
} }
...@@ -278,7 +281,7 @@ func (δFtail *ΔFtail) Update(δZ *zodb.EventCommit) (_ ΔF, err error) { ...@@ -278,7 +281,7 @@ func (δFtail *ΔFtail) Update(δZ *zodb.EventCommit) (_ ΔF, err error) {
for _, oid := range δZ.Changev { for _, oid := range δZ.Changev {
if δFtail.trackSetZFile.Has(oid) { if δFtail.trackSetZFile.Has(oid) {
// TODO check that .blksize and .blktab (it is only // 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) return ΔF{}, fmt.Errorf("ZBigFile<%s> changed @%s", oid, δZ.Tid)
} }
......
...@@ -97,6 +97,9 @@ func TestΔFtail(t *testing.T) { ...@@ -97,6 +97,9 @@ func TestΔFtail(t *testing.T) {
{δT{5:e}, δD()}, {δT{5:e}, δD()},
{δT{}, δD(i)}, {δT{}, δD(i)},
// XXX text
{nil, nil},
// XXX more // XXX more
// ---- found by TestΔFtailRandom ---- // ---- found by TestΔFtailRandom ----
...@@ -234,11 +237,28 @@ func testΔFtail(t_ *testing.T, testq chan ΔFTestEntry) { ...@@ -234,11 +237,28 @@ func testΔFtail(t_ *testing.T, testq chan ΔFTestEntry) {
i := 0 i := 0
delfilePrev := false
for test := range testq { for test := range testq {
i++ i++
δblk := setI64{} δblk := setI64{}
δtree := false δ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 // rebuild blkTab/Zinblk
for blk, zblk := range test.δblkTab { for blk, zblk := range test.δblkTab {
zprev, ok := blkTab[blk] zprev, ok := blkTab[blk]
...@@ -282,10 +302,16 @@ func testΔFtail(t_ *testing.T, testq chan ΔFTestEntry) { ...@@ -282,10 +302,16 @@ func testΔFtail(t_ *testing.T, testq chan ΔFTestEntry) {
} }
} }
// commit updated blkTab + dataTab // commit updated zfile / blkTab + dataTab
tTxt := "t" + xbtreetest.KVTxt(blkTab) var req string
dTxt := "D" + dataTabTxt(dataTab) if delfile {
commit := t.CommitTree(tTxt + " " + dTxt) req = "øf"
} else {
tTxt := "t" + xbtreetest.KVTxt(blkTab)
dTxt := "D" + dataTabTxt(dataTab)
req = tTxt + " " + dTxt
}
commit := t.CommitTree(req)
// update blkRevAt // update blkRevAt
var blkRevPrev map[int64]zodb.Tid var blkRevPrev map[int64]zodb.Tid
...@@ -294,7 +320,11 @@ func testΔFtail(t_ *testing.T, testq chan ΔFTestEntry) { ...@@ -294,7 +320,11 @@ func testΔFtail(t_ *testing.T, testq chan ΔFTestEntry) {
} }
blkRev := map[int64]zodb.Tid{} blkRev := map[int64]zodb.Tid{}
for blk, rev := range blkRevPrev { for blk, rev := range blkRevPrev {
blkRev[blk] = rev if epoch {
blkRev[blk] = commit.At
} else {
blkRev[blk] = rev
}
} }
for blk := range δblk { for blk := range δblk {
blkRev[blk] = commit.At blkRev[blk] = commit.At
...@@ -310,6 +340,7 @@ func testΔFtail(t_ *testing.T, testq chan ΔFTestEntry) { ...@@ -310,6 +340,7 @@ func testΔFtail(t_ *testing.T, testq chan ΔFTestEntry) {
if len(δblk) != 0 { if len(δblk) != 0 {
δfok = &ΔFile{ δfok = &ΔFile{
Rev: commit.At, Rev: commit.At,
Epoch: epoch, // XXX epoch -> blocks/size = nil ?
Blocks: δblk, Blocks: δblk,
Size: δtree, // not strictly ok, but matches current ΔFtail code Size: δtree, // not strictly ok, but matches current ΔFtail code
} }
...@@ -317,7 +348,8 @@ func testΔFtail(t_ *testing.T, testq chan ΔFTestEntry) { ...@@ -317,7 +348,8 @@ func testΔFtail(t_ *testing.T, testq chan ΔFTestEntry) {
} }
xat[commit.At] = fmt.Sprintf("at%d", i) 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)) //t.Logf("# vδf: %s", vδfstr(vδf))
//fmt.Printf("Zinblk: %v\n", Zinblk) //fmt.Printf("Zinblk: %v\n", Zinblk)
......
...@@ -882,28 +882,35 @@ retry: ...@@ -882,28 +882,35 @@ retry:
sort.Slice(blkv, func(i, j int) bool { sort.Slice(blkv, func(i, j int) bool {
return blkv[i] < blkv[j] return blkv[i] < blkv[j]
}) })
size := " " flags := ""
if δfile.Size { 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") log.Infof("\n\n")
} }
// invalidate kernel cache for file data
wg := xsync.NewWorkGroup(ctx) wg := xsync.NewWorkGroup(ctx)
for foid, δfile := range δF.ByFile { 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 was requested to be tracked -> it must be present in fileTab
file := bfdir.fileTab[foid] file := bfdir.fileTab[foid]
for blk := range δfile.Blocks {
blk := blk if δfile.Epoch {
wg.Go(func(ctx context.Context) error { 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() err = wg.Wait()
...@@ -1112,6 +1119,21 @@ func (f *BigFile) invalidateAttr() (err error) { ...@@ -1112,6 +1119,21 @@ func (f *BigFile) invalidateAttr() (err error) {
return nil 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 // lockRevFile makes sure inode ID of /@<rev>/bigfile/<fid> is known to kernel
// and won't change until unlock. // and won't change until unlock.
......
...@@ -1132,7 +1132,8 @@ def _expectPin(twlink, ctx, zf, expect): # -> []SrvReq ...@@ -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. # _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? # 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) @func(tDB)
def _blkDataAt(t, zf, blk, at): # -> (data, rev) def _blkDataAt(t, zf, blk, at): # -> (data, rev)
if at is None: if at is None:
...@@ -1417,7 +1418,7 @@ def test_wcfs_watch_robust(): ...@@ -1417,7 +1418,7 @@ def test_wcfs_watch_robust():
wl.close() wl.close()
# verify that `watch file @at` -> error, for @at when file did not existed. # 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 @func
def test_wcfs_watch_before_create(): def test_wcfs_watch_before_create():
t = tDB(); zf = t.zfile 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