func (sub *Sub) compareEntries(request *subproto.UpdateRequest, subEntry, requiredEntry *filesystem.DirectoryEntry, myPathName string) { subInode := subEntry.Inode() requiredInode := requiredEntry.Inode() sameType, sameMetadata, sameData := filesystem.CompareInodes( subInode, requiredInode, nil) if requiredInode, ok := requiredInode.(*filesystem.DirectoryInode); ok { if sameMetadata { return } if sameType { makeDirectory(request, requiredInode, myPathName, false) } else { makeDirectory(request, requiredInode, myPathName, true) } return } if sameType && sameData && sameMetadata { sub.relink(request, subEntry, requiredEntry, myPathName) return } if sameType && sameData { sub.updateMetadata(request, requiredEntry, myPathName) sub.relink(request, subEntry, requiredEntry, myPathName) return } sub.addInode(request, requiredEntry, myPathName) }
func addFile(directory *filesystem.Directory, fileSystem, oldFS *FileSystem, name string, directoryPathName string, stat *syscall.Stat_t) error { inode, isNewInode := fileSystem.getInode(stat) var file filesystem.File file.Name = name file.InodeNumber = stat.Ino file.SetInode(inode) if isNewInode { err := scanFile(&file, fileSystem, directoryPathName) if err != nil { return err } if oldFS != nil && oldFS.InodeTable != nil { if oldInode, found := oldFS.InodeTable[stat.Ino]; found { if filesystem.CompareInodes(inode, oldInode, nil) { inode = oldInode file.SetInode(inode) fileSystem.InodeTable[stat.Ino] = inode } } } } directory.FileList = append(directory.FileList, &file) return nil }
func (sub *Sub) addInode(request *subproto.UpdateRequest, requiredEntry *filesystem.DirectoryEntry, myPathName string) { requiredInode := requiredEntry.Inode() if name, ok := sub.inodesCreated[requiredEntry.InodeNumber]; ok { makeHardlink(request, myPathName, name) return } // Try to find a sibling inode. names := sub.requiredFS.InodeToFilenamesTable()[requiredEntry.InodeNumber] subFS := sub.FileSystem if len(names) > 1 { var sameDataInode filesystem.GenericInode var sameDataName string for _, name := range names { if inum, found := subFS.FilenameToInodeTable()[name]; found { subInode := sub.FileSystem.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 { sub.updateMetadata(request, requiredEntry, sameDataName) makeHardlink(request, myPathName, sameDataName) return } } if inode, ok := requiredEntry.Inode().(*filesystem.RegularInode); ok { if inode.Size > 0 { if _, ok := sub.subObjectCacheUsage[inode.Hash]; ok { sub.subObjectCacheUsage[inode.Hash]++ } else { // Not in object cache: grab it from file-system. request.FilesToCopyToCache = append( request.FilesToCopyToCache, sub.getFileToCopy(myPathName, inode.Hash)) sub.subObjectCacheUsage[inode.Hash] = 1 } } } var inode subproto.Inode inode.Name = myPathName inode.GenericInode = requiredEntry.Inode() request.InodesToMake = append(request.InodesToMake, inode) sub.inodesCreated[requiredEntry.InodeNumber] = myPathName }
func layerImages(baseFS *filesystem.FileSystem, layerFS *filesystem.FileSystem) error { for filename, layerInum := range layerFS.FilenameToInodeTable() { layerInode := layerFS.InodeTable[layerInum] if _, ok := layerInode.(*filesystem.DirectoryInode); ok { continue } baseInum, ok := baseFS.FilenameToInodeTable()[filename] if !ok { return errors.New(filename + " missing in base image") } baseInode := baseFS.InodeTable[baseInum] sameType, sameMetadata, sameData := filesystem.CompareInodes(baseInode, layerInode, nil) if !sameType { return errors.New(filename + " changed type") } if sameMetadata && sameData { continue } baseFS.InodeTable[baseInum] = layerInode } return nil }
func compareFile(request *subproto.UpdateRequest, state *state, subEntry interface{}, requiredFile *filesystem.File, parentName string) { debugFilename := path.Join(parentName, requiredFile.Name) if subFile, ok := subEntry.(*filesystem.File); ok { if requiredInode, ok := state.subInodeToRequiredInode[subFile.InodeNumber]; ok { if requiredInode != requiredFile.InodeNumber { fmt.Printf("Different links: %s...\n", debugFilename) // HACK } } else { state.subInodeToRequiredInode[subFile.InodeNumber] = requiredFile.InodeNumber } if filesystem.CompareInodes(subFile.Inode(), requiredFile.Inode(), os.Stdout) { return } fmt.Printf("Different file: %s...\n", debugFilename) // HACK } else { fmt.Printf("Add file: %s...\n", debugFilename) // HACK } // TODO(rgooch): Delete entry and replace. }
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 }