使用下面的代码时,我希望db中只有一个条目。 我使用Go的syndtr/goleveldb LevelDB实现。
for count := 0; count < 5; count++ {
err := db.Put([]byte("key"), []byte("value"))
if err != nil {
t.Error(err)
}
}
相反,hexdump显示有5个条目:
00000000 a8 ef d2 d4 17 00 01 01 00 00 00 00 00 00 00 01 |................|
00000010 00 00 00 01 03 6b 65 79 05 76 61 6c 75 65 10 23 |.....key.value.#|
00000020 44 b5 17 00 01 02 00 00 00 00 00 00 00 01 00 00 |D...............|
00000030 00 01 03 6b 65 79 05 76 61 6c 75 65 77 be 34 95 |...key.valuew.4.|
00000040 17 00 01 03 00 00 00 00 00 00 00 01 00 00 00 01 |................|
00000050 03 6b 65 79 05 76 61 6c 75 65 08 35 86 60 17 00 |.key.value.5.`..|
00000060 01 04 00 00 00 00 00 00 00 01 00 00 00 01 03 6b |...............k|
00000070 65 79 05 76 61 6c 75 65 6f 8c f6 00 17 00 01 05 |ey.valueo.......|
00000080 00 00 00 00 00 00 00 01 00 00 00 01 03 6b 65 79 |.............key|
00000090 05 76 61 6c 75 65 |.value|
00000096
根据我的理解LevelDB
默认情况下应覆盖任何重复的密钥或至少抛出错误。
如何控制值被覆盖的时间或我如何收到错误(除了每次db.Has(key)
时都检查db.Put(key)
?
compaction
与此有关吗?
答案 0 :(得分:2)
LevelDB是log-structured merge-tree并且具有事务日志(您使用hexdump检查的日志)。使用此代码,您可以验证密钥只有一个值:
public static void main(String[] args) {
char[][] board = {{'.', 'o', '.', '.'},
{'o', 'o', 'o', 'o'},
{'.', '.', 'o', '.'}};
CoinMoveSolver solver = new CoinMoveSolver(board);
System.out.println(solver.getMinimumMove(3));
}
static class CoinMoveSolver {
int[][] directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
char[][] board;
int[] rowCount;
int[] colCount;
int height;
int width;
int totalCoins;
public CoinMoveSolver(char[][] board) {
// Set up the board
this.board = board;
this.height = board.length;
this.width = board[0].length;
// Count how many coins we have per row,
// per column and the total no. of coins
this.rowCount = new int[height];
this.colCount = new int[width];
for (int i = 0 ; i < board.length ; i++) {
for (int j = 0 ; j < board[i].length ; j++) {
if (board[i][j] == 'o') {
this.rowCount[i]++;
this.colCount[j]++;
totalCoins++;
}
}
}
}
// Returns the number of coins if the top left
// corner of the board is at rowIdx and colIdx
private int countCoins(int rowIdx, int colIdx) {
int sumRow = 0;
for (int i = rowIdx ; i < rowIdx + height ; i++) {
if (i >= 0 && i < height)
sumRow += rowCount[i];
}
int sumCol = 0;
for (int j = colIdx ; j < colIdx + width ; j++) {
if (j >= 0 && j < width)
sumCol += colCount[j];
}
return Math.min(sumRow, sumCol);
}
public int getMinimumMove(int targetCoinCount) {
if (totalCoins < targetCoinCount)
return -1;
else if (totalCoins == targetCoinCount)
return 0;
else
return this.recursiveSolve(0, 0, -1, 0, targetCoinCount);
}
private boolean isOppositeDirection(int prevDirectionIdx, int curDirectionIdx) {
if (prevDirectionIdx < 0)
return false;
else {
int[] prevDirection = directions[prevDirectionIdx];
int[] curDirection = directions[curDirectionIdx];
return prevDirection[0] + curDirection[0] + prevDirection[1] + curDirection[1] == 0;
}
}
private int recursiveSolve(int curRowIdx, int curColIdx, int prevDirectionIdx, int moveCount, int targetCoinCount) {
int minMove = -1;
for (int i = 0 ; i < directions.length ; i++) {
if (!this.isOppositeDirection(prevDirectionIdx, i)) {
int[] direction = directions[i];
int nextRowIdx = curRowIdx + direction[0];
int nextColIdx = curColIdx + direction[1];
int coinCount = this.countCoins(nextRowIdx, nextColIdx);
// If this move reduces too many coins, abandon
if (coinCount < targetCoinCount)
continue;
// If this move can get us the exact number of
// coins we're looking for, break the loop
else if (coinCount == targetCoinCount) {
minMove = moveCount + 1;
break;
} else {
// Look for the potential answer by moving the board in 1 of the 4 directions
int potentialMin = this.recursiveSolve(nextRowIdx, nextColIdx, i, moveCount + 1, targetCoinCount);
if (potentialMin > 0 && (minMove < 0 || potentialMin < minMove))
minMove = potentialMin;
}
}
}
// If minMove is still < 0, that means
// there's no solution
if (minMove < 0)
return -1;
else
return minMove;
}
}
如何控制值何时被覆盖?
如果密钥存在,则无法覆盖其值