func (sub *Sub) getFileToCopy(myPathName string, hashVal hash.Hash) subproto.FileToCopyToCache { subFS := sub.FileSystem requiredFS := sub.requiredFS inos, ok := subFS.HashToInodesTable()[hashVal] if !ok { panic("No object in cache for: " + myPathName) } file := subproto.FileToCopyToCache{ Name: subFS.InodeToFilenamesTable()[inos[0]][0], Hash: hashVal, } // Try to find an inode where all its links will be deleted and mark one of // the links (filenames) to be hardlinked instead of copied into the cache. for _, iNum := range inos { filenames := subFS.InodeToFilenamesTable()[iNum] for _, filename := range filenames { if _, ok := requiredFS.FilenameToInodeTable()[filename]; ok { filenames = nil break } if sub.filter == nil || sub.filter.Match(filename) { filenames = nil break } } if filenames != nil { file.DoHardlink = true break } } return file }
func addInode(request *subproto.UpdateRequest, state *state, requiredEntry *filesystem.DirectoryEntry, myPathName string) { requiredInode := requiredEntry.Inode() if name, ok := state.inodesCreated[requiredEntry.InodeNumber]; ok { makeHardlink(request, myPathName, name) return } // Try to find a sibling inode. names := state.requiredFS.InodeToFilenamesTable[requiredEntry.InodeNumber] if len(names) > 1 { var sameDataInode filesystem.GenericInode var sameDataName string for _, name := range names { if inum, found := state.getSubInodeFromFilename(name); found { subInode := state.subFS.InodeTable[inum] _, sameMetadata, sameData := filesystem.CompareInodes( subInode, requiredInode, nil) if sameMetadata && sameData { makeHardlink(request, myPathName, name) return } if sameData { sameDataInode = subInode sameDataName = name } } } if sameDataInode != nil { updateMetadata(request, state, requiredEntry, sameDataName) makeHardlink(request, myPathName, sameDataName) return } } if inode, ok := requiredEntry.Inode().(*filesystem.RegularInode); ok { if inode.Size > 0 { if _, ok := state.subObjectCacheUsage[inode.Hash]; ok { state.subObjectCacheUsage[inode.Hash]++ } else { // Not in object cache: grab it from file-system. if state.subFS.HashToInodesTable == nil { state.subFS.BuildHashToInodesTable() } if ilist, ok := state.subFS.HashToInodesTable[inode.Hash]; ok { var fileToCopy subproto.FileToCopyToCache fileToCopy.Name = state.subFS.InodeToFilenamesTable[ilist[0]][0] fileToCopy.Hash = inode.Hash request.FilesToCopyToCache = append( request.FilesToCopyToCache, fileToCopy) state.subObjectCacheUsage[inode.Hash] = 1 } else { panic("No object in cache for: " + myPathName) } } } } var inode subproto.Inode inode.Name = myPathName inode.GenericInode = requiredEntry.Inode() request.InodesToMake = append(request.InodesToMake, inode) state.inodesCreated[requiredEntry.InodeNumber] = myPathName }