docs: public Deferred<Boolean> storeTree(final TSDB tsdb, final boolean overwrite) {
      if (tree_id < 1 || tree_id > 65535) {
        throw new IllegalArgumentException("Invalid Tree ID");
      }
      
      // if there aren't any changes, save time and bandwidth by not writing to
      // storage
      boolean has_changes = false;
      for (Map.Entry<String, Boolean> entry : changed.entrySet()) {
        if (entry.getValue()) {
          has_changes = true;
          break;
        }
      }
      if (!has_changes) {
        LOG.debug(this + " does not have changes, skipping sync to storage");
        throw new IllegalStateException("No changes detected in the tree");
      }
  
      /**
       * Callback executed after loading a tree from storage so that we can
       * synchronize changes to the meta data and write them back to storage.
       */
      final class StoreTreeCB implements Callback<Deferred<Boolean>, Tree> {
        
        final private Tree local_tree;
        
        public StoreTreeCB(final Tree local_tree) {
          this.local_tree = local_tree;
        }
        
        /**
         * Synchronizes the stored tree object (if found) with the local tree 
         * and issues a CAS call to write the update to storage.
         * @return True if the CAS was successful, false if something changed 
         * in flight
         */
        @Override
        public Deferred<Boolean> call(final Tree fetched_tree) throws Exception {
          
          Tree stored_tree = fetched_tree;
          final byte[] original_tree = stored_tree == null ? new byte[0] : 
            stored_tree.toStorageJson();
  
          // now copy changes
          if (stored_tree == null) {
            stored_tree = local_tree;
          } else {
            stored_tree.copyChanges(local_tree, overwrite);
          }
          
          // reset the change map so we don't keep writing
          initializeChangedMap();
          
          final PutRequest put = new PutRequest(tsdb.treeTable(), 
              Tree.idToBytes(tree_id), TREE_FAMILY, TREE_QUALIFIER, 
              stored_tree.toStorageJson());
          return tsdb.getClient().compareAndSet(put, original_tree);
        }
      }
      
      // initiate the sync by attempting to fetch an existing tree from storage
      return fetchTree(tsdb, tree_id).addCallbackDeferring(new StoreTreeCB(this));
    }