ReadPage reads Page info & full Page data from a path. This is not transactionally safe.
(path string, pageID uint64)
| 19 | // ReadPage reads Page info & full Page data from a path. |
| 20 | // This is not transactionally safe. |
| 21 | func ReadPage(path string, pageID uint64) (*common.Page, []byte, error) { |
| 22 | // Find Page size. |
| 23 | pageSize, hwm, err := ReadPageAndHWMSize(path) |
| 24 | if err != nil { |
| 25 | return nil, nil, fmt.Errorf("read Page size: %s", err) |
| 26 | } |
| 27 | |
| 28 | // Open database file. |
| 29 | f, err := os.Open(path) |
| 30 | if err != nil { |
| 31 | return nil, nil, err |
| 32 | } |
| 33 | defer f.Close() |
| 34 | |
| 35 | // Read one block into buffer. |
| 36 | buf := make([]byte, pageSize) |
| 37 | if n, err := f.ReadAt(buf, int64(pageID*pageSize)); err != nil { |
| 38 | return nil, nil, err |
| 39 | } else if n != len(buf) { |
| 40 | return nil, nil, io.ErrUnexpectedEOF |
| 41 | } |
| 42 | |
| 43 | // Determine total number of blocks. |
| 44 | p := common.LoadPage(buf) |
| 45 | if p.Id() != common.Pgid(pageID) { |
| 46 | return nil, nil, fmt.Errorf("error: %w due to unexpected Page id: %d != %d", ErrCorrupt, p.Id(), pageID) |
| 47 | } |
| 48 | overflowN := p.Overflow() |
| 49 | if overflowN >= uint32(hwm)-3 { // we exclude 2 Meta pages and the current Page. |
| 50 | return nil, nil, fmt.Errorf("error: %w, Page claims to have %d overflow pages (>=hwm=%d). Interrupting to avoid risky OOM", ErrCorrupt, overflowN, hwm) |
| 51 | } |
| 52 | |
| 53 | if overflowN == 0 { |
| 54 | return p, buf, nil |
| 55 | } |
| 56 | |
| 57 | // Re-read entire Page (with overflow) into buffer. |
| 58 | buf = make([]byte, (uint64(overflowN)+1)*pageSize) |
| 59 | if n, err := f.ReadAt(buf, int64(pageID*pageSize)); err != nil { |
| 60 | return nil, nil, err |
| 61 | } else if n != len(buf) { |
| 62 | return nil, nil, io.ErrUnexpectedEOF |
| 63 | } |
| 64 | p = common.LoadPage(buf) |
| 65 | if p.Id() != common.Pgid(pageID) { |
| 66 | return nil, nil, fmt.Errorf("error: %w due to unexpected Page id: %d != %d", ErrCorrupt, p.Id(), pageID) |
| 67 | } |
| 68 | |
| 69 | return p, buf, nil |
| 70 | } |
| 71 | |
| 72 | func WritePage(path string, pageBuf []byte) error { |
| 73 | page := common.LoadPage(pageBuf) |