in tx.go [345:397]
func (tx *Tx) doCheckpointWAL() {
if tx.flags.checkpoint {
return
}
// collect page ids that would have an old WAL page
// entry still alive after this transaction.
ids := make([]PageID, 0, len(tx.file.wal.mapping))
walIDS := make([]PageID, 0, len(tx.file.wal.mapping))
for id, walID := range tx.file.wal.mapping {
page := tx.pages[id]
if page != nil {
if page.flags.dirty {
// wal pages of dirty pages will be freed on flush -> do not copy
continue
}
}
ids = append(ids, id)
walIDS = append(walIDS, walID)
}
if len(ids) == 0 {
return
}
// XXX: Some OS/filesystems might lock up when writing to file
// from mmapped area.
// -> Copy contents into temporary buffer, such that
// write operations are not backed by mmapped pages from same file.
pageSize := int(tx.PageSize())
writeBuffer := make([]byte, pageSize*len(ids))
for i := range ids {
id, walID := ids[i], walIDS[i]
contents := tx.access(walID)
if contents == nil {
panic("invalid WAL mapping")
}
tracef("checkpoint copy from WAL page %v -> %v\n", walID, id)
n := copy(writeBuffer, contents)
buf := writeBuffer[:n]
writeBuffer = writeBuffer[n:]
tx.file.writer.Schedule(tx.writeSync, id, buf)
tx.freeWALID(id, walID)
}
tx.onWALTransfer(len(ids))
tx.flags.checkpoint = true
}