第六节 WriteTo()和CopyFile()实现

  1. // WriteTo writes the entire database to a writer.
  2. // If err == nil then exactly tx.Size() bytes will be written into the writer.
  3. func (tx *Tx) WriteTo(w io.Writer) (n int64, err error) {
  4. // Attempt to open reader with WriteFlag
  5. f, err := os.OpenFile(tx.db.path, os.O_RDONLY|tx.WriteFlag, 0)
  6. if err != nil {
  7. return 0, err
  8. }
  9. defer func() { _ = f.Close() }()
  10. // Generate a meta page. We use the same page data for both meta pages.
  11. buf := make([]byte, tx.db.pageSize)
  12. page := (*page)(unsafe.Pointer(&buf[0]))
  13. page.flags = metaPageFlag
  14. *page.meta() = *tx.meta
  15. // Write meta 0.
  16. page.id = 0
  17. page.meta().checksum = page.meta().sum64()
  18. nn, err := w.Write(buf)
  19. n += int64(nn)
  20. if err != nil {
  21. return n, fmt.Errorf("meta 0 copy: %s", err)
  22. }
  23. // Write meta 1 with a lower transaction id.
  24. page.id = 1
  25. page.meta().txid -= 1
  26. page.meta().checksum = page.meta().sum64()
  27. nn, err = w.Write(buf)
  28. n += int64(nn)
  29. if err != nil {
  30. return n, fmt.Errorf("meta 1 copy: %s", err)
  31. }
  32. // Move past the meta pages in the file.
  33. if _, err := f.Seek(int64(tx.db.pageSize*2), os.SEEK_SET); err != nil {
  34. return n, fmt.Errorf("seek: %s", err)
  35. }
  36. // Copy data pages.
  37. wn, err := io.CopyN(w, f, tx.Size()-int64(tx.db.pageSize*2))
  38. n += wn
  39. if err != nil {
  40. return n, err
  41. }
  42. return n, f.Close()
  43. }
  44. // CopyFile copies the entire database to file at the given path.
  45. // A reader transaction is maintained during the copy so it is safe to continue
  46. // using the database while a copy is in progress.
  47. func (tx *Tx) CopyFile(path string, mode os.FileMode) error {
  48. f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, mode)
  49. if err != nil {
  50. return err
  51. }
  52. err = tx.Copy(f)
  53. if err != nil {
  54. _ = f.Close()
  55. return err
  56. }
  57. return f.Close()
  58. }