func TestDirectIo(t *testing.T) { // Make a temporary file name fd, err := ioutil.TempFile("", "direct_io_test") if err != nil { t.Fatal("Failed to make temp file", err) } path := fd.Name() fd.Close() // starting block block1 := directio.AlignedBlock(directio.BlockSize) for i := 0; i < len(block1); i++ { block1[i] = 'A' } // Write the file out, err := directio.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0666) if err != nil { t.Fatal("Failed to directio.OpenFile for read", err) } _, err = out.Write(block1) if err != nil { t.Fatal("Failed to write", err) } err = out.Close() if err != nil { t.Fatal("Failed to close writer", err) } // Read the file block2 := directio.AlignedBlock(directio.BlockSize) in, err := directio.OpenFile(path, os.O_RDONLY, 0666) if err != nil { t.Fatal("Failed to directio.OpenFile for write", err) } _, err = io.ReadFull(in, block2) if err != nil { t.Fatal("Failed to read", err) } err = in.Close() if err != nil { t.Fatal("Failed to close reader", err) } // Tidy err = os.Remove(path) if err != nil { t.Fatal("Failed to remove temp file", path, err) } // Compare if !bytes.Equal(block1, block2) { t.Fatal("Read not the same as written") } }
// WriteFile writes the random source for size bytes to the file given // // Returns a true if the write failed, false otherwise. func WriteFile(file string, size int64) bool { out, err := directio.OpenFile(file, os.O_CREATE|os.O_WRONLY, 0666) if err != nil { log.Fatalf("Couldn't open file %q for write: %s\n", file, err) } log.Printf("Writing file %q size %d\n", file, size) failed := false random := NewRandom() br := NewBlockReader(random, "random") defer br.Close() for size > 0 { block := br.Read() _, err := out.Write(block) br.Return(block) if err != nil { log.Printf("Error while writing %q\n", file) failed = true break } size -= BlockSize stats.Written(BlockSize) } out.Close() if failed { log.Printf("Removing incomplete file %q\n", file) err = os.Remove(file) if err != nil { log.Fatalf("Failed to remove incomplete file %q: %s\n", file, err) } } return failed }
// ReadFile reads the file given and checks it against the random source func ReadFile(file string) { in, err := directio.OpenFile(file, os.O_RDONLY, 0666) if err != nil { log.Fatalf("Failed to open %s for reading: %s\n", file, err) } defer in.Close() random := NewRandom() pos := int64(0) log.Printf("Reading file %q\n", file) // FIXME this is similar code to ReadTwoFiles br1 := NewBlockReader(in, file) defer br1.Close() br2 := NewBlockReader(random, "random") defer br2.Close() output := true for { block1 := br1.Read() block2 := br2.Read() if block1 == nil { break } if bytes.Compare(block1, block2) != 0 { output = outputDiff(pos, block1, block2, output) } pos += BlockSize br1.Return(block1) br2.Return(block2) } }
func (s *streamSender) Run() error { if err := s.prepare(); err != nil { return err } if err := s.putHeader(&s.header); err != nil { return err } if len(s.srcname) > 0 { // always activate original lv so that target lv can be activated later if err := lvmutil.ActivateLv(s.vgname, s.srcname); err != nil { return err } defer lvmutil.DeactivateLv(s.vgname, s.srcname) } if err := lvmutil.ActivateLv(s.vgname, s.lvname); err != nil { return err } defer lvmutil.DeactivateLv(s.vgname, s.lvname) devpath := lvmutil.LvDevicePath(s.vgname, s.lvname) devFile, err := directio.OpenFile(devpath, os.O_RDONLY, 0644) if err != nil { return err } defer devFile.Close() buf := directio.AlignedBlock(int(s.header.BlockSize)) blockSize := int64(s.header.BlockSize) for _, e := range s.blocks { if e.OpType == thindump.DeltaOpDelete { for i := 0; i < len(buf); i++ { buf[i] = 0 } } else { if _, err := devFile.Seek(e.OriginBlock*blockSize, os.SEEK_SET); err != nil { return err } if _, err := io.ReadFull(devFile, buf); err != nil { return err } } if err := s.putBlock(e.OriginBlock, buf); err != nil { return err } } return nil }
// ReadTwoFiles reads two files and checks them to be the same as it goes along. // // It reads the files in BlockSize chunks. func ReadTwoFiles(file1, file2 string) { in1, err := directio.OpenFile(file1, os.O_RDONLY, 0666) if err != nil { log.Fatalf("Couldn't open file %q for read\n", file1) } defer in1.Close() in2, err := directio.OpenFile(file2, os.O_RDONLY, 0666) if err != nil { log.Fatalf("Couldn't open file %q for read\n", file2) } defer in2.Close() log.Printf("Reading file %q, %q\n", file1, file2) stats.SetMode(modeRead) defer stats.SetMode(modeReadDone) pos := int64(0) br1 := NewBlockReader(in1, file1) defer br1.Close() br2 := NewBlockReader(in2, file2) defer br2.Close() output := true for { block1 := br1.Read() block2 := br2.Read() if block1 == nil || block2 == nil { if block1 != nil || block2 != nil { log.Fatalf("Files %q and %q are different sizes\n", file1, file2) } break } if bytes.Compare(block1, block2) != 0 { output = outputDiff(pos, block1, block2, output) } pos += BlockSize br1.Return(block1) br2.Return(block2) } }
func main() { // Get hold of the current working dir cwd, err := os.Getwd() fatalIfErr(err) // Create a temporary file fd, err := ioutil.TempFile(cwd, "sleepless") fatalIfErr(err) // We just need the file name, we're going to reopen it with the right flags path := fd.Name() fd.Close() // Allocate a block which will be filled with garbage on each iteration garbage := directio.AlignedBlock(directio.BlockSize) // Get ready out, err := directio.OpenFile(path, os.O_CREATE|os.O_RDWR|os.O_SYNC, 0600) fatalIfErr(err) // Setup signal handling sigint := make(chan os.Signal, 1) signal.Notify(sigint, os.Interrupt) go func() { <-sigint cleanup(out, path) os.Exit(0) }() // Start the main loop for { // Garbage in... if _, err = rand.Read(garbage); err != nil { cleanup(out, path) log.Fatal(err) } // ... garbage out if _, err = out.Write(garbage); err != nil { cleanup(out, path) log.Fatal(err) } // Rewind the file to the start so that it does not grow // indefintely if _, err = out.Seek(0, os.SEEK_SET); err != nil { cleanup(out, path) log.Fatal(err) } // Take a nap time.Sleep(10 * time.Second) } }
func Open(path string, sch Scheduler) (Disk, error) { stat, err := os.Stat(path) if err != nil { return nil, err } f, err := directio.OpenFile(path, os.O_RDWR, 0666) if err != nil { return nil, err } return &disk{ f: f, sch: sch, size: uint64(stat.Size()), path: path, }, nil }
func (sr *streamRecver) recvNextStream() error { if err := sr.prepare(); err != nil { return err } devpath := lvmutil.LvDevicePath(sr.vgname, sr.lvname) devFile, err := directio.OpenFile(devpath, os.O_WRONLY, 0644) if err != nil { return err } defer devFile.Close() n := 8 + sr.header.BlockSize b := make([]byte, n+md5.Size) buf := directio.AlignedBlock(int(sr.header.BlockSize)) for i := uint64(0); i < sr.header.BlockCount; i++ { if _, err := io.ReadFull(sr.r, b); err != nil { return err } sr.h.Reset() sr.h.Write(b[:n]) if !bytes.Equal(sr.h.Sum(nil), b[n:n+md5.Size]) { return fmt.Errorf("check sum mismatch for %dst block", i) } index := int64(binary.BigEndian.Uint64(b)) copy(buf, b[8:n]) if _, err := devFile.Seek(int64(sr.header.BlockSize)*index, os.SEEK_SET); err != nil { return err } if _, err := devFile.Write(buf); err != nil { return err } } sr.prevUUID = string(sr.header.VolumeUUID[:]) return nil }
func (c *OSClient) open(filename string, flags int) (File, error) { fullpath := path.Join(c.RootDir, filename) var f *os.File var err error if c.Direct { f, err = directio.OpenFile(fullpath, flags, 0666) } else { f, err = os.OpenFile(fullpath, flags, 0644) } if err != nil { return nil, err } return &OSFile{ BaseFile: BaseFile{filename: fullpath}, file: f, }, nil }