Skip to content

Commit 6ec3841

Browse files
jeniawhiteguymguym
authored andcommitted
Builder chunk batches locking (mainly to fix nodes_monitor working on same chunks) (#2500)
* Builder chunk batches locking from nodes_monitor * Altering logic a bit and fixing errors * Addition of tests * Fixing when there is no system
1 parent 9feb491 commit 6ec3841

File tree

7 files changed

+343
-62
lines changed

7 files changed

+343
-62
lines changed

src/server/bg_services/scrubber.js

Lines changed: 38 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ const dbg = require('../../util/debug_module')(__filename);
55
const config = require('../../../config');
66
const md_store = require('../object_services/md_store');
77
const map_builder = require('../object_services/map_builder');
8+
const system_store = require('../system_services/system_store').get_instance();
9+
const system_server_utils = require('../utils/system_server_utils');
10+
811

912
/**
1013
*
@@ -16,33 +19,42 @@ const map_builder = require('../object_services/map_builder');
1619
*
1720
*/
1821
function background_worker() {
22+
if (!system_store.is_finished_initial_load) {
23+
dbg.log0('System did not finish initial load');
24+
return;
25+
}
26+
27+
const system = system_store.data.systems[0];
28+
if (!system || system_server_utils.system_in_maintenance(system._id)) return;
29+
1930
var self = this;
2031
return P.fcall(function() {
2132
var now = Date.now();
2233
var query = {
2334
$and: [{
24-
$or: [{
25-
last_build: null
26-
}, {
27-
last_build: {
28-
$lt: new Date(now - config.REBUILD_LAST_BUILD_BACKOFF)
29-
}
30-
}]
31-
}, {
32-
$or: [{
33-
building: null
35+
$or: [{
36+
last_build: null
37+
}, {
38+
last_build: {
39+
$lt: new Date(now - config.REBUILD_LAST_BUILD_BACKOFF)
40+
}
41+
}]
3442
}, {
35-
building: {
36-
$lt: new Date(now - config.REBUILD_BUILDING_MODE_BACKOFF)
43+
$or: [{
44+
building: null
45+
}, {
46+
building: {
47+
$lt: new Date(now - config.REBUILD_BUILDING_MODE_BACKOFF)
48+
}
49+
}]
50+
},
51+
//ignore old chunks without buckets
52+
{
53+
bucket: {
54+
$exists: true
3755
}
38-
}]
39-
},
40-
//ignore old chunks without buckets
41-
{
42-
bucket: {
43-
$exists: true
4456
}
45-
}]
57+
]
4658
};
4759
if (self.last_chunk_id) {
4860
query._id = {
@@ -54,29 +66,24 @@ function background_worker() {
5466
query.deleted = null;
5567

5668
return P.resolve(md_store.DataChunk.find(query)
69+
.select('_id')
5770
.limit(config.REBUILD_BATCH_SIZE)
5871
.sort('-_id')
5972
.lean()
6073
.exec());
61-
// return P.resolve(md_store.DataChunk.collection.find(query, {
62-
// limit: config.REBUILD_BATCH_SIZE,
63-
// sort: {
64-
// _id: -1
65-
// }
66-
// }).toArray());
6774
})
68-
.then(function(chunks) {
75+
.then(function(chunk_ids) {
6976

7077
// update the last_chunk_id for next time
71-
if (chunks.length === config.REBUILD_BATCH_SIZE) {
72-
self.last_chunk_id = chunks[0]._id;
78+
if (chunk_ids.length === config.REBUILD_BATCH_SIZE) {
79+
self.last_chunk_id = chunk_ids[0];
7380
} else {
7481
self.last_chunk_id = undefined;
7582
}
7683

77-
if (chunks.length) {
78-
dbg.log0('SCRUBBER:', 'WORKING ON', chunks.length, 'CHUNKS');
79-
let builder = new map_builder.MapBuilder(chunks);
84+
if (chunk_ids.length) {
85+
dbg.log0('SCRUBBER:', 'WORKING ON', chunk_ids.length, 'CHUNKS');
86+
let builder = new map_builder.MapBuilder(chunk_ids);
8087
return builder.run()
8188
.catch(function(err) {
8289
dbg.error('SCRUBBER:', 'BUILD ERROR', err, err.stack);

src/server/node_services/nodes_monitor.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1556,7 +1556,7 @@ class NodesMonitor extends EventEmitter {
15561556
// we update the stage marker even if failed to advance the scan
15571557
act.stage.marker = res.marker;
15581558
blocks_size = res.blocks_size;
1559-
const builder = new MapBuilder(res.chunks);
1559+
const builder = new MapBuilder(res.chunk_ids);
15601560
return builder.run();
15611561
})
15621562
.then(() => {

src/server/object_services/map_builder.js

Lines changed: 47 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ const map_deleter = require('./map_deleter');
1313
const mongo_utils = require('../../util/mongo_utils');
1414
const system_store = require('../system_services/system_store').get_instance();
1515
const node_allocator = require('../node_services/node_allocator');
16-
const system_server_utils = require('../utils/system_server_utils');
17-
// const promise_utils = require('../../util/promise_utils');
16+
const KeysLock = require('../../util/keys_lock');
1817

1918

2019
const replicate_block_sem = new Semaphore(config.IO_REPLICATE_CONCURRENCY);
20+
const builder_lock = new KeysLock();
2121

2222

2323
/**
@@ -31,35 +31,54 @@ const replicate_block_sem = new Semaphore(config.IO_REPLICATE_CONCURRENCY);
3131
*/
3232
class MapBuilder {
3333

34-
constructor(chunks) {
35-
this.chunks = chunks;
36-
this.system_id = chunks[0] && chunks[0].system;
34+
constructor(chunk_ids) {
35+
this.chunk_ids = chunk_ids;
3736
}
3837

3938
run() {
40-
dbg.log1('MapBuilder.run:', 'batch start', this.chunks.length, 'chunks');
41-
if (!this.chunks.length) return;
42-
if (system_server_utils.system_in_maintenance(this.system_id)) return;
43-
return P.resolve()
44-
.then(() => P.join(
45-
system_store.refresh(),
46-
md_store.load_blocks_for_chunks(this.chunks),
47-
md_store.load_parts_objects_for_chunks(this.chunks),
48-
this.mark_building()
49-
))
50-
.then(() => this.refresh_alloc())
51-
.then(() => this.analyze_chunks())
52-
// .then(() => this.refresh_alloc())
53-
.then(() => this.allocate_blocks())
54-
.then(() => this.replicate_blocks())
55-
.then(() => this.update_db())
56-
.then(() => {
57-
// return error from the promise if any replication failed,
58-
// so that caller will know the build isn't really complete,
59-
// although it might partially succeeded
60-
if (this.had_errors) {
61-
throw new Error('MapBuilder had errors');
62-
}
39+
dbg.log1('MapBuilder.run:', 'batch start', this.chunk_ids.length, 'chunks');
40+
if (!this.chunk_ids.length) return;
41+
42+
return builder_lock.surround_keys(_.map(this.chunk_ids, String), () => {
43+
return P.resolve(this.reload_chunks(this.chunk_ids))
44+
.then(() => P.join(
45+
system_store.refresh(),
46+
md_store.load_blocks_for_chunks(this.chunks),
47+
md_store.load_parts_objects_for_chunks(this.chunks),
48+
this.mark_building()
49+
))
50+
.then(() => this.refresh_alloc())
51+
.then(() => this.analyze_chunks())
52+
.then(() => this.allocate_blocks())
53+
.then(() => this.replicate_blocks())
54+
.then(() => this.update_db())
55+
.then(() => {
56+
// return error from the promise if any replication failed,
57+
// so that caller will know the build isn't really complete,
58+
// although it might partially succeeded
59+
if (this.had_errors) {
60+
throw new Error('MapBuilder had errors');
61+
}
62+
});
63+
});
64+
}
65+
66+
67+
// In order to get the most relevant data regarding the chunks
68+
// Note that there is always a possibility that the chunks will cease to exist
69+
reload_chunks(chunk_ids) {
70+
var query = {
71+
_id: {
72+
$in: chunk_ids
73+
},
74+
deleted: null
75+
};
76+
77+
return P.resolve(md_store.DataChunk.find(query)
78+
.lean()
79+
.exec())
80+
.then(chunks => {
81+
this.chunks = chunks;
6382
});
6483
}
6584

src/server/object_services/md_store.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,9 +186,13 @@ function iterate_node_chunks(system_id, node_id, marker, limit) {
186186
_id: {
187187
$in: mongo_utils.uniq_ids(blocks, 'chunk')
188188
}
189+
}, {
190+
fields: {
191+
_id: 1,
192+
},
189193
}).toArray())
190-
.then(chunks => ({
191-
chunks: chunks,
194+
.then(chunk_ids => ({
195+
chunk_ids: chunk_ids,
192196
marker: blocks.length ? blocks[blocks.length - 1]._id : null,
193197
blocks_size: _.sumBy(blocks, 'size'),
194198
}));

src/test/unit_tests/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ require('./test_s3_list_objects');
1919
// require('./test_debug_module');
2020
require('./test_job_queue');
2121
require('./test_linked_list');
22+
require('./test_keys_lock');
2223
require('./test_lru');
2324
require('./test_mongoose_logger');
2425
require('./test_prefetch');

0 commit comments

Comments
 (0)