Key-Value Store on a Block Device
Problem statement
Build a key-value store on top of a block device. The device has numBlocks blocks numbered 0 to numBlocks - 1, and each block holds at most blockSize characters.
Values live on the device. To store a value, cut it into chunks of blockSize characters (the last chunk may be shorter) and write each chunk to its own block. A value of length L therefore uses ceil(L / blockSize) blocks. The chunks go into the lowest-numbered free blocks: the first chunk into the lowest one, the second chunk into the next lowest, and so on. The blocks a value uses do not have to be next to each other.
Process operations in order. Each operation adds one string to the answer:
["put", key, value]: storevalueunderkey, replacing any old value. Ifkeyalready has a value, its blocks count as available, because they are released first. If the free blocks plus those released blocks are fewer than the blocks the new value needs, nothing changes and the answer is"FULL"; an old value stays in place. Otherwise, release the old blocks, write the new chunks as described above, and answer"OK".["get", key]: answer the value stored underkey, read back from its blocks, or"NOT_FOUND".["delete", key]: release the blocks ofkeyand answer"OK", or answer"NOT_FOUND"if the key has no value.["read", block]: answer the chunk stored in block numberblock. A free block reads as the empty string.
Return the answers in order.
Function
blockKeyValueStore(blockSize: int, numBlocks: int, operations: String[][]) → String[]Examples
Example 1
blockSize = 4numBlocks = 3operations = [["put","cat","meowmeow"],["read","0"],["read","1"],["get","cat"],["put","dog","woof"],["put","cow","moo"],["delete","cat"],["put","cow","moo"],["read","0"],["get","cow"]]return = ["OK","meow","meow","meowmeow","OK","FULL","OK","OK","moo","moo"]meowmeowhas 8 characters, so it fills blocks0and1withmeoweach, andgetreads them back asmeowmeow.wooftakes the last free block,2. The device is now full, so puttingmooanswersFULL.- Deleting
catfrees blocks0and1. The second put ofmoogoes to block0, the lowest free block.
Example 2
blockSize = 3numBlocks = 4operations = [["put","a","abcdefg"],["put","b","xy"],["put","a","zz"],["read","0"],["read","1"],["read","2"],["get","b"],["put","a","1234567890"]]return = ["OK","OK","OK","zz","","","xy","FULL"]abcdefguses blocks0,1and2(abc,def,g), andxyuses block3.- Replacing
awithzzreleases its three blocks first, sozzlands in block0and blocks1and2read as empty strings. 1234567890needs 4 blocks, but only blocks1and2are free andacan release only block0. That is 3 blocks, so the put answersFULLandakeepszz.
Example 3
blockSize = 5numBlocks = 2operations = [["get","k"],["delete","k"],["read","1"],["put","k","hello"],["delete","k"],["delete","k"],["read","0"]]return = ["NOT_FOUND","NOT_FOUND","","OK","OK","NOT_FOUND",""]Getting or deleting a missing key answers NOT_FOUND, and unused block 1 reads as an empty string. After hello is stored and deleted, a second delete answers NOT_FOUND and block 0 is empty again.
Constraints
1 <= blockSize <= 10001 <= numBlocks <= 10001 <= operations.length <= 500- Each
operations[i]is["put", key, value],["get", key],["delete", key], or["read", block]. - Each
keyhas1to10lowercase letters. - Each
valuehas1to1000characters, all lowercase letters or digits. - Each
blockis a decimal number without leading zeros, and0 <= block < numBlocks.