@aj-shadow/z-abs-funclayer-database-server 0.0.0-aj-beta.221
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitattributes +26 -0
- package/LICENSE.txt +96 -0
- package/README.md +5 -0
- package/npm-shrinkwrap.json +13 -0
- package/package.json +10 -0
- package/project/server/_build/server-funclayer-database-server.bld +12 -0
- package/project/server/_build/z-abs-funclayer-database-server.prj +12 -0
- package/project/server/core/database-cache.js +128 -0
- package/project/server/core/database-const.js +71 -0
- package/project/server/core/database-database.js +126 -0
- package/project/server/core/database-lock.js +97 -0
- package/project/server/core/database-table.js +265 -0
- package/project/server/database-file/database-file.js +302 -0
- package/project/server/database-file/table-decoder.js +74 -0
- package/project/server/database-file/table-encoder.js +82 -0
- package/project/server/database-file/table-page.js +182 -0
- package/project/server/database-file/table.js +165 -0
- package/project/server/database-git/database-git.js +169 -0
- package/project/server/database-npm/database-npm.js +89 -0
- package/project/z-abs-funclayer-database-server.tree +21 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const DatabaseConst = require('../core/database-const');
|
|
5
|
+
const Encoder = require('z-abs-corelayer-server/server/communication/core-protocol/encoder');
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TableEncoder {
|
|
9
|
+
static encoder = new Encoder(null);
|
|
10
|
+
static size = 0;
|
|
11
|
+
|
|
12
|
+
static calculateSize(row, types) {
|
|
13
|
+
TableEncoder.encoder.calculate(true);
|
|
14
|
+
TableEncoder._encodeRow(row, types);
|
|
15
|
+
const size = TableEncoder.encoder.offset;
|
|
16
|
+
TableEncoder.encoder.calculate(false);
|
|
17
|
+
TableEncoder.encoder.clear();
|
|
18
|
+
return size;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
static encodeRow(row, types, size) {
|
|
22
|
+
TableEncoder.encoder.createBuffer(size);
|
|
23
|
+
TableEncoder._encodeRow(row, types);
|
|
24
|
+
const buffer = TableEncoder.encoder.buffer;
|
|
25
|
+
TableEncoder.encoder.clear();
|
|
26
|
+
return buffer;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
static _encodeRow(row, types) {
|
|
30
|
+
for(let i = 0; i < types.length; ++i) {
|
|
31
|
+
switch(types[i]) {
|
|
32
|
+
case DatabaseConst.COLUMN_TYPE_GUID:
|
|
33
|
+
TableEncoder.encoder.setGuid(row[i]);
|
|
34
|
+
break;
|
|
35
|
+
case DatabaseConst.COLUMN_TYPE_INT8:
|
|
36
|
+
TableEncoder.encoder.setInt8(row[i]);
|
|
37
|
+
break;
|
|
38
|
+
case DatabaseConst.COLUMN_TYPE_INT16:
|
|
39
|
+
TableEncoder.encoder.setInt16(row[i]);
|
|
40
|
+
break;
|
|
41
|
+
case DatabaseConst.COLUMN_TYPE_INT32:
|
|
42
|
+
TableEncoder.encoder.setInt32(row[i]);
|
|
43
|
+
break;
|
|
44
|
+
case DatabaseConst.COLUMN_TYPE_INT64:
|
|
45
|
+
TableEncoder.encoder.setBigInt64(row[i]);
|
|
46
|
+
break;
|
|
47
|
+
case DatabaseConst.COLUMN_TYPE_UINT8:
|
|
48
|
+
TableEncoder.encoder.setUint8(row[i]);
|
|
49
|
+
break;
|
|
50
|
+
case DatabaseConst.COLUMN_TYPE_UINT16:
|
|
51
|
+
TableEncoder.encoder.setUint16(row[i]);
|
|
52
|
+
break;
|
|
53
|
+
case DatabaseConst.COLUMN_TYPE_UINT32:
|
|
54
|
+
TableEncoder.encoder.setUint32(row[i]);
|
|
55
|
+
break;
|
|
56
|
+
case DatabaseConst.COLUMN_TYPE_UINT64:
|
|
57
|
+
TableEncoder.encoder.setBigUint64(row[i]);
|
|
58
|
+
break;
|
|
59
|
+
case DatabaseConst.COLUMN_TYPE_FLOAT32:
|
|
60
|
+
TableEncoder.encoder.setFloat32(row[i]);
|
|
61
|
+
break;
|
|
62
|
+
case DatabaseConst.COLUMN_TYPE_FLOAT64:
|
|
63
|
+
TableEncoder.encoder.setFloat64(row[i]);
|
|
64
|
+
break;
|
|
65
|
+
case DatabaseConst.COLUMN_TYPE_STRING:
|
|
66
|
+
TableEncoder.encoder.setString(row[i]);
|
|
67
|
+
break;
|
|
68
|
+
case DatabaseConst.COLUMN_TYPE_TIMESTAMP:
|
|
69
|
+
TableEncoder.encoder.setBigInt64(row[i]);
|
|
70
|
+
break;
|
|
71
|
+
default:
|
|
72
|
+
#BUILD_DEBUG_START
|
|
73
|
+
ddb.warning('DB type: ', types[i], ' is not supported.');
|
|
74
|
+
#BUILD_DEBUG_STOP
|
|
75
|
+
break;
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
module.exports = TableEncoder;
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const TableDecoder = require('./table-decoder');
|
|
5
|
+
const TableEncoder = require('./table-encoder');
|
|
6
|
+
const DatabaseConst = require('../core/database-const');
|
|
7
|
+
const Fs = require('fs');
|
|
8
|
+
const Path = require('path');
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class TablePage {
|
|
12
|
+
static GROW_SIZE = 0;
|
|
13
|
+
static INDEX_SIZE = 5;
|
|
14
|
+
static indexBuffer = null;
|
|
15
|
+
static dataBuffer = null;
|
|
16
|
+
|
|
17
|
+
constructor(id, tableName, rowIndex, pageSize, types, baseFileName) {
|
|
18
|
+
this.id = id;
|
|
19
|
+
this.tableName = tableName;
|
|
20
|
+
this.startRowIndex = rowIndex;
|
|
21
|
+
this.stopRowIndex = rowIndex;
|
|
22
|
+
this.indexes = [{start:-1, stop:-1, status:DatabaseConst.ROW_STATUS_NONE}];
|
|
23
|
+
this.types = types;
|
|
24
|
+
this.pageSize = pageSize;
|
|
25
|
+
this.freeSpace = pageSize;
|
|
26
|
+
this.dataFileName = `${baseFileName}-${id.toString().padStart(12, '0')}-data`;
|
|
27
|
+
this.fd = -1;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
active(isActive, cb) {
|
|
31
|
+
if(isActive) {
|
|
32
|
+
if(-1 === this.fd) {
|
|
33
|
+
Fs.open(this.dataFileName, 'r+', (err, fd) => {
|
|
34
|
+
if(err) {
|
|
35
|
+
ddb.error(`Could not open filehandler: '${this.dataFileName}'`);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
this.fd = fd;
|
|
39
|
+
}
|
|
40
|
+
cb(err);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
process.nextTick(cb);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
if(-1 === this.fd) {
|
|
49
|
+
process.nextTick(cb);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
Fs.close(this.fd, (err) => {
|
|
53
|
+
if(err) {
|
|
54
|
+
ddb.error(`Could not close filehandler: '${this.dataFileName}'`);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
this.fd = -1;
|
|
58
|
+
}
|
|
59
|
+
cb(err);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
insertRow(row, cb) {
|
|
66
|
+
const size = TableEncoder.calculateSize(row, this.types);
|
|
67
|
+
if(this.freeSpace - size - TablePage.INDEX_SIZE >= TablePage.GROW_SIZE) {
|
|
68
|
+
this.freeSpace -= (size + TablePage.INDEX_SIZE);
|
|
69
|
+
const buffer = TableEncoder.encodeRow(row, this.types, size);
|
|
70
|
+
const index = this.stopRowIndex - this.startRowIndex;
|
|
71
|
+
const indexData = this.indexes[index];
|
|
72
|
+
const start = indexData.stop + 1;
|
|
73
|
+
const stop = start + size;
|
|
74
|
+
const newIndexData = {start, stop, status:DatabaseConst.ROW_STATUS_EXISTS};
|
|
75
|
+
this._write(buffer, newIndexData, this.indexes.length, (err) => {
|
|
76
|
+
if(!err) {
|
|
77
|
+
this.indexes[index] = newIndexData;
|
|
78
|
+
this.indexes.push({start:-1, stop, status:DatabaseConst.ROW_STATUS_NONE});
|
|
79
|
+
++this.stopRowIndex;
|
|
80
|
+
}
|
|
81
|
+
cb(err);
|
|
82
|
+
});
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
updateRow(row, rowIndex, cb) {
|
|
91
|
+
const index = this.indexes[rowIndex - this.startRowIndex];
|
|
92
|
+
console.log(index);
|
|
93
|
+
const size = TableEncoder.calculateSize(row, this.types);
|
|
94
|
+
if(size === index.stop -index.start) {
|
|
95
|
+
console.log('SAME SIZE');
|
|
96
|
+
const buffer = TableEncoder.encodeRow(row, this.types, size);
|
|
97
|
+
this._write(buffer, index, this.indexes.length, cb);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
console.log('!SAME SIZE!');
|
|
101
|
+
process.nextTick(cb, new Error('Update row not the same size'));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
_writeClosed(buffer, indexData, index, cb) {
|
|
106
|
+
Fs.open(this.dataFileName, 'r+', (errOpen, fd) => {
|
|
107
|
+
if(errOpen) {
|
|
108
|
+
cb(errOpen);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
this._writeOpen(fd, buffer, indexData, index, (errWrite) => {
|
|
112
|
+
Fs.close(fd, (errClose) => {
|
|
113
|
+
cb(errWrite ? errWrite : errClose);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
_writeOpen(fd, buffer, indexData, index, cb) {
|
|
120
|
+
Fs.write(fd, buffer, 0, indexData.stop - indexData.start, indexData.start, (err, bytes) => {
|
|
121
|
+
if(err) {
|
|
122
|
+
cb(err);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
TablePage.indexBuffer.writeUInt16BE(indexData.start, 0);
|
|
126
|
+
TablePage.indexBuffer.writeUInt16BE(indexData.stop, 2);
|
|
127
|
+
TablePage.indexBuffer.writeUInt8(indexData.status, 4);
|
|
128
|
+
Fs.write(fd, TablePage.indexBuffer, 0, TablePage.INDEX_SIZE, this.pageSize - index * TablePage.INDEX_SIZE, (err, bytes) => {
|
|
129
|
+
cb(err);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
_write(buffer, indexData, index, cb) {
|
|
135
|
+
if(-1 !== this.fd) {
|
|
136
|
+
this._writeOpen(this.fd, buffer, indexData, index, cb);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
this._writeClosed(buffer, indexData, index, cb);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
createFile(cb) {
|
|
144
|
+
Fs.writeFile(this.dataFileName, TablePage.dataBuffer, cb);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
static parseFile(data, types, defaults, pageSize) {
|
|
148
|
+
let freeSpace = pageSize;
|
|
149
|
+
let index = 0;
|
|
150
|
+
let pos = pageSize - TablePage.INDEX_SIZE;
|
|
151
|
+
const indexes = [{start:-1, stop:-1, status:DatabaseConst.ROW_STATUS_NONE}];
|
|
152
|
+
const rows = [];
|
|
153
|
+
TableDecoder.decoder.buffer = data;
|
|
154
|
+
while(freeSpace >= TablePage.GROW_SIZE) {
|
|
155
|
+
const start = data.readUInt16BE(pos);
|
|
156
|
+
const stop = data.readUInt16BE(pos + 2);
|
|
157
|
+
const status = data.readUInt8(pos + 4);
|
|
158
|
+
const indexData = indexes[index++];
|
|
159
|
+
if(0 === stop) {
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
indexData.start = start;
|
|
163
|
+
indexData.stop = stop;
|
|
164
|
+
indexData.status = status;
|
|
165
|
+
indexes.push({start:-1, stop, status:DatabaseConst.ROW_STATUS_NONE});
|
|
166
|
+
const row = [];
|
|
167
|
+
TableDecoder.decodeRow(row, types, defaults, start, stop);
|
|
168
|
+
rows.push(row);
|
|
169
|
+
freeSpace -= (stop - start + TablePage.INDEX_SIZE);
|
|
170
|
+
pos -= TablePage.INDEX_SIZE;
|
|
171
|
+
}
|
|
172
|
+
TableDecoder.decoder.clear();
|
|
173
|
+
return {
|
|
174
|
+
indexes,
|
|
175
|
+
rows,
|
|
176
|
+
freeSpace
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
module.exports = TablePage;
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const TableEncoder = require('./table-encoder');
|
|
5
|
+
const TablePage = require('./table-page');
|
|
6
|
+
const DatabaseConst = require('../core/database-const');
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Table {
|
|
10
|
+
constructor(tableName, types, fileName) {
|
|
11
|
+
this.tableName = tableName;
|
|
12
|
+
this.types = types;
|
|
13
|
+
this.baseFileName = fileName;
|
|
14
|
+
this.nextRowIndex = 0;
|
|
15
|
+
this.nextPageIndex = 0;
|
|
16
|
+
this.meanSizeOfFullPages = 0;
|
|
17
|
+
this.tablePages = [];
|
|
18
|
+
this.pageSize = 8192;
|
|
19
|
+
this.pageLock = false;
|
|
20
|
+
this.pageLockQueue = [];
|
|
21
|
+
TablePage.indexBuffer = Buffer.allocUnsafeSlow(TablePage.INDEX_SIZE);
|
|
22
|
+
TablePage.dataBuffer = Buffer.allocUnsafeSlow(this.pageSize).fill(0);
|
|
23
|
+
TableEncoder.size = this.pageSize;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
createTable(cb) {
|
|
27
|
+
const tablePage = this._getTablePageNext();
|
|
28
|
+
tablePage.createFile((err) => {
|
|
29
|
+
if(err) {
|
|
30
|
+
cb(err);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
this.tablePages[this.nextPageIndex].active(true, cb);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
addTablePage(id) {
|
|
39
|
+
const tablePage = new TablePage(id, this.tableName, this.nextRowIndex, this.pageSize, this.types, this.baseFileName);
|
|
40
|
+
this.tablePages.push(tablePage);
|
|
41
|
+
return tablePage;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
parseTableFiles(fileDatas, table, cb) {
|
|
45
|
+
let fileData = fileDatas.shift();
|
|
46
|
+
let id = -1;
|
|
47
|
+
this.nextPageIndex = -1;
|
|
48
|
+
do {
|
|
49
|
+
++this.nextPageIndex;
|
|
50
|
+
const result = TablePage.parseFile(fileData.data, table.types, table.defaults, this.pageSize);
|
|
51
|
+
if(0 !== result.rows.length) {
|
|
52
|
+
Array.prototype.push.apply(table.rows, result.rows);
|
|
53
|
+
const tablePage = this.addTablePage(++id);
|
|
54
|
+
tablePage.stopRowIndex += result.rows.length;
|
|
55
|
+
tablePage.freeSpace = result.freeSpace;
|
|
56
|
+
tablePage.indexes = result.indexes;
|
|
57
|
+
this.nextRowIndex += result.rows.length;
|
|
58
|
+
}
|
|
59
|
+
fileData = fileDatas.shift();
|
|
60
|
+
} while(fileData);
|
|
61
|
+
const lastPos = this.tablePages.length - 1;
|
|
62
|
+
if(2 <= this.tablePages.length) {
|
|
63
|
+
const lastTablePage = this.tablePages[lastPos];
|
|
64
|
+
this.meanSizeOfFullPages = (this.nextRowIndex - (lastTablePage.stopRowIndex - lastTablePage.startRowIndex)) / (lastPos);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
this.meanSizeOfFullPages = 0;
|
|
68
|
+
}
|
|
69
|
+
if(lastPos >= 0) {
|
|
70
|
+
this.tablePages[lastPos].active(true, cb);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
cb(null);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
insertRow(row, cb) {
|
|
78
|
+
const tablePage = this._getTablePageNext();
|
|
79
|
+
if(!tablePage.insertRow(row, (err) => {
|
|
80
|
+
if(!err) {
|
|
81
|
+
++this.nextRowIndex;
|
|
82
|
+
}
|
|
83
|
+
cb(err);
|
|
84
|
+
})) {
|
|
85
|
+
this._createTablePage((err) => {
|
|
86
|
+
if(err) {
|
|
87
|
+
cb(err);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
const currentTablePage = this.tablePages[this.nextPageIndex];
|
|
91
|
+
this.meanSizeOfFullPages = this.meanSizeOfFullPages + ((currentTablePage.stopRowIndex - currentTablePage.startRowIndex) - this.meanSizeOfFullPages) / (this.tablePages.length - 1);
|
|
92
|
+
this.tablePages[this.nextPageIndex].active(false, () => {
|
|
93
|
+
++this.nextPageIndex;
|
|
94
|
+
this.tablePages[this.nextPageIndex].active(true, () => {
|
|
95
|
+
this.insertRow(row, cb);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
updateRow(row, rowIndex, cb) {
|
|
104
|
+
const possiblePageIndex = 0 === this.meanSizeOfFullPages ? 0 : Math.floor(rowIndex / this.meanSizeOfFullPages);
|
|
105
|
+
const tablePage = this._getPageFromRow(possiblePageIndex, rowIndex);
|
|
106
|
+
if(tablePage) {
|
|
107
|
+
tablePage.updateRow(row, rowIndex, cb);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
process.nextTick(cb, new Error('Update row not found:', rowIndex));
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
_createTablePage(cb) {
|
|
115
|
+
if(this.pageLock) {
|
|
116
|
+
this.pageLockQueue.push(cb);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
this.pageLock = true;
|
|
120
|
+
const tablePage = new TablePage(this.tablePages.length, this.tableName, this.nextRowIndex, this.pageSize, this.types, this.baseFileName);
|
|
121
|
+
this.tablePages.push(tablePage);
|
|
122
|
+
tablePage.createFile((err) => {
|
|
123
|
+
let queuedCb = this.pageLockQueue.shift();
|
|
124
|
+
while(queuedCb) {
|
|
125
|
+
queuedCb(err);
|
|
126
|
+
queuedCb = this.pageLockQueue.shift();
|
|
127
|
+
}
|
|
128
|
+
this.pageLock = false;
|
|
129
|
+
cb(err);
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
_getTablePageNext() {
|
|
135
|
+
return this.tablePages[this.nextPageIndex];
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
_getPageFromRow(possiblePageIndex, rowIndex) {
|
|
139
|
+
const possiblePage = this.tablePages[possiblePageIndex];
|
|
140
|
+
if(rowIndex >= possiblePage.startRowIndex) {
|
|
141
|
+
if(rowIndex < possiblePage.stopRowIndex) {
|
|
142
|
+
return possiblePage;
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
if(this.tablePages.length < ++possiblePageIndex) {
|
|
146
|
+
return this._getPageFromRow(possiblePageIndex);
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
if(0 >= --possiblePageIndex) {
|
|
155
|
+
return this._getPageFromRow(possiblePageIndex);
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
module.exports = Table;
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const ActorPathGenerated = require('z-abs-corelayer-server/server/path/actor-path-generated');
|
|
5
|
+
const GitSimple = require('simple-git');
|
|
6
|
+
const Fs = require('fs');
|
|
7
|
+
const Path = require('path');
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class DatabaseGit {
|
|
11
|
+
constructor(dbName, isReadOnly, releaseData) {
|
|
12
|
+
this.dbName = dbName;
|
|
13
|
+
this.isReadOnly = isReadOnly;
|
|
14
|
+
this.databasePath = `${ActorPathGenerated.getDatabasesGitFolder()}${Path.sep}${releaseData.releaseStep + (releaseData.organization ? Path.sep + releaseData.organization : '')}${Path.sep}${this.dbName}`;
|
|
15
|
+
this.databaseFileDefinition = `${this.databasePath}${Path.sep}project${Path.sep}server${Path.sep}definition.json`;
|
|
16
|
+
this.databaseFileData = `${this.databasePath}${Path.sep}project${Path.sep}server${Path.sep}data.json`;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
loadDatabase(cb) {
|
|
20
|
+
let pendings = 2;
|
|
21
|
+
let configList = [];
|
|
22
|
+
let configListError = null;
|
|
23
|
+
let statError = null;
|
|
24
|
+
GitSimple('.').listConfig((err, _configList) => {
|
|
25
|
+
configList = _configList
|
|
26
|
+
configListError = err;
|
|
27
|
+
if(0 === --pendings) {
|
|
28
|
+
this._loadDatabase(configListError, configList, statError, (err, definition, data) => {
|
|
29
|
+
cb(err, this.dbName, definition, data);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
Fs.stat(this.databasePath, (err, stat) => {
|
|
34
|
+
statError = err;
|
|
35
|
+
if(0 === --pendings) {
|
|
36
|
+
this._loadDatabase(configListError, configList, statError, (err, definition, data) => {
|
|
37
|
+
cb(err, this.dbName, definition, data);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
_loadDatabase(configListError, configList, statError, cb) {
|
|
44
|
+
if(configListError) {
|
|
45
|
+
ddb.error('Could not get git config.');
|
|
46
|
+
cb(configListError);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
let isHttp = false;
|
|
50
|
+
for(let i = configList.files.length - 1; i >= 0; --i) {
|
|
51
|
+
const remoteOriginUrl = configList.values[configList.files[i]]['remote.origin.url'];
|
|
52
|
+
if(remoteOriginUrl?.startsWith('https://')) {
|
|
53
|
+
isHttp = true;
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if(statError) {
|
|
58
|
+
if('ENOENT' === statError.code) {
|
|
59
|
+
Fs.mkdir(this.databasePath, {recursive: true}, (err) => {
|
|
60
|
+
if(err) {
|
|
61
|
+
cb(err);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
this._cloneDatabase(isHttp, (err) => {
|
|
66
|
+
if(err) {
|
|
67
|
+
cb(err);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
this._readDatabase(cb);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
cb(statError);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
this.fetchDatabase(cb);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
fetchDatabase(cb) {
|
|
85
|
+
GitSimple(this.databasePath).fetch(['--no-tags'], (err, result) => {
|
|
86
|
+
if(err) {
|
|
87
|
+
cb(err);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
if(0 !== result.updated.length || 0 !== result.deleted.length) {
|
|
91
|
+
GitSimple(this.databasePath).reset(this.databasePath, 'hard', 'HEAD', (err, result) => {
|
|
92
|
+
if(err) {
|
|
93
|
+
cb(err);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
GitSimple(this.databasePath).merge(this.databasePath, 'orig', '@{u}', ['--no-verify'], (err, result) => {
|
|
97
|
+
if(err) {
|
|
98
|
+
cb(err);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
this._readDatabase(cb);
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
this._readDatabase(cb);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
_readDatabase(cb) {
|
|
112
|
+
let pendings = 2;
|
|
113
|
+
let definitionJson = '';
|
|
114
|
+
let dataJson = '';
|
|
115
|
+
let hasError = false;
|
|
116
|
+
Fs.readFile(this.databaseFileDefinition, (err, data) => {
|
|
117
|
+
if(!hasError) {
|
|
118
|
+
if(err) {
|
|
119
|
+
hasError = true;
|
|
120
|
+
cb(err, null, null);
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
try {
|
|
124
|
+
definitionJson = JSON.parse(data);
|
|
125
|
+
}
|
|
126
|
+
catch(err) {
|
|
127
|
+
hasError = true;
|
|
128
|
+
cb(err, null, null);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if(0 === --pendings) {
|
|
132
|
+
cb(null, definitionJson, dataJson);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
Fs.readFile(this.databaseFileData, (err, data) => {
|
|
138
|
+
if(!hasError) {
|
|
139
|
+
if(err) {
|
|
140
|
+
hasError = true;
|
|
141
|
+
cb(err, null, null);
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
try {
|
|
145
|
+
dataJson = JSON.parse(data);
|
|
146
|
+
}
|
|
147
|
+
catch(err) {
|
|
148
|
+
hasError = true;
|
|
149
|
+
cb(err, null, null);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
if(0 === --pendings) {
|
|
153
|
+
cb(null, definitionJson, dataJson);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
_cloneDatabase(isHttp, cb) {
|
|
161
|
+
const databaseRepo = isHttp ? `https://gitlab.com/actorjs-database/${this.dbName}.git` : `git@gitlab.com:actorjs-database/${this.dbName}.git`;
|
|
162
|
+
GitSimple(Path.resolve(`${this.databasePath}${Path.sep}..`), ['--no-tags', '--single-branch', '--depth=1']).clone(databaseRepo, (err, result) => {
|
|
163
|
+
cb(err);
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
module.exports = DatabaseGit;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const DatabaseCache = require('../core/database-cache');
|
|
5
|
+
const ActorPathGenerated = require('z-abs-corelayer-server/server/path/actor-path-generated');
|
|
6
|
+
const ChildProcess = require('child_process');
|
|
7
|
+
const Fs = require('fs');
|
|
8
|
+
const Path = require('path');
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class DatabaseNpm {
|
|
12
|
+
constructor(dbName, isReadOnly, releaseData) {
|
|
13
|
+
this.dbName = dbName;
|
|
14
|
+
this.isReadOnly = isReadOnly;
|
|
15
|
+
this.releaseData = releaseData;
|
|
16
|
+
this.databasePath = ActorPathGenerated.getDatabasesNpmFolder();
|
|
17
|
+
this.databaseFile = `${this.databasePath}${Path.sep}node_modules${Path.sep}${this.releaseData.organization}${Path.sep}${this.dbName}${Path.sep}project${Path.sep}server`;
|
|
18
|
+
this.npmInstall = `npm install --prefix ${this.databasePath} ${this.releaseData.organization}/${this.dbName}@latest --no-save --ignore-scripts --package-lock false`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
loadDatabase(cb) {
|
|
22
|
+
ChildProcess.exec(this.npmInstall, (err, stdout, stderr) => {
|
|
23
|
+
if(!err) {
|
|
24
|
+
this._readDatabase((err, definition, data) => {
|
|
25
|
+
cb(err, this.dbName, definition, data);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
cb(err, this.dbName);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
fetchDatabase(cb) {
|
|
35
|
+
this.loadDatabase(cb);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
_readDatabase(cb) {
|
|
39
|
+
let pendings = 2;
|
|
40
|
+
let definitionJson = '';
|
|
41
|
+
let dataJson = '';
|
|
42
|
+
let hasError = false;
|
|
43
|
+
Fs.readFile(`${this.databaseFile}${Path.sep}definition.json`, (err, data) => {
|
|
44
|
+
if(!hasError) {
|
|
45
|
+
if(err) {
|
|
46
|
+
hasError = true;
|
|
47
|
+
cb(err, null, null);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
try {
|
|
51
|
+
definitionJson = JSON.parse(data);
|
|
52
|
+
}
|
|
53
|
+
catch(err) {
|
|
54
|
+
hasError = true;
|
|
55
|
+
cb(err, null, null);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if(0 === --pendings) {
|
|
59
|
+
cb(null, definitionJson, dataJson);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
Fs.readFile(`${this.databaseFile}${Path.sep}data.json`, (err, data) => {
|
|
65
|
+
if(!hasError) {
|
|
66
|
+
if(err) {
|
|
67
|
+
hasError = true;
|
|
68
|
+
cb(err, null, null);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
try {
|
|
72
|
+
dataJson = JSON.parse(data);
|
|
73
|
+
}
|
|
74
|
+
catch(err) {
|
|
75
|
+
hasError = true;
|
|
76
|
+
cb(err, null, null);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if(0 === --pendings) {
|
|
80
|
+
cb(null, definitionJson, dataJson);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
module.exports = DatabaseNpm;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
59471cfa-20c5-4d54-95e3-bfc6c5690aa5;;z-abs-funclayer-database-server;project_folder;.;[actorjs,js]
|
|
2
|
+
5ddf2916-8ed9-4f99-8547-b8a7c3c476fa;59471cfa-20c5-4d54-95e3-bfc6c5690aa5;server;static_folder;./z-abs-funclayer-database-server;[js]
|
|
3
|
+
1659decf-22ce-4d8a-81ce-841f816c1a62;5ddf2916-8ed9-4f99-8547-b8a7c3c476fa;_build;static_folder;./z-abs-funclayer-database-server/server;[bld]
|
|
4
|
+
a00a05dc-1023-4a9a-a640-217cc533b818;1659decf-22ce-4d8a-81ce-841f816c1a62;server-funclayer-database-server.bld;file;./z-abs-funclayer-database-server/server/_build;bld
|
|
5
|
+
aac685aa-4052-430f-b7ca-d9230292a51e;1659decf-22ce-4d8a-81ce-841f816c1a62;z-abs-funclayer-database-server.prj;file;./z-abs-funclayer-database-server/server/_build;prj
|
|
6
|
+
82a6ada3-f19a-4375-be1f-dcb5578b831b;5ddf2916-8ed9-4f99-8547-b8a7c3c476fa;core;folder;./z-abs-funclayer-database-server/server;[js,jsx,html]
|
|
7
|
+
d52efe09-818e-4336-b62c-fd0668b885eb;82a6ada3-f19a-4375-be1f-dcb5578b831b;database-cache.js;file;./z-abs-funclayer-database-server/server/core;js
|
|
8
|
+
29365329-92fb-48df-9bd1-8076a4e48016;82a6ada3-f19a-4375-be1f-dcb5578b831b;database-const.js;file;./z-abs-funclayer-database-server/server/core;js
|
|
9
|
+
eb8be420-8de6-448b-93e9-48b9aa3a4c7c;82a6ada3-f19a-4375-be1f-dcb5578b831b;database-database.js;file;./z-abs-funclayer-database-server/server/core;js
|
|
10
|
+
f818737d-7bf2-4e94-a5ce-9cff6156caea;82a6ada3-f19a-4375-be1f-dcb5578b831b;database-lock.js;file;./z-abs-funclayer-database-server/server/core;js
|
|
11
|
+
ab22af0c-1e0d-412f-b39b-c724fecc0e65;82a6ada3-f19a-4375-be1f-dcb5578b831b;database-table.js;file;./z-abs-funclayer-database-server/server/core;js
|
|
12
|
+
886a61fa-1f47-44c2-a690-9caccf49b67d;5ddf2916-8ed9-4f99-8547-b8a7c3c476fa;database-file;folder;./z-abs-funclayer-database-server/server;[js]
|
|
13
|
+
b2933700-cf12-4aed-9f53-226653ee0c45;886a61fa-1f47-44c2-a690-9caccf49b67d;database-file.js;file;./z-abs-funclayer-database-server/server/database-file;js
|
|
14
|
+
06fde3ae-24f4-4d19-9ab5-2da7dc2ef9c0;886a61fa-1f47-44c2-a690-9caccf49b67d;table-decoder.js;file;./z-abs-funclayer-database-server/server/database-file;js
|
|
15
|
+
93b0cfb4-ff16-4933-885f-f42611e5ac5c;886a61fa-1f47-44c2-a690-9caccf49b67d;table-encoder.js;file;./z-abs-funclayer-database-server/server/database-file;js
|
|
16
|
+
5616f079-ffc9-4a6b-b422-292942229c86;886a61fa-1f47-44c2-a690-9caccf49b67d;table.js;file;./z-abs-funclayer-database-server/server/database-file;js
|
|
17
|
+
b7ac1df6-2267-4f75-b9c3-d15d7a53c12a;886a61fa-1f47-44c2-a690-9caccf49b67d;table-page.js;file;./z-abs-funclayer-database-server/server/database-file;js
|
|
18
|
+
d06ff963-a60d-4e72-bb8c-0a6920f17fa7;5ddf2916-8ed9-4f99-8547-b8a7c3c476fa;database-git;folder;./z-abs-funclayer-database-server/server;[json]
|
|
19
|
+
d2ae58a2-5eaf-4a02-bfdb-0cf45e55c244;d06ff963-a60d-4e72-bb8c-0a6920f17fa7;database-git.js;file;./z-abs-funclayer-database-server/server/database-git;js
|
|
20
|
+
d6f61d9a-1e5d-433d-97aa-5e1b8a04364a;5ddf2916-8ed9-4f99-8547-b8a7c3c476fa;database-npm;folder;./z-abs-funclayer-database-server/server;[json]
|
|
21
|
+
e24e686d-f161-46bf-82b3-79104fef61fc;d6f61d9a-1e5d-433d-97aa-5e1b8a04364a;database-npm.js;file;./z-abs-funclayer-database-server/server/database-npm;js
|