1
// Copyright 2018 The CubeFS Authors.
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
7
// http://www.apache.org/licenses/LICENSE-2.0
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12
// implied. See the License for the specific language governing
13
// permissions and limitations under the License.
23
"github.com/cubefs/cubefs/proto"
24
"github.com/cubefs/cubefs/util/log"
27
// Dentry wraps necessary properties of the `dentry` information in file system.
28
// Marshal exporterKey:
29
// +-------+----------+------+
30
// | item | ParentId | Name |
31
// +-------+----------+------+
32
// | bytes | 8 | rest |
33
// +-------+----------+------+
35
// +-------+-------+------+
36
// | item | Inode | Type |
37
// +-------+-------+------+
39
// +-------+-------+------+
41
// +-------+-----------+--------------+-----------+--------------+
42
// | item | KeyLength | MarshaledKey | ValLength | MarshaledVal |
43
// +-------+-----------+--------------+-----------+--------------+
44
// | bytes | 4 | KeyLength | 4 | ValLength |
45
// +-------+-----------+--------------+-----------+--------------+
47
type DentryMultiSnap struct {
49
dentryList DentryBatch
53
ParentId uint64 // FileID value of the parent inode.
54
Name string // Name of the current dentry.
55
Inode uint64 // FileID value of the current inode.
58
multiSnap *DentryMultiSnap
61
func NewDentrySnap(seq uint64) *DentryMultiSnap {
62
return &DentryMultiSnap{
67
func (d *Dentry) getSnapListLen() int {
68
if d.multiSnap == nil {
71
return len(d.multiSnap.dentryList)
74
func (d *Dentry) addVersion(ver uint64) {
75
dn := d.CopyDirectly().(*Dentry)
76
dn.setVerSeq(d.getSeqFiled())
78
d.multiSnap.dentryList = append([]*Dentry{dn}, d.multiSnap.dentryList...)
81
func (d *Dentry) setVerSeq(verSeq uint64) {
85
if d.multiSnap == nil {
86
d.multiSnap = NewDentrySnap(verSeq)
88
d.multiSnap.VerSeq = verSeq
92
func (d *Dentry) getSeqFiled() (verSeq uint64) {
93
if d.multiSnap == nil {
96
return d.multiSnap.VerSeq
99
func isSeqEqual(ver_1 uint64, ver_2 uint64) bool {
100
if isInitSnapVer(ver_1) {
103
if isInitSnapVer(ver_2) {
106
return (ver_1 & math.MaxInt64) == (ver_2 & math.MaxInt64)
109
func (d *Dentry) getVerSeq() (verSeq uint64) {
110
if d.multiSnap == nil {
113
return d.multiSnap.VerSeq & math.MaxInt64
116
func (d *Dentry) isDeleted() bool {
117
if d.multiSnap == nil {
120
return (d.multiSnap.VerSeq >> 63) != 0
123
func (d *Dentry) setDeleted() {
124
if d.multiSnap == nil {
125
log.LogErrorf("action[setDeleted] d %v be set deleted not found multiSnap", d)
128
log.LogDebugf("action[setDeleted] d %v be set deleted", d)
129
d.multiSnap.VerSeq |= uint64(1) << 63
132
func (d *Dentry) minimizeSeq() (verSeq uint64) {
133
cnt := d.getSnapListLen()
137
return d.multiSnap.dentryList[cnt-1].getVerSeq()
140
func (d *Dentry) isEffective(verSeq uint64) bool {
144
if isInitSnapVer(verSeq) {
147
return verSeq >= d.minimizeSeq()
150
// isHit return the right version or else return the version can be seen
151
func (d *Dentry) getDentryFromVerList(verSeq uint64, isHit bool) (den *Dentry, idx int) {
152
if verSeq == 0 || (verSeq >= d.getVerSeq() && !isInitSnapVer(verSeq)) {
154
log.LogDebugf("action[getDentryFromVerList] tmp dentry %v, is deleted, seq [%v]", d, d.getVerSeq())
160
// read the oldest version snapshot,the oldest version is 0 should make a different with the lastest uncommit version read(with seq 0)
161
if isInitSnapVer(verSeq) {
162
if d.getVerSeq() == 0 {
165
denListLen := d.getSnapListLen()
169
den = d.multiSnap.dentryList[denListLen-1]
170
if d.multiSnap.dentryList[denListLen-1].getVerSeq() != 0 || d.multiSnap.dentryList[denListLen-1].isDeleted() {
173
return den, denListLen
175
if d.multiSnap == nil {
178
for id, lDen := range d.multiSnap.dentryList {
179
if verSeq < lDen.getVerSeq() {
180
log.LogDebugf("action[getDentryFromVerList] den in ver list %v, return nil, request seq [%v], history ver seq [%v]", lDen, verSeq, lDen.getVerSeq())
182
if lDen.isDeleted() {
183
log.LogDebugf("action[getDentryFromVerList] den in ver list %v, return nil due to latest is deleted", lDen)
186
if isHit && lDen.getVerSeq() != verSeq {
187
log.LogDebugf("action[getDentryFromVerList] den in ver list %v, return nil due to ver not equal %v vs %v", lDen, lDen.getVerSeq(), verSeq)
193
log.LogDebugf("action[getDentryFromVerList] den in ver list not found right dentry with seq [%v]", verSeq)
197
func (d *Dentry) getLastestVer(reqVerSeq uint64, commit bool, verlist []*proto.VolVersionInfo) (uint64, bool) {
198
if len(verlist) == 0 {
201
for id, info := range verlist {
202
if commit && id == len(verlist)-1 {
205
if info.Ver >= reqVerSeq { // include reqSeq itself
206
return info.Ver, true
210
log.LogDebugf("action[getLastestVer] inode[%v] reqVerseq [%v] not found, the largetst one %v",
211
d.Inode, reqVerSeq, verlist[len(verlist)-1].Ver)
215
func (d *Dentry) deleteTopLayer(mpVerSeq uint64) (rd *Dentry, dmore bool, clean bool) {
217
log.LogDebugf("action[deleteTopLayer.delSeq_0] do noting dentry %v seq 0 be deleted before", d)
218
return nil, false, false
221
// if there's no snapshot itself, nor have snapshot after dentry's ver then need unlink directly and make no snapshot
222
// just move to upper layer,the request snapshot be dropped
223
if d.getSnapListLen() == 0 {
224
if d.getVerSeq() == mpVerSeq {
225
// operate dentry directly
226
log.LogDebugf("action[deleteTopLayer.delSeq_0] no snapshot depend on this dentry,could drop seq 0 dentry %v", d)
231
if d.getVerSeq() < mpVerSeq {
232
dn := d.CopyDirectly()
233
dn.(*Dentry).setVerSeq(d.getVerSeq())
234
d.setVerSeq(mpVerSeq)
235
d.multiSnap.dentryList = append([]*Dentry{dn.(*Dentry)}, d.multiSnap.dentryList...)
236
log.LogDebugf("action[deleteTopLayer.delSeq_0] create version and push to dentry list. dentry %v", dn.(*Dentry))
238
d.setVerSeq(mpVerSeq)
240
d.setVerSeq(mpVerSeq)
241
d.setDeleted() // denParm create at the same version.no need to push to history list
242
log.LogDebugf("action[deleteTopLayer.delSeq_0] den %v be set deleted at version seq [%v]", d, mpVerSeq)
244
return d, true, false
247
func (d *Dentry) updateTopLayerSeq(delVerSeq uint64, verlist []*proto.VolVersionInfo) (rd *Dentry, dmore bool, clean bool) {
248
if !isSeqEqual(delVerSeq, d.getVerSeq()) {
249
// header layer do nothing and be depends on should not be dropped
250
log.LogDebugf("action[updateTopLayerSeq.inSnapList_del_%v] den %v first layer do nothing", delVerSeq, d)
251
return d, false, false
253
for _, info := range verlist {
254
if info.Ver > d.getVerSeq() {
255
d.setVerSeq(info.Ver)
256
return d, false, false
262
func (d *Dentry) cleanDeletedVersion(index int) (bDrop bool) {
264
if len(d.multiSnap.dentryList) == 0 && d.isDeleted() {
270
if !d.multiSnap.dentryList[delIdx].isDeleted() {
274
// del the dentry before
275
log.LogDebugf("ction[cleanDeleteVersion] dentry (%v) delete the last seq [%v] which set deleted before",
276
d, d.multiSnap.dentryList[delIdx].getVerSeq())
277
d.multiSnap.dentryList = append(d.multiSnap.dentryList[:delIdx], d.multiSnap.dentryList[:delIdx+1]...)
279
if len(d.multiSnap.dentryList) == 0 && d.isDeleted() {
280
log.LogDebugf("ction[cleanDeleteVersion] dentry (%v) require to be deleted", d)
286
// the lastest dentry may be deleted before and set status DentryDeleted,
287
// the scope of deleted happened from the DentryDeleted flag owner(include in) to the file with the same name be created is invisible,
288
// if create anther dentry with larger verSeq, put the deleted dentry to the history list.
289
// return doMore bool.True means need do next step on caller such as unlink parentIO
290
func (d *Dentry) deleteVerSnapshot(delVerSeq uint64, mpVerSeq uint64, verlist []*proto.VolVersionInfo) (rd *Dentry, dmore bool, clean bool) { // bool is doMore
291
log.LogDebugf("action[deleteVerSnapshot] enter.dentry %v delVerseq [%v] mpver [%v] verList %v", d, delVerSeq, mpVerSeq, verlist)
292
// create denParm version
293
if !isInitSnapVer(delVerSeq) && delVerSeq > mpVerSeq {
294
panic(fmt.Sprintf("Dentry version %v large than mp[%v]", delVerSeq, mpVerSeq))
298
return d.deleteTopLayer(mpVerSeq)
305
if den, idx = d.getDentryFromVerList(delVerSeq, true); den == nil {
306
log.LogDebugf("action[deleteVerSnapshot.inSnapList_del_%v] den %v not found", delVerSeq, d)
307
return nil, false, false
309
if idx == 0 { // top layer
310
return d.updateTopLayerSeq(delVerSeq, verlist)
312
// if any alive snapshot in mp dimension exist in seq scope from den to next ascend neighbor, dio snapshot be keep or else drop
313
startSeq := den.getVerSeq()
314
realIdx := idx - 1 // index in history list layer
316
endSeq = d.getVerSeq()
318
endSeq = d.multiSnap.dentryList[realIdx-1].getVerSeq()
319
if d.multiSnap.dentryList[realIdx-1].isDeleted() {
320
log.LogInfof("action[deleteVerSnapshot.inSnapList_del_%v] inode[%v] layer %v name %v be deleted already!",
321
delVerSeq, d.Inode, realIdx, d.multiSnap.dentryList[realIdx-1].Name)
325
log.LogDebugf("action[deleteVerSnapshot.inSnapList_del_%v] inode[%v] try drop multiVersion idx %v effective seq scope [%v,%v) ", delVerSeq,
326
d.Inode, realIdx, den.getVerSeq(), endSeq)
328
for _, info := range verlist {
329
if info.Ver >= startSeq && info.Ver < endSeq { // the version itself not include in
330
log.LogDebugf("action[deleteVerSnapshotInList.inSnapList_del_%v] inode[%v] dir layer idx %v include snapshot %v.don't drop", delVerSeq, den.Inode, realIdx, info.Ver)
331
// there's some snapshot depends on the version trying to be deleted,
332
// keep it,all the snapshots which depends on this version will reach here when make snapshot delete, and found the scope is minimized
333
// other versions depends upon this version will be found zero finally after deletions and do clean
334
den.setVerSeq(info.Ver)
335
return den, false, false
337
if info.Ver >= endSeq {
340
log.LogDebugf("action[deleteVerSnapshotInList.inSnapList_del_%v] inode[%v] try drop scope [%v, %v), mp ver [%v] not suitable",
341
delVerSeq, den.Inode, den.getVerSeq(), endSeq, info.Ver)
344
log.LogDebugf("action[deleteVerSnapshotInList.inSnapList_del_%v] inode[%v] try drop multiVersion idx %v", delVerSeq, den.Inode, realIdx)
345
d.multiSnap.dentryList = append(d.multiSnap.dentryList[:realIdx], d.multiSnap.dentryList[realIdx+1:]...)
346
if d.cleanDeletedVersion(realIdx) {
347
return den, true, true
349
return den, false, false
353
func (d *Dentry) String() string {
354
str := fmt.Sprintf("dentry(name:[%v],parentId:[%v],inode:[%v],type:[%v],seq:[%v],isDeleted:[%v],dentryList_len[%v])",
355
d.Name, d.ParentId, d.Inode, d.Type, d.getVerSeq(), d.isDeleted(), d.getSnapListLen())
356
if d.getSnapListLen() > 0 {
357
for idx, den := range d.multiSnap.dentryList {
358
str += fmt.Sprintf("idx:%v,content(%v))", idx, den)
364
type TxDentry struct {
367
TxInfo *proto.TransactionInfo
370
func NewTxDentry(parentID uint64, name string, ino uint64, mode uint32, parInode *Inode, txInfo *proto.TransactionInfo) *TxDentry {
378
txDentry := &TxDentry{
379
// ParInode: parInode,
386
func (td *TxDentry) Marshal() (result []byte, err error) {
387
buff := bytes.NewBuffer(make([]byte, 0))
389
//bs, err := td.ParInode.Marshal()
393
//if err = binary.Write(buff, binary.BigEndian, uint32(len(bs))); err != nil {
396
//if _, err := buff.Write(bs); err != nil {
400
bs, err := td.Dentry.Marshal()
404
if err = binary.Write(buff, binary.BigEndian, uint32(len(bs))); err != nil {
407
if _, err := buff.Write(bs); err != nil {
411
bs, err = td.TxInfo.Marshal()
415
if err = binary.Write(buff, binary.BigEndian, uint32(len(bs))); err != nil {
418
if _, err := buff.Write(bs); err != nil {
421
result = buff.Bytes()
425
func (td *TxDentry) Unmarshal(raw []byte) (err error) {
426
buff := bytes.NewBuffer(raw)
428
if err = binary.Read(buff, binary.BigEndian, &dataLen); err != nil {
431
data := make([]byte, int(dataLen))
432
if _, err = buff.Read(data); err != nil {
437
if err = dentry.Unmarshal(data); err != nil {
442
if err = binary.Read(buff, binary.BigEndian, &dataLen); err != nil {
445
data = make([]byte, int(dataLen))
446
if _, err = buff.Read(data); err != nil {
449
txInfo := proto.NewTransactionInfo(0, proto.TxTypeUndefined)
450
if err = txInfo.Unmarshal(data); err != nil {
457
type TxUpdateDentry struct {
460
TxInfo *proto.TransactionInfo
463
func NewTxUpdateDentry(oldDentry *Dentry, newDentry *Dentry, txInfo *proto.TransactionInfo) *TxUpdateDentry {
464
txUpdateDentry := &TxUpdateDentry{
465
OldDentry: oldDentry,
466
NewDentry: newDentry,
469
return txUpdateDentry
472
func (td *TxUpdateDentry) Marshal() (result []byte, err error) {
473
buff := bytes.NewBuffer(make([]byte, 0))
474
bs, err := td.OldDentry.Marshal()
478
if err = binary.Write(buff, binary.BigEndian, uint32(len(bs))); err != nil {
481
if _, err := buff.Write(bs); err != nil {
485
bs, err = td.NewDentry.Marshal()
489
if err = binary.Write(buff, binary.BigEndian, uint32(len(bs))); err != nil {
492
if _, err := buff.Write(bs); err != nil {
496
bs, err = td.TxInfo.Marshal()
500
if err = binary.Write(buff, binary.BigEndian, uint32(len(bs))); err != nil {
503
if _, err := buff.Write(bs); err != nil {
506
result = buff.Bytes()
510
func (td *TxUpdateDentry) Unmarshal(raw []byte) (err error) {
511
buff := bytes.NewBuffer(raw)
513
if err = binary.Read(buff, binary.BigEndian, &dataLen); err != nil {
516
data := make([]byte, int(dataLen))
517
if _, err = buff.Read(data); err != nil {
521
oldDentry := &Dentry{}
522
if err = oldDentry.Unmarshal(data); err != nil {
525
td.OldDentry = oldDentry
527
if err = binary.Read(buff, binary.BigEndian, &dataLen); err != nil {
530
data = make([]byte, int(dataLen))
531
if _, err = buff.Read(data); err != nil {
535
newDentry := &Dentry{}
536
if err = newDentry.Unmarshal(data); err != nil {
539
td.NewDentry = newDentry
541
if err = binary.Read(buff, binary.BigEndian, &dataLen); err != nil {
544
data = make([]byte, int(dataLen))
545
if _, err = buff.Read(data); err != nil {
548
txInfo := proto.NewTransactionInfo(0, proto.TxTypeUndefined)
549
if err = txInfo.Unmarshal(data); err != nil {
556
type DentryBatch []*Dentry
558
// todo(leon chang), buffer need alloc first before and write directly consider the space and performance
560
// Marshal marshals a dentry into a byte array.
561
func (d *Dentry) Marshal() (result []byte, err error) {
562
keyBytes := d.MarshalKey()
563
valBytes := d.MarshalValue()
564
keyLen := uint32(len(keyBytes))
565
valLen := uint32(len(valBytes))
566
buff := bytes.NewBuffer(make([]byte, 0))
567
buff.Grow(int(keyLen + valLen + 8))
569
if err = binary.Write(buff, binary.BigEndian, keyLen); err != nil {
572
if _, err = buff.Write(keyBytes); err != nil {
575
if err = binary.Write(buff, binary.BigEndian, valLen); err != nil {
578
if _, err = buff.Write(valBytes); err != nil {
581
result = buff.Bytes()
585
// Unmarshal unmarshals the dentry from a byte array.
586
func (d *Dentry) Unmarshal(raw []byte) (err error) {
591
buff := bytes.NewBuffer(raw)
592
if err = binary.Read(buff, binary.BigEndian, &keyLen); err != nil {
595
keyBytes := make([]byte, keyLen)
596
if _, err = buff.Read(keyBytes); err != nil {
599
if err = d.UnmarshalKey(keyBytes); err != nil {
602
if err = binary.Read(buff, binary.BigEndian, &valLen); err != nil {
605
valBytes := make([]byte, valLen)
606
if _, err = buff.Read(valBytes); err != nil {
609
err = d.UnmarshalValue(valBytes)
613
// Marshal marshals the dentryBatch into a byte array.
614
func (d DentryBatch) Marshal() ([]byte, error) {
615
buff := bytes.NewBuffer(make([]byte, 0))
616
if err := binary.Write(buff, binary.BigEndian, uint32(len(d))); err != nil {
619
for _, dentry := range d {
620
bs, err := dentry.Marshal()
624
if err = binary.Write(buff, binary.BigEndian, uint32(len(bs))); err != nil {
627
if _, err := buff.Write(bs); err != nil {
631
return buff.Bytes(), nil
634
// Unmarshal unmarshals the dentryBatch.
635
func DentryBatchUnmarshal(raw []byte) (DentryBatch, error) {
636
buff := bytes.NewBuffer(raw)
638
if err := binary.Read(buff, binary.BigEndian, &batchLen); err != nil {
642
result := make(DentryBatch, 0, int(batchLen))
645
for j := 0; j < int(batchLen); j++ {
646
if err := binary.Read(buff, binary.BigEndian, &dataLen); err != nil {
649
data := make([]byte, int(dataLen))
650
if _, err := buff.Read(data); err != nil {
654
if err := den.Unmarshal(data); err != nil {
657
result = append(result, den)
663
// Less tests whether the current dentry is less than the given one.
664
// This method is necessary fot B-Tree item implementation.
665
func (d *Dentry) Less(than BtreeItem) (less bool) {
666
dentry, ok := than.(*Dentry)
667
less = ok && ((d.ParentId < dentry.ParentId) || ((d.ParentId == dentry.ParentId) && (d.Name < dentry.Name)))
671
func (d *Dentry) CopyDirectly() BtreeItem {
673
newDentry.multiSnap = nil
677
func (d *Dentry) Copy() BtreeItem {
679
if d.multiSnap != nil {
680
newDentry.multiSnap = &DentryMultiSnap{
681
VerSeq: d.multiSnap.VerSeq,
682
dentryList: d.multiSnap.dentryList,
688
// MarshalKey is the bytes version of the MarshalKey method which returns the byte slice result.
689
func (d *Dentry) MarshalKey() (k []byte) {
690
buff := bytes.NewBuffer(make([]byte, 0))
692
if err := binary.Write(buff, binary.BigEndian, &d.ParentId); err != nil {
695
buff.Write([]byte(d.Name))
700
// UnmarshalKey unmarshals the exporterKey from bytes.
701
func (d *Dentry) UnmarshalKey(k []byte) (err error) {
702
buff := bytes.NewBuffer(k)
703
if err = binary.Read(buff, binary.BigEndian, &d.ParentId); err != nil {
706
d.Name = string(buff.Bytes())
710
func (d *Dentry) MarshalValue() []byte {
711
buff := bytes.NewBuffer(nil)
712
buff.Grow(24 + d.getSnapListLen()*20)
714
writeBinary := func(data interface{}) {
715
if err := binary.Write(buff, binary.BigEndian, data); err != nil {
720
writeBinary(&d.Inode)
722
seq := d.getSeqFiled()
728
verCnt := uint32(d.getSnapListLen())
731
if d.getSnapListLen() > 0 {
732
for _, dd := range d.multiSnap.dentryList {
733
writeBinary(&dd.Inode)
734
writeBinary(&dd.Type)
735
seq = dd.getSeqFiled()
743
func (d *Dentry) UnmarshalValue(val []byte) (err error) {
744
buff := bytes.NewBuffer(val)
745
if err = binary.Read(buff, binary.BigEndian, &d.Inode); err != nil {
748
if err = binary.Read(buff, binary.BigEndian, &d.Type); err != nil {
754
if err = binary.Read(buff, binary.BigEndian, &seq); err != nil {
758
d.multiSnap = NewDentrySnap(seq)
761
if err = binary.Read(buff, binary.BigEndian, &verCnt); err != nil {
765
for i := 0; i < int(verCnt); i++ {
766
// todo(leonchang) name and parentid should be removed to reduce space
769
ParentId: d.ParentId,
771
if err = binary.Read(buff, binary.BigEndian, &den.Inode); err != nil {
774
if err = binary.Read(buff, binary.BigEndian, &den.Type); err != nil {
777
if err = binary.Read(buff, binary.BigEndian, &seq); err != nil {
781
den.multiSnap = NewDentrySnap(seq)
783
d.multiSnap.dentryList = append(d.multiSnap.dentryList, den)