keith-turner commented on code in PR #2967:
URL: https://github.com/apache/accumulo/pull/2967#discussion_r992772102


##########
core/src/main/java/org/apache/accumulo/core/client/admin/InstanceOperations.java:
##########
@@ -57,19 +56,86 @@ void setProperty(final String property, final String value)
    * property overrides in ZooKeeper. Only properties which can be stored in 
ZooKeeper will be
    * accepted.
    *
+   * <p>
+   * Accumulo has multiple layers of properties that for many APIs and SPIs 
are presented as a
+   * single merged view. This API does not offer that merged view, it only 
offers the properties set
+   * at the system layer to the mapMutator.
+   * </p>
+   *
+   * <p>
+   * This new API offers two distinct advantages over the older {@link 
#setProperty(String, String)}
+   * API. The older API offered the ability to unconditionally set a single 
property. This new API
+   * offers the following.
+   * </p>
+   *
+   * <ul>
+   * <li>Ability to unconditionally set multiple properties atomically. If 
five properties are
+   * mutated by this API, then eventually all of the servers will see those 
changes all at once.
+   * This is really important for configuring something like a scan iterator 
that requires setting
+   * multiple properties.</li>
+   * <li>Ability to conditionally set multiple properties atomically. With 
this new API a snapshot
+   * of the current instance configuration is passed in to the mapMutator. 
Code can inspect the
+   * current config and decide what if any changes it would like to make. If 
the config changes
+   * while mapMutator is doing inspection and modification, then those actions 
will be ignored and
+   * it will be called again with the latest snapshot of the config.</li>
+   * </ul>
+   *
+   * <p>
+   * Below is an example of using this API to conditionally set some instance 
properties. If while
+   * trying to set the compaction planner properties another process modifies 
the manager balancer
+   * properties, then it would automatically retry and call the lambda again 
with the latest
+   * snapshot of instance properties.
+   * </p>
+   *
+   * <pre>
+   *         {@code
+   *             AccumuloClient client = getClient();
+   *             Map<String,String> acceptedProps = 
client.instanceOperations().modifyProperties(currProps -> {
+   *               var planner = 
currProps.get("tserver.compaction.major.service.default.planner");
+   *               //This code will only change the compaction planner if its 
currently set to default settings.
+   *               //The endsWith() function was used to make the example 
short, would be better to use equals().
+   *               if(planner != null && 
planner.endsWith("DefaultCompactionPlanner") {
+   *                 // tservers will eventually see these compaction planner 
changes and when they do they will see all of the changes at once
+   *                 currProps.keySet().removeIf(
+   *                    prop -> 
prop.startsWith("tserver.compaction.major.service.default.planner.opts."));
+   *                 
currProps.put("tserver.compaction.major.service.default.planner","MyPlannerClassName");
+   *                 
currProps.put("tserver.compaction.major.service.default.planner.opts.myOpt1","val1");
+   *                 
currProps.put("tserver.compaction.major.service.default.planner.opts.myOpt2","val2");
+   *                }
+   *             });
+   *
+   *             // Since three properties were set may want to check for the 
values of all
+   *             // three, just checking one in this example to keep it short.
+   *             
if("MyPlannerClassName".equals(acceptedProps.get("tserver.compaction.major.service.default.planner"))){
+   *                // the compaction planner change was accepted or already 
existed, so take action for that outcome
+   *             } else {
+   *                // the compaction planner change was not done, so take 
action for that outcome
+   *             }
+   *           }
+   *         }
+   * </pre>
+   *
+   * @param mapMutator
+   *          This consumer should modify the passed snapshot of instance 
properties to contain the
+   *          desired keys and values. It should be safe for Accumulo to call 
this consumer multiple
+   *          times, this may be done automatically when certain retryable 
errors happen. The
+   *          consumer should probably avoid accessing the Accumulo client as 
that could lead to
+   *          undefined behavior.
+   *
    * @throws AccumuloException
    *           if a general error occurs
    * @throws AccumuloSecurityException
    *           if the user does not have permission
    * @throws IllegalArgumentException
    *           if the Consumer alters the map by adding properties that cannot 
be stored in
    *           ZooKeeper
-   * @throws ConcurrentModificationException
-   *           without altering the stored properties if the server reports 
that the properties have
-   *           been changed by another process
+   *
+   * @return The map that became Accumulo's new properties for this table. 
This map is immutable and
+   *         contains the snapshot passed to mapMutator and the changes made 
by mapMutator.
+   * @since 2.1.0
    */
-  void modifyProperties(Consumer<Map<String,String>> mapMutator) throws 
AccumuloException,
-      AccumuloSecurityException, IllegalArgumentException, 
ConcurrentModificationException;
+  Map<String,String> modifyProperties(Consumer<Map<String,String>> mapMutator)

Review Comment:
   I think i like `modify` a bit better because it conveys something that is 
happening in the distributed system where `compute` feels a bit more centered 
on what is happening in the client.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to