How to clear all keys in FoundationDB using Java?

I am building a Clojure wrapper for FoundationDB. I would like to write a function to clear all the values from the database. I googled the question and came across the below answer :

It uses the Python API with ‘’ as start and ‘\xFF’ for the end in the clear_range function. The same works with get_range function also. There is a comment in the question with the equivalent Java code

Java code : https://stackoverflow.com/questions/21417785/how-to-clean-foundationdb/21421524#comment32394788_21421524

When I use the same in Clojure the keys are not getting deleted. They delete only till x and when I have a key named ‘z’ its not getting deleted.

Clojure code :

(defn clear-all
  "Clear all  keys from the database"
  [db]
  (.run db
        (reify
          java.util.function.Function
          (apply [this tr]
            (let [begin (.pack (Tuple/from (to-array [""])))
                  end     (.pack (Tuple/from (to-array ["xFF"])))]
              (.clear tr (Range. begin end)))))))

The printable range is as below :

“Range(”\x02\x00", “\x02xFF\x00”)"]

There are possibly two problems:

  • "xFF" looks like a string of 3 characters x, F and F. You probably want "\u00FF" for a string with a single character (don’t know the string escaping rules for Clojure). This is one example where using strings to represent byte sequences is not always the best idea because 0xFF is not a valid Unicode character and can cause issues in most languages.
  • Tuple/from(...) uses the Tuple Layer encoding, which turns vectors of values into binary. For elements of type string, it adds a 0x02 byte prefix before the string (encoded as UTF8), and a 0x00 suffix.

So to sum up, you are calling clear with the range (in pseudo hexa): { 02 00 }{ 02 'x' 'F' 'F' 00 } which will delete all keys encoded as tuple, starting from the ( "", ) up ( “xFF”, ), leaving all keys(“xFF…”, )...(“zzzzz…”, )` alive.

If you want to erase all the keys in the database (not only the ones encoded as tuples), you need to use the empty byte array as the begin, and a byte array containing a single 255 as the end to get (in pseudo hexa): { }{ FF }. (don’t know the sequence for that in Clojure).

2 Likes

Thanks a lot for the explanation @KrzysFR . I solved it with the byte array solution as you suggested :

(defn clear-all
  "Clear all  keys from the database"
  [db]
  (.run db
        (reify
          java.util.function.Function
          (apply [this tr]
            (let [begin (byte-array [])
                  end     (byte-array [0xFF])]
              (.clear tr (Range. begin end)))))))
2 Likes

FWIW, I have that in Makefile:

fdbcli --exec 'writemode on; clearrange "" \xFF;'

edit: fix command

Just a word of warning, single quotes are not a special character to fdbcli. In other words, this command is clearing every key starting at the string "''" rather than the empty string. To clear everything from the beginning, use double quotes:

fdbcli --exec 'writemode on; clearrange "" \xFF;'

1 Like

I’ll add that sometimes when I need to clear the whole database, I live dangerously and issue a command like:

fdbcli --exec 'writemode on; clearrange \x00 \xff;'

If someone sneaks a value into the blank key, then technically I haven’t cleared it, but this is usually good enough for most purposes (and who would write a key there, right?). It means I don’t have to remember whether single-quotes or double-quotes are not escaped.

I recognize that not everyone lives the high-octane, devil-may-care lifestyle that I do, though.

3 Likes