github.com/Cloud-Foundations/Dominator@v0.3.4/lib/filesystem/rebuild.go (about) 1 package filesystem 2 3 import ( 4 "errors" 5 "fmt" 6 "path" 7 ) 8 9 func (fs *FileSystem) rebuildInodePointers() error { 10 return fs.DirectoryInode.rebuildInodePointers(fs) 11 } 12 13 func (inode *DirectoryInode) rebuildInodePointers(fs *FileSystem) error { 14 for _, dirent := range inode.EntryList { 15 tableInode, ok := fs.InodeTable[dirent.InodeNumber] 16 if !ok { 17 return fmt.Errorf("%s: no entry in inode table for: %d %p", 18 dirent.Name, dirent.InodeNumber, dirent.inode) 19 } 20 if tableInode == nil { 21 return fmt.Errorf("%s: nil entry in inode table for: %d %p", 22 dirent.Name, dirent.InodeNumber, dirent.inode) 23 } else if dirent.inode != nil && dirent.inode != tableInode { 24 return fmt.Errorf( 25 "%s: changing inode entry for: %d from: %p to %p\n", 26 dirent.Name, dirent.InodeNumber, dirent.inode, tableInode) 27 } 28 dirent.inode = tableInode 29 if inode, ok := dirent.inode.(*DirectoryInode); ok { 30 if err := inode.rebuildInodePointers(fs); err != nil { 31 return errors.New(dirent.Name + "/" + err.Error()) 32 } 33 } 34 } 35 return nil 36 } 37 38 func (fs *FileSystem) buildInodeToFilenamesTable() InodeToFilenamesTable { 39 if fs.inodeToFilenamesTable == nil { 40 fs.inodeToFilenamesTable = make(InodeToFilenamesTable) 41 fs.DirectoryInode.buildInodeToFilenamesTable(fs, "/") 42 } 43 return fs.inodeToFilenamesTable 44 } 45 46 func (inode *DirectoryInode) buildInodeToFilenamesTable(fs *FileSystem, 47 name string) { 48 for _, dirent := range inode.EntryList { 49 name := path.Join(name, dirent.Name) 50 fs.inodeToFilenamesTable[dirent.InodeNumber] = append( 51 fs.inodeToFilenamesTable[dirent.InodeNumber], name) 52 if inode, ok := dirent.inode.(*DirectoryInode); ok { 53 inode.buildInodeToFilenamesTable(fs, name) 54 } 55 } 56 } 57 58 func (fs *FileSystem) buildFilenameToInodeTable() FilenameToInodeTable { 59 if fs.filenameToInodeTable == nil { 60 fs.filenameToInodeTable = make(map[string]uint64) 61 for inum, filenames := range fs.InodeToFilenamesTable() { 62 for _, filename := range filenames { 63 fs.filenameToInodeTable[filename] = inum 64 } 65 } 66 67 } 68 return fs.filenameToInodeTable 69 } 70 71 func (fs *FileSystem) buildHashToInodesTable() HashToInodesTable { 72 if fs.hashToInodesTable == nil { 73 fs.hashToInodesTable = make(HashToInodesTable) 74 for inum, inode := range fs.InodeTable { 75 if inode, ok := inode.(*RegularInode); ok && inode.Size > 0 { 76 fs.hashToInodesTable[inode.Hash] = append( 77 fs.hashToInodesTable[inode.Hash], inum) 78 } 79 } 80 } 81 return fs.hashToInodesTable 82 } 83 84 func (fs *FileSystem) computeTotalDataBytes() { 85 fs.NumRegularInodes = 0 86 fs.TotalDataBytes = 0 87 for _, inode := range fs.InodeTable { 88 if inode, ok := inode.(*RegularInode); ok { 89 fs.NumRegularInodes++ 90 fs.TotalDataBytes += uint64(inode.Size) 91 } 92 } 93 } 94 95 func (fs *FileSystem) computeNumComputedRegularInodes() uint64 { 96 if fs.numComputedRegularInodes == nil { 97 var numInodes uint64 98 for _, inode := range fs.InodeTable { 99 if _, ok := inode.(*ComputedRegularInode); ok { 100 numInodes++ 101 } 102 } 103 fs.numComputedRegularInodes = &numInodes 104 } 105 return *fs.numComputedRegularInodes 106 } 107 108 func (inode *DirectoryInode) buildEntryMap() { 109 inode.EntriesByName = make(map[string]*DirectoryEntry) 110 for _, dirent := range inode.EntryList { 111 inode.EntriesByName[dirent.Name] = dirent 112 if inode, ok := dirent.inode.(*DirectoryInode); ok { 113 inode.buildEntryMap() 114 } 115 } 116 } 117 118 func (inode *DirectoryInode) registerStrings(registerFunc func(string)) { 119 for _, dirent := range inode.EntryList { 120 registerFunc(dirent.Name) 121 if inode, ok := dirent.inode.(*DirectoryInode); ok { 122 inode.registerStrings(registerFunc) 123 } 124 } 125 } 126 127 func (inode *DirectoryInode) replaceStrings(replaceFunc func(string) string) { 128 if inode.EntriesByName != nil { 129 inode.EntriesByName = make(map[string]*DirectoryEntry, 130 len(inode.EntryList)) 131 } 132 for _, dirent := range inode.EntryList { 133 dirent.Name = replaceFunc(dirent.Name) 134 if inode.EntriesByName != nil { 135 inode.EntriesByName[dirent.Name] = dirent 136 } 137 if inode, ok := dirent.inode.(*DirectoryInode); ok { 138 inode.replaceStrings(replaceFunc) 139 } 140 } 141 }