Skip to content

Commit 10c4a86

Browse files
lokeshj1703RogPodge
authored andcommitted
HDDS-1981: Datanode should sync db when container is moved to CLOSED or QUASI_CLOSED state (apache#1319)
1 parent 37df611 commit 10c4a86

File tree

6 files changed

+59
-4
lines changed

6 files changed

+59
-4
lines changed

hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/LevelDBStore.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,12 @@ public void compactDB() throws IOException {
240240
}
241241
}
242242

243+
@Override
244+
public void flushDB(boolean sync) {
245+
// TODO: Implement flush for level db
246+
// do nothing
247+
}
248+
243249
@Override
244250
public void writeBatch(BatchOperation operation) throws IOException {
245251
List<BatchOperation.SingleOperation> operations =

hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/MetadataStore.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,12 @@ List<Map.Entry<byte[], byte[]>> getSequentialRangeKVs(byte[] startKey,
131131
*/
132132
void compactDB() throws IOException;
133133

134+
/**
135+
* Flush the outstanding I/O operations of the DB.
136+
* @param sync if true will sync the outstanding I/Os to the disk.
137+
*/
138+
void flushDB(boolean sync) throws IOException;
139+
134140
/**
135141
* Destroy the content of the specified database,
136142
* a destroyed database will not be able to load again.

hadoop-hdds/common/src/main/java/org/apache/hadoop/utils/RocksDBStore.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,19 @@ public void compactDB() throws IOException {
279279
}
280280
}
281281

282+
@Override
283+
public void flushDB(boolean sync) throws IOException {
284+
if (db != null) {
285+
try {
286+
// for RocksDB it is sufficient to flush the WAL as entire db can
287+
// be reconstructed using it.
288+
db.flushWal(sync);
289+
} catch (RocksDBException e) {
290+
throw toIOException("Failed to flush db", e);
291+
}
292+
}
293+
}
294+
282295
private void deleteQuietly(File fileOrDir) {
283296
if (fileOrDir != null && fileOrDir.exists()) {
284297
try {

hadoop-hdds/common/src/main/proto/DatanodeContainerProtocol.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ enum Result {
144144
CONTAINER_NOT_OPEN = 39;
145145
CONTAINER_MISSING = 40;
146146
BLOCK_TOKEN_VERIFICATION_FAILED = 41;
147+
ERROR_IN_DB_SYNC = 42;
147148
}
148149

149150
/**

hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueContainer.java

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@
6868
.Result.DISK_OUT_OF_SPACE;
6969
import static org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos
7070
.Result.ERROR_IN_COMPACT_DB;
71+
import static org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos
72+
.Result.ERROR_IN_DB_SYNC;
7173
import static org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos
7274
.Result.INVALID_CONTAINER_STATE;
7375
import static org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos
@@ -298,8 +300,14 @@ public void markContainerUnhealthy() throws StorageContainerException {
298300

299301
@Override
300302
public void quasiClose() throws StorageContainerException {
303+
// The DB must be synced during close operation
304+
flushAndSyncDB();
305+
301306
writeLock();
302307
try {
308+
// Second sync should be a very light operation as sync has already
309+
// been done outside the lock.
310+
flushAndSyncDB();
303311
updateContainerData(containerData::quasiCloseContainer);
304312
} finally {
305313
writeUnlock();
@@ -308,16 +316,18 @@ public void quasiClose() throws StorageContainerException {
308316

309317
@Override
310318
public void close() throws StorageContainerException {
319+
// The DB must be synced during close operation
320+
flushAndSyncDB();
321+
311322
writeLock();
312323
try {
324+
// Second sync should be a very light operation as sync has already
325+
// been done outside the lock.
326+
flushAndSyncDB();
313327
updateContainerData(containerData::closeContainer);
314328
} finally {
315329
writeUnlock();
316330
}
317-
318-
// It is ok if this operation takes a bit of time.
319-
// Close container is not expected to be instantaneous.
320-
compactDB();
321331
}
322332

323333
/**
@@ -365,6 +375,22 @@ void compactDB() throws StorageContainerException {
365375
}
366376
}
367377

378+
private void flushAndSyncDB() throws StorageContainerException {
379+
try {
380+
try (ReferenceCountedDB db = BlockUtils.getDB(containerData, config)) {
381+
db.getStore().flushDB(true);
382+
LOG.info("Container {} is synced with bcsId {}.",
383+
containerData.getContainerID(),
384+
containerData.getBlockCommitSequenceId());
385+
}
386+
} catch (StorageContainerException ex) {
387+
throw ex;
388+
} catch (IOException ex) {
389+
LOG.error("Error in DB sync while closing container", ex);
390+
throw new StorageContainerException(ex, ERROR_IN_DB_SYNC);
391+
}
392+
}
393+
368394
@Override
369395
public KeyValueContainerData getContainerData() {
370396
return containerData;

hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestKeyValueContainerMarkUnhealthy.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,9 @@ public void testMarkClosedContainerAsUnhealthy() throws IOException {
155155
*/
156156
@Test
157157
public void testMarkQuasiClosedContainerAsUnhealthy() throws IOException {
158+
// We need to create the container so the sync-on-quasi-close operation
159+
// does not NPE.
160+
keyValueContainer.create(volumeSet, volumeChoosingPolicy, scmId);
158161
keyValueContainer.quasiClose();
159162
keyValueContainer.markContainerUnhealthy();
160163
assertThat(keyValueContainerData.getState(), is(UNHEALTHY));

0 commit comments

Comments
 (0)