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

// WriteTo writes the entire database to a writer.
// If err == nil then exactly tx.Size() bytes will be written into the writer.
func (tx *Tx) WriteTo(w io.Writer) (n int64, err error) {
    // Attempt to open reader with WriteFlag
    f, err := os.OpenFile(tx.db.path, os.O_RDONLY|tx.WriteFlag, 0)
    if err != nil {
        return 0, err
    }
    defer func() { _ = f.Close() }()

    // Generate a meta page. We use the same page data for both meta pages.
    buf := make([]byte, tx.db.pageSize)
    page := (*page)(unsafe.Pointer(&buf[0]))
    page.flags = metaPageFlag
    *page.meta() = *tx.meta

    // Write meta 0.
    page.id = 0
    page.meta().checksum = page.meta().sum64()
    nn, err := w.Write(buf)
    n += int64(nn)
    if err != nil {
        return n, fmt.Errorf("meta 0 copy: %s", err)
    }

    // Write meta 1 with a lower transaction id.
    page.id = 1
    page.meta().txid -= 1
    page.meta().checksum = page.meta().sum64()
    nn, err = w.Write(buf)
    n += int64(nn)
    if err != nil {
        return n, fmt.Errorf("meta 1 copy: %s", err)
    }

    // Move past the meta pages in the file.
    if _, err := f.Seek(int64(tx.db.pageSize*2), os.SEEK_SET); err != nil {
        return n, fmt.Errorf("seek: %s", err)
    }

    // Copy data pages.
    wn, err := io.CopyN(w, f, tx.Size()-int64(tx.db.pageSize*2))
    n += wn
    if err != nil {
        return n, err
    }

    return n, f.Close()
}

// CopyFile copies the entire database to file at the given path.
// A reader transaction is maintained during the copy so it is safe to continue
// using the database while a copy is in progress.
func (tx *Tx) CopyFile(path string, mode os.FileMode) error {
    f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, mode)
    if err != nil {
        return err
    }

    err = tx.Copy(f)
    if err != nil {
        _ = f.Close()
        return err
    }
    return f.Close()
}

results matching ""

    No results matching ""