Skip to content

Commit 63789a9

Browse files
authored
Merge pull request #1413 from 0chain/fix/same-root
Add version to path
2 parents 1246de8 + c6c7338 commit 63789a9

File tree

10 files changed

+110
-88
lines changed

10 files changed

+110
-88
lines changed

code/go/0chain.net/blobbercore/allocation/allocationchange.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ type Result struct {
265265
PrevValidationRoot string
266266
ThumbnailHash string
267267
PrevThumbnailHash string
268+
FilestoreVersion int
268269
}
269270

270271
// TODO: Need to speed up this function
@@ -281,7 +282,7 @@ func (a *AllocationChangeCollector) MoveToFilestore(ctx context.Context) error {
281282

282283
err = datastore.GetStore().WithNewTransaction(func(ctx context.Context) error {
283284
tx := datastore.GetStore().GetTransaction(ctx)
284-
err := tx.Model(&reference.Ref{}).Clauses(clause.Locking{Strength: "NO KEY UPDATE"}).Select("id", "validation_root", "thumbnail_hash", "prev_validation_root", "prev_thumbnail_hash").Where("allocation_id=? AND is_precommit=? AND type=?", a.AllocationID, true, reference.FILE).
285+
err := tx.Model(&reference.Ref{}).Clauses(clause.Locking{Strength: "NO KEY UPDATE"}).Select("id", "validation_root", "thumbnail_hash", "prev_validation_root", "prev_thumbnail_hash", "filestore_version").Where("allocation_id=? AND is_precommit=? AND type=?", a.AllocationID, true, reference.FILE).
285286
FindInBatches(&refs, 50, func(tx *gorm.DB, batch int) error {
286287

287288
for _, ref := range refs {
@@ -303,27 +304,27 @@ func (a *AllocationChangeCollector) MoveToFilestore(ctx context.Context) error {
303304
}()
304305

305306
if count == 0 && ref.PrevValidationRoot != "" {
306-
err := filestore.GetFileStore().DeleteFromFilestore(a.AllocationID, ref.PrevValidationRoot)
307+
err := filestore.GetFileStore().DeleteFromFilestore(a.AllocationID, ref.PrevValidationRoot, ref.FilestoreVersion)
307308
if err != nil {
308309
logging.Logger.Error(fmt.Sprintf("Error while deleting file: %s", err.Error()),
309310
zap.String("validation_root", ref.ValidationRoot))
310311
}
311312
}
312-
err := filestore.GetFileStore().MoveToFilestore(a.AllocationID, ref.ValidationRoot)
313+
err := filestore.GetFileStore().MoveToFilestore(a.AllocationID, ref.ValidationRoot, ref.FilestoreVersion)
313314
if err != nil {
314315
logging.Logger.Error(fmt.Sprintf("Error while moving file: %s", err.Error()),
315316
zap.String("validation_root", ref.ValidationRoot))
316317
}
317318

318319
if ref.ThumbnailHash != "" && ref.ThumbnailHash != ref.PrevThumbnailHash {
319320
if ref.PrevThumbnailHash != "" {
320-
err := filestore.GetFileStore().DeleteFromFilestore(a.AllocationID, ref.PrevThumbnailHash)
321+
err := filestore.GetFileStore().DeleteFromFilestore(a.AllocationID, ref.PrevThumbnailHash, ref.FilestoreVersion)
321322
if err != nil {
322323
logging.Logger.Error(fmt.Sprintf("Error while deleting thumbnail file: %s", err.Error()),
323324
zap.String("thumbnail_hash", ref.ThumbnailHash))
324325
}
325326
}
326-
err := filestore.GetFileStore().MoveToFilestore(a.AllocationID, ref.ThumbnailHash)
327+
err := filestore.GetFileStore().MoveToFilestore(a.AllocationID, ref.ThumbnailHash, ref.FilestoreVersion)
327328
if err != nil {
328329
logging.Logger.Error(fmt.Sprintf("Error while moving thumbnail file: %s", err.Error()),
329330
zap.String("thumbnail_hash", ref.ThumbnailHash))
@@ -380,15 +381,16 @@ func deleteFromFileStore(ctx context.Context, allocationID string) error {
380381
}()
381382

382383
if count == 0 {
383-
err := filestore.GetFileStore().DeleteFromFilestore(allocationID, res.ValidationRoot)
384+
err := filestore.GetFileStore().DeleteFromFilestore(allocationID, res.ValidationRoot,
385+
res.FilestoreVersion)
384386
if err != nil {
385387
logging.Logger.Error(fmt.Sprintf("Error while deleting file: %s", err.Error()),
386388
zap.String("validation_root", res.ValidationRoot))
387389
}
388390
}
389391

390392
if res.ThumbnailHash != "" {
391-
err := filestore.GetFileStore().DeleteFromFilestore(allocationID, res.ThumbnailHash)
393+
err := filestore.GetFileStore().DeleteFromFilestore(allocationID, res.ThumbnailHash, res.FilestoreVersion)
392394
if err != nil {
393395
logging.Logger.Error(fmt.Sprintf("Error while deleting thumbnail: %s", err.Error()),
394396
zap.String("thumbnail", res.ThumbnailHash))

code/go/0chain.net/blobbercore/allocation/common_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,22 +37,22 @@ func (mfs *MockFileStore) CommitWrite(allocID, connID string, fileData *filestor
3737
return true, nil
3838
}
3939

40-
func (mfs *MockFileStore) MoveToFilestore(allocID, hash string) error {
40+
func (mfs *MockFileStore) MoveToFilestore(allocID, hash string, version int) error {
4141
return nil
4242
}
4343

4444
func (mfs *MockFileStore) DeleteAllocation(allocID string) {
4545
}
4646

47-
func (mfs *MockFileStore) DeleteFromFilestore(allocID, hash string) error {
47+
func (mfs *MockFileStore) DeleteFromFilestore(allocID, hash string, version int) error {
4848
return nil
4949
}
5050

5151
func (mfs *MockFileStore) DeleteTempFile(allocID, connID string, fileData *filestore.FileInputData) error {
5252
return nil
5353
}
5454

55-
func (mfs *MockFileStore) DeleteFile(allocID, contentHash string) error {
55+
func (mfs *MockFileStore) DeleteFile(allocID, contentHash string, version int) error {
5656
return nil
5757
}
5858

@@ -64,7 +64,7 @@ func (mfs *MockFileStore) GetFileBlock(rin *filestore.ReadBlockInput) (*filestor
6464
return nil, nil
6565
}
6666

67-
func (mfs *MockFileStore) GetFilePathSize(allocID, contentHash, thumbHash string) (int64, int64, error) {
67+
func (mfs *MockFileStore) GetFilePathSize(allocID, contentHash, thumbHash string, version int) (int64, int64, error) {
6868
return 0, 0, nil
6969
}
7070

@@ -112,7 +112,7 @@ func (mfs *MockFileStore) CalculateCurrentDiskCapacity() error {
112112
return nil
113113
}
114114

115-
func (mfs *MockFileStore) GetPathForFile(allocID, contentHash string) (string, error) {
115+
func (mfs *MockFileStore) GetPathForFile(allocID, contentHash string, version int) (string, error) {
116116
return "", nil
117117
}
118118

code/go/0chain.net/blobbercore/allocation/deletefilechange.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,18 @@ func (nf *DeleteFileChange) DeleteTempFile() error {
6161
func (nf *DeleteFileChange) CommitToFileStore(ctx context.Context, mut *sync.Mutex) error {
6262
db := datastore.GetStore().GetTransaction(ctx)
6363
type Result struct {
64-
Id string
65-
ValidationRoot string
66-
ThumbnailHash string
64+
Id string
65+
ValidationRoot string
66+
ThumbnailHash string
67+
FilestoreVersion int
6768
}
6869

6970
limitCh := make(chan struct{}, 10)
7071
wg := &sync.WaitGroup{}
7172
var results []Result
7273
mut.Lock()
7374
err := db.Model(&reference.Ref{}).Unscoped().
74-
Select("id", "validation_root", "thumbnail_hash").
75+
Select("id", "validation_root", "thumbnail_hash", "filestore_version").
7576
Where("allocation_id=? AND path LIKE ? AND type=? AND deleted_at is not NULL",
7677
nf.AllocationID, nf.Path+"%", reference.FILE).
7778
FindInBatches(&results, 100, func(tx *gorm.DB, batch int) error {
@@ -96,7 +97,7 @@ func (nf *DeleteFileChange) CommitToFileStore(ctx context.Context, mut *sync.Mut
9697
}()
9798

9899
if count == 0 {
99-
err := filestore.GetFileStore().DeleteFile(nf.AllocationID, res.ValidationRoot)
100+
err := filestore.GetFileStore().DeleteFile(nf.AllocationID, res.ValidationRoot, res.FilestoreVersion)
100101
if err != nil {
101102
logging.Logger.Error(fmt.Sprintf("Error while deleting file: %s", err.Error()),
102103
zap.String("validation_root", res.ValidationRoot))

code/go/0chain.net/blobbercore/allocation/file_changer_update.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ func (nf *UpdateFileChanger) ApplyChange(ctx context.Context, rootRef *reference
7878
nf.deleteHash = make(map[string]int)
7979

8080
if fileRef.ValidationRoot != "" && fileRef.ValidationRoot != nf.ValidationRoot {
81-
nf.deleteHash[fileRef.ValidationRoot] = int(CONTENT)
81+
nf.deleteHash[fileRef.ValidationRoot] = fileRef.FilestoreVersion
8282
}
8383

8484
fileRef.ActualFileHash = nf.ActualHash
@@ -106,7 +106,7 @@ func (nf *UpdateFileChanger) ApplyChange(ctx context.Context, rootRef *reference
106106

107107
func (nf *UpdateFileChanger) CommitToFileStore(ctx context.Context, mut *sync.Mutex) error {
108108
db := datastore.GetStore().GetTransaction(ctx)
109-
for hash := range nf.deleteHash {
109+
for hash, version := range nf.deleteHash {
110110
var count int64
111111
mut.Lock()
112112
err := db.Table((&reference.Ref{}).TableName()).
@@ -116,7 +116,7 @@ func (nf *UpdateFileChanger) CommitToFileStore(ctx context.Context, mut *sync.Mu
116116
mut.Unlock()
117117
if err == nil && count == 0 {
118118
logging.Logger.Info("Deleting content file", zap.String("validation_root", hash))
119-
if err := filestore.GetFileStore().DeleteFile(nf.AllocationID, hash); err != nil {
119+
if err := filestore.GetFileStore().DeleteFile(nf.AllocationID, hash, version); err != nil {
120120
logging.Logger.Error("FileStore_DeleteFile", zap.String("allocation_id", nf.AllocationID), zap.Error(err))
121121
}
122122
}

code/go/0chain.net/blobbercore/filestore/mock_store.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ func (fs *MockStore) DeleteTempFile(allocID, connID string, fileData *FileInputD
4949
return fs.FileStore.DeleteTempFile(allocID, connID, fileData)
5050
}
5151

52-
func (fs *MockStore) DeleteFile(allocationID, contentHash string) error {
53-
return fs.FileStore.DeleteFile(allocationID, contentHash)
52+
func (fs *MockStore) DeleteFile(allocationID, contentHash string, version int) error {
53+
return fs.FileStore.DeleteFile(allocationID, contentHash, version)
5454
}
5555

5656
func (fs *MockStore) GetFileBlock(rbi *ReadBlockInput) (*FileDownloadResponse, error) {
@@ -98,8 +98,8 @@ func (fs *MockStore) CalculateCurrentDiskCapacity() error {
9898
return fs.FileStore.CalculateCurrentDiskCapacity()
9999
}
100100

101-
func (fs *MockStore) GetPathForFile(allocID, contentHash string) (string, error) {
102-
return fs.FileStore.GetPathForFile(allocID, contentHash)
101+
func (fs *MockStore) GetPathForFile(allocID, contentHash string, version int) (string, error) {
102+
return fs.FileStore.GetPathForFile(allocID, contentHash, version)
103103
}
104104

105105
func (fs *MockStore) UpdateAllocationMetaData(m map[string]interface{}) error {

code/go/0chain.net/blobbercore/filestore/storage.go

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -143,14 +143,13 @@ func (fs *FileStore) GetTempFilePath(allocID, connID, fileName, filePathHash str
143143
return fs.getTempPathForFile(allocID, fileName, filePathHash, connID)
144144
}
145145

146-
func (fs *FileStore) MoveToFilestore(allocID, hash string) error {
147-
148-
fPath, err := fs.GetPathForFile(allocID, hash)
146+
func (fs *FileStore) MoveToFilestore(allocID, hash string, version int) error {
147+
fPath, err := fs.GetPathForFile(allocID, hash, version)
149148
if err != nil {
150149
return common.NewError("get_file_path_error", err.Error())
151150
}
152151

153-
preCommitPath := fs.getPreCommitPathForFile(allocID, hash)
152+
preCommitPath := fs.getPreCommitPathForFile(allocID, hash, version)
154153

155154
err = createDirs(filepath.Dir(fPath))
156155
if err != nil {
@@ -161,9 +160,9 @@ func (fs *FileStore) MoveToFilestore(allocID, hash string) error {
161160
return nil
162161
}
163162

164-
func (fs *FileStore) DeleteFromFilestore(allocID, hash string) error {
163+
func (fs *FileStore) DeleteFromFilestore(allocID, hash string, version int) error {
165164

166-
fPath, err := fs.GetPathForFile(allocID, hash)
165+
fPath, err := fs.GetPathForFile(allocID, hash, version)
167166
if err != nil {
168167
return common.NewError("get_file_path_error", err.Error())
169168
}
@@ -203,7 +202,7 @@ func (fs *FileStore) CommitWrite(allocID, conID string, fileData *FileInputData)
203202
fileHash = fileData.ThumbnailHash
204203
}
205204

206-
preCommitPath := fs.getPreCommitPathForFile(allocID, fileHash)
205+
preCommitPath := fs.getPreCommitPathForFile(allocID, fileHash, VERSION)
207206

208207
err := createDirs(filepath.Dir(preCommitPath))
209208
if err != nil {
@@ -323,9 +322,9 @@ func (fs *FileStore) CommitWrite(allocID, conID string, fileData *FileInputData)
323322
return true, nil
324323
}
325324

326-
func (fs *FileStore) GetFilePathSize(allocID, filehash, thumbHash string) (int64, int64, error) {
325+
func (fs *FileStore) GetFilePathSize(allocID, filehash, thumbHash string, version int) (int64, int64, error) {
327326

328-
filePath, err := fs.GetPathForFile(allocID, filehash)
327+
filePath, err := fs.GetPathForFile(allocID, filehash, version)
329328

330329
if err != nil {
331330
return 0, 0, err
@@ -340,7 +339,7 @@ func (fs *FileStore) GetFilePathSize(allocID, filehash, thumbHash string) (int64
340339
}
341340
var thumbSize int64
342341
if thumbHash != "" {
343-
thumbPath, err := fs.GetPathForFile(allocID, thumbHash)
342+
thumbPath, err := fs.GetPathForFile(allocID, thumbHash, version)
344343
if err != nil {
345344
return 0, 0, err
346345
}
@@ -356,9 +355,9 @@ func (fs *FileStore) GetFilePathSize(allocID, filehash, thumbHash string) (int64
356355
}
357356

358357
// Only decreasing the file size and number. Not deleting the file
359-
func (fs *FileStore) DeleteFile(allocID, validationRoot string) error {
358+
func (fs *FileStore) DeleteFile(allocID, validationRoot string, version int) error {
360359

361-
fileObjectPath, err := fs.GetPathForFile(allocID, validationRoot)
360+
fileObjectPath, err := fs.GetPathForFile(allocID, validationRoot, version)
362361
if err != nil {
363362
return err
364363
}
@@ -439,9 +438,9 @@ func (fs *FileStore) GetFileThumbnail(readBlockIn *ReadBlockInput) (*FileDownloa
439438
}
440439
if readBlockIn.IsPrecommit {
441440
fileObjectPath = fs.getPreCommitPathForFile(readBlockIn.AllocationID,
442-
readBlockIn.Hash)
441+
readBlockIn.Hash, readBlockIn.FilestoreVersion)
443442
} else {
444-
fileObjectPath, err = fs.GetPathForFile(readBlockIn.AllocationID, readBlockIn.Hash)
443+
fileObjectPath, err = fs.GetPathForFile(readBlockIn.AllocationID, readBlockIn.Hash, readBlockIn.FilestoreVersion)
445444
if err != nil {
446445
return nil, common.NewError("get_file_path_error", err.Error())
447446
}
@@ -450,7 +449,7 @@ func (fs *FileStore) GetFileThumbnail(readBlockIn *ReadBlockInput) (*FileDownloa
450449
file, err := os.Open(fileObjectPath)
451450
if err != nil {
452451
if readBlockIn.IsPrecommit {
453-
fileObjectPath, err = fs.GetPathForFile(readBlockIn.AllocationID, readBlockIn.Hash)
452+
fileObjectPath, err = fs.GetPathForFile(readBlockIn.AllocationID, readBlockIn.Hash, readBlockIn.FilestoreVersion)
454453
if err != nil {
455454
return nil, common.NewError("get_file_path_error", err.Error())
456455
}
@@ -519,17 +518,18 @@ func (fs *FileStore) GetFileBlock(readBlockIn *ReadBlockInput) (*FileDownloadRes
519518
return nil, common.NewError("invalid_block_number", "Invalid block number. Start block number cannot be negative")
520519
}
521520
if readBlockIn.IsPrecommit {
522-
fileObjectPath = fs.getPreCommitPathForFile(readBlockIn.AllocationID, readBlockIn.Hash)
521+
fileObjectPath = fs.getPreCommitPathForFile(readBlockIn.AllocationID, readBlockIn.Hash, readBlockIn.FilestoreVersion)
523522
} else {
524-
fileObjectPath, err = fs.GetPathForFile(readBlockIn.AllocationID, readBlockIn.Hash)
523+
fileObjectPath, err = fs.GetPathForFile(readBlockIn.AllocationID, readBlockIn.Hash, readBlockIn.FilestoreVersion)
525524
if err != nil {
526525
return nil, common.NewError("get_file_path_error", err.Error())
527526
}
528527
}
528+
529529
file, err := os.Open(fileObjectPath)
530530
if err != nil {
531531
if readBlockIn.IsPrecommit {
532-
fileObjectPath, err = fs.GetPathForFile(readBlockIn.AllocationID, readBlockIn.Hash)
532+
fileObjectPath, err = fs.GetPathForFile(readBlockIn.AllocationID, readBlockIn.Hash, readBlockIn.FilestoreVersion)
533533
if err != nil {
534534
return nil, common.NewError("get_file_path_error", err.Error())
535535
}
@@ -609,9 +609,9 @@ func (fs *FileStore) GetBlocksMerkleTreeForChallenge(in *ChallengeReadBlockInput
609609
}
610610

611611
if in.IsPrecommit {
612-
fileObjectPath = fs.getPreCommitPathForFile(in.AllocationID, in.Hash)
612+
fileObjectPath = fs.getPreCommitPathForFile(in.AllocationID, in.Hash, in.FilestoreVersion)
613613
} else {
614-
fileObjectPath, err = fs.GetPathForFile(in.AllocationID, in.Hash)
614+
fileObjectPath, err = fs.GetPathForFile(in.AllocationID, in.Hash, in.FilestoreVersion)
615615
if err != nil {
616616
return nil, err
617617
}
@@ -620,7 +620,7 @@ func (fs *FileStore) GetBlocksMerkleTreeForChallenge(in *ChallengeReadBlockInput
620620
file, err := os.Open(fileObjectPath)
621621
if err != nil {
622622
if in.IsPrecommit {
623-
fileObjectPath, err = fs.GetPathForFile(in.AllocationID, in.Hash)
623+
fileObjectPath, err = fs.GetPathForFile(in.AllocationID, in.Hash, in.FilestoreVersion)
624624
if err != nil {
625625
return nil, common.NewError("get_file_path_error", err.Error())
626626
}
@@ -792,12 +792,15 @@ func (fs *FileStore) getAllocDir(allocID string) string {
792792
return filepath.Join(fs.mp, getPartialPath(allocID, getDirLevelsForAllocations()))
793793
}
794794

795-
func (fs *FileStore) GetPathForFile(allocID, hash string) (string, error) {
795+
func (fs *FileStore) GetPathForFile(allocID, hash string, version int) (string, error) {
796796
if len(allocID) != 64 || len(hash) != 64 {
797797
return "", errors.New("length of allocationID/hash must be 64")
798798
}
799-
800-
return filepath.Join(fs.getAllocDir(allocID), getPartialPath(hash, getDirLevelsForFiles())), nil
799+
var versionStr string
800+
if version > 0 {
801+
versionStr = fmt.Sprintf("%d", version)
802+
}
803+
return filepath.Join(fs.getAllocDir(allocID), getPartialPath(hash, getDirLevelsForFiles())+versionStr), nil
801804
}
802805

803806
// getPath returns "/" separated strings with the given levels.
@@ -827,9 +830,14 @@ func (fs *FileStore) getTempPathForFile(allocId, fileName, pathHash, connectionI
827830
return filepath.Join(fs.getAllocTempDir(allocId), fileName+"."+pathHash+"."+connectionID)
828831
}
829832

830-
func (fs *FileStore) getPreCommitPathForFile(allocID, hash string) string {
833+
func (fs *FileStore) getPreCommitPathForFile(allocID, hash string, version int) string {
834+
835+
var versionStr string
836+
if version > 0 {
837+
versionStr = fmt.Sprintf("%d", version)
838+
}
831839

832-
return filepath.Join(fs.getPreCommitDir(allocID), getPartialPath(hash, getDirLevelsForFiles()))
840+
return filepath.Join(fs.getPreCommitDir(allocID), getPartialPath(hash, getDirLevelsForFiles())+versionStr)
833841
}
834842

835843
func (fs *FileStore) updateAllocTempFileSize(allocID string, size int64) {

code/go/0chain.net/blobbercore/filestore/store.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@ type FileStorer interface {
5252
WriteDataToTree(allocID, connID, fileName, filePathHash string, hahser *CommitHasher) error
5353
CommitWrite(allocID, connID string, fileData *FileInputData) (bool, error)
5454
DeleteTempFile(allocID, connID string, fileData *FileInputData) error
55-
DeleteFile(allocID, contentHash string) error
56-
MoveToFilestore(allocID, hash string) error
57-
DeleteFromFilestore(allocID, hash string) error
55+
DeleteFile(allocID, contentHash string, version int) error
56+
MoveToFilestore(allocID, hash string, version int) error
57+
DeleteFromFilestore(allocID, hash string, version int) error
5858
DeletePreCommitDir(allocID string) error
5959
DeleteAllocation(allocID string)
6060
// GetFileBlock Get blocks of file starting from blockNum upto numBlocks. blockNum can't be less than 1.
@@ -64,7 +64,7 @@ type FileStorer interface {
6464
GetTempFilesSizeOfAllocation(allocID string) uint64
6565
GetTotalCommittedFileSize() uint64
6666
GetCommittedFileSizeOfAllocation(allocID string) uint64
67-
GetFilePathSize(allocID, filehash, thumbHash string) (int64, int64, error)
67+
GetFilePathSize(allocID, filehash, thumbHash string, version int) (int64, int64, error)
6868
GetTotalFilesSize() uint64
6969
GetTotalFilesSizeOfAllocation(allocID string) uint64
7070
GetTempFilePath(allocID, connID, fileName, filePathHash string) string
@@ -75,7 +75,7 @@ type FileStorer interface {
7575
CalculateCurrentDiskCapacity() error
7676
// GetPathForFile given allocation id and content hash of a file, its path is calculated.
7777
// Will return error if allocation id or content hash are not of length 64
78-
GetPathForFile(allocID, contentHash string) (string, error)
78+
GetPathForFile(allocID, contentHash string, version int) (string, error)
7979
// UpdateAllocationMetaData only updates if allocation size has changed or new allocation is allocated. Must use allocationID.
8080
// Use of allocation Tx might leak memory. allocation size must be of int64 type otherwise it won't be updated
8181
UpdateAllocationMetaData(m map[string]interface{}) error

0 commit comments

Comments
 (0)