-
Notifications
You must be signed in to change notification settings - Fork 11
/
logging2.go
146 lines (125 loc) · 2.85 KB
/
logging2.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package logging2
import (
"github.com/tchajed/goose/machine"
"github.com/tchajed/goose/machine/disk"
"sync"
)
const LOGCOMMIT = uint64(0)
const LOGSTART = uint64(1)
const LOGMAXBLK = uint64(510)
const LOGEND = LOGMAXBLK + LOGSTART
type Log struct {
logLock *sync.Mutex // protects on disk log
memLock *sync.Mutex // protects in-memory state
logSz uint64
memLog *[]disk.Block // in-memory log
memLen *uint64 // length of in-memory log
memTxnNxt *uint64 // next in-memory transaction number
logTxnNxt *uint64 // next log transaction number
}
func (log Log) writeHdr(len uint64) {
hdr := make([]byte, 4096)
machine.UInt64Put(hdr, len)
disk.Write(LOGCOMMIT, hdr)
}
func Init(logSz uint64) Log {
log := Log{
logLock: new(sync.Mutex),
memLock: new(sync.Mutex),
logSz: logSz,
memLog: new([]disk.Block),
memLen: new(uint64),
memTxnNxt: new(uint64),
logTxnNxt: new(uint64),
}
log.writeHdr(0)
return log
}
func (log Log) readHdr() uint64 {
hdr := disk.Read(LOGCOMMIT)
disklen := machine.UInt64Get(hdr)
return disklen
}
func (log Log) readBlocks(len uint64) []disk.Block {
var blks = make([]disk.Block, 0)
for i := uint64(0); i < len; i++ {
blk := disk.Read(LOGSTART + i)
blks = append(blks, blk)
}
return blks
}
func (log Log) Read() []disk.Block {
log.logLock.Lock()
disklen := log.readHdr()
blks := log.readBlocks(disklen)
log.logLock.Unlock()
return blks
}
func (log Log) memWrite(l []disk.Block) {
n := uint64(len(l))
for i := uint64(0); i < n; i++ {
*log.memLog = append(*log.memLog, l[i])
}
}
func (log Log) memAppend(l []disk.Block) (bool, uint64) {
log.memLock.Lock()
if *log.memLen+uint64(len(l)) >= log.logSz {
log.memLock.Unlock()
return false, uint64(0)
}
txn := *log.memTxnNxt
n := *log.memLen + uint64(len(l))
*log.memLen = n
*log.memTxnNxt = *log.memTxnNxt + 1
log.memLock.Unlock()
return true, txn
}
// XXX just an atomic read?
func (log Log) readLogTxnNxt() uint64 {
log.memLock.Lock()
n := *log.logTxnNxt
log.memLock.Unlock()
return n
}
func (log Log) diskAppendWait(txn uint64) {
for {
logtxn := log.readLogTxnNxt()
if txn < logtxn {
break
}
continue
}
}
func (log Log) Append(l []disk.Block) bool {
ok, txn := log.memAppend(l)
if ok {
log.diskAppendWait(txn)
}
return ok
}
func (log Log) writeBlocks(l []disk.Block, pos uint64) {
n := uint64(len(l))
for i := uint64(0); i < n; i++ {
bk := l[i]
disk.Write(pos+i, bk)
}
}
func (log Log) diskAppend() {
log.logLock.Lock()
disklen := log.readHdr()
log.memLock.Lock()
memlen := *log.memLen
allblks := *log.memLog
blks := allblks[disklen:]
memnxt := *log.memTxnNxt
log.memLock.Unlock()
log.writeBlocks(blks, disklen)
log.writeHdr(memlen)
*log.logTxnNxt = memnxt // XXX updating wo holding lock, atomic write?
log.logLock.Unlock()
}
func (log Log) Logger() {
for {
log.diskAppend()
}
}