-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathtape.js
executable file
·165 lines (162 loc) · 4.75 KB
/
tape.js
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
const fs = require('fs')
const readline = require('readline');
const path = require('path')
const stream = require('stream');
const write = function(str, logpath) {
return new Promise(function(resolve, reject) {
let lp = path.resolve(logpath, "../");
if (!fs.existsSync(lp)) {
fs.mkdirSync(lp, { recursive: true });
}
fs.appendFile(logpath, str + "\n", function(err, res) {
if (err) {
console.log("PLANARIA", err);
process.exit(1);
} else {
resolve();
}
})
})
}
const range = function (logpath) {
return new Promise(function(resolve, reject) {
if (fs.existsSync(logpath)) {
const instream = fs.createReadStream(logpath);
const outstream = new stream;
let r = readline.createInterface(instream, outstream);
let maxheight = null;
let minheight = null;
let log = [];
r.on('line', function(line) {
let chunks = line.split(" ");
let type = chunks[0];
let height = parseInt(chunks[1]);
if (['BLOCK', 'REWIND'].includes(type)) {
if (log.length >= 10) { log.shift() }
log.push({
type: type,
height: height,
hash: chunks[2],
prevHash: chunks[3],
time: parseInt(chunks[4])
})
// update maxheight
maxheight = height;
// update minheight only in the beginning
if (!minheight) {
minheight = height;
}
}
});
r.on('close', function() {
resolve({ end: maxheight, start: minheight, log: log })
/*
if (maxheight) {
resolve({ end: maxheight, start: minheight, log: log })
} else {
resolve(null)
}
*/
});
} else {
resolve(null)
}
})
}
// Given a tape path, returns both ends of the tape file: "start", "end"
// Process input (Bitcoin or Bitbus)
// 1. Replicate bitbus/bitcoin tape to planarian tape
// 2. Queue jobs from the tape
const current = async function(subdir, c) {
/*******************************************************
*
* 1. Get output tape (Planarian Log)
* => figure out where it left off
*
*******************************************************/
let destTape = await range(c.tape + "/tape.txt")
/*******************************************************
*
* 2. Get input tape (Bitbus Log)
* => figure out the start and the end of the chain
*
*******************************************************/
let srcTape;
if (typeof subdir === 'string') {
srcTape = await range(subdir + "/tape.txt")
} else {
srcTape = subdir;
}
/*******************************************************
*
* srcTape (bitbus || bitcoin)
*
* [start][.][.][.][.][.][.][end]
*
* destTape (planarian)
*
* [start][.][.][.][.][.][.][end]
*
* Read destTape and figure out where to resume from:
*
* 1. if destTape is empty
* 1.a. if 'from' exists, it overrides all other conditions. start from 'from'
* - however, if 'from' is smaller than srcTape.start, it must exit.
* 1.b. if srcTape is also empty, there's nothing to do. exit
* 1.c. if srcTape has an item, start from [srcTape.start]
* 2. if destTape has an item, start from [destTape.end+1]
*
*******************************************************/
let HEAD;
if (destTape && destTape.end) {
// destination tape exists. continue
if (srcTape.end) {
HEAD = destTape.end+1;
} else {
// dest exists but source tape doesn't exist.
// Need to warn in order to avoid out of sync
console.log("PLANARIA", "Planaria tape exists but source tape not availalble...Please update Planaria log to start in sync with source log.")
process.exit(1);
}
} else {
// destination tape doesn't exist.
if (c.filter && c.filter.from) {
// 'from' exists. it overrides everything else.
HEAD = c.filter.from;
} else if (srcTape.end) {
// start from source tape's beginning
HEAD = srcTape.start;
} else {
console.log("PLANARIA", "Source tape not available...")
process.exit(1);
}
}
return {
head: HEAD,
tape: {
src: srcTape,
self: {
start: (destTape ? destTape.start : null),
end: (destTape ? destTape.end : null),
log: (destTape ? destTape.log : []),
write: function(str) {
return new Promise(function(resolve, reject) {
fs.writeFile(c.log, str, function(err, res) {
if (err) {
console.log("PLANARIA", err);
process.exit(1);
} else {
resolve();
}
})
})
}
}
}
}
}
module.exports = {
write: write,
range: range,
current: current
}