Go LevelDB中重复键上的覆盖/抛出错误

时间:2017-10-01 16:03:16

标签: go leveldb

使用下面的代码时,我希望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与此有关吗?

1 个答案:

答案 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;
    }
}
  

如何控制值何时被覆盖?

如果密钥存在,则无法覆盖其值