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


##########
server/manager/src/main/java/org/apache/accumulo/manager/tableOps/goal/SetHostingGoal.java:
##########
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.accumulo.manager.tableOps.goal;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.accumulo.core.client.AccumuloException;
+import org.apache.accumulo.core.client.admin.TabletHostingGoal;
+import org.apache.accumulo.core.clientImpl.ClientContext;
+import org.apache.accumulo.core.clientImpl.thrift.TableOperation;
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.NamespaceId;
+import org.apache.accumulo.core.data.PartialKey;
+import org.apache.accumulo.core.data.Range;
+import org.apache.accumulo.core.data.TableId;
+import org.apache.accumulo.core.dataImpl.KeyExtent;
+import org.apache.accumulo.core.dataImpl.thrift.TRange;
+import org.apache.accumulo.core.fate.Repo;
+import org.apache.accumulo.core.metadata.schema.Ample.TabletsMutator;
+import org.apache.accumulo.core.metadata.schema.TabletMetadata;
+import org.apache.accumulo.core.metadata.schema.TabletMetadata.Location;
+import org.apache.accumulo.core.metadata.schema.TabletsMetadata;
+import org.apache.accumulo.manager.Manager;
+import org.apache.accumulo.manager.tableOps.ManagerRepo;
+import org.apache.accumulo.manager.tableOps.Utils;
+import org.apache.hadoop.io.Text;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SetHostingGoal extends ManagerRepo {
+
+  private static final long serialVersionUID = 1L;
+  private static final Logger LOG = 
LoggerFactory.getLogger(SetHostingGoal.class);
+
+  private final TableId tableId;
+  private final NamespaceId namespaceId;
+  private final TRange range;
+  private final TabletHostingGoal goal;
+
+  public SetHostingGoal(TableId tableId, NamespaceId namespaceId, TRange range,
+      TabletHostingGoal goal) {
+    this.tableId = tableId;
+    this.namespaceId = namespaceId;
+    this.range = range;
+    this.goal = goal;
+  }
+
+  @Override
+  public long isReady(long tid, Manager manager) throws Exception {
+    return Utils.reserveNamespace(manager, namespaceId, tid, false, true,
+        TableOperation.SET_HOSTING_GOAL)
+        + Utils.reserveTable(manager, tableId, tid, true, true, 
TableOperation.SET_HOSTING_GOAL);
+  }
+
+  @Override
+  public Repo<Manager> call(long tid, Manager manager) throws Exception {
+    final Range r = new Range(range);
+    final List<KeyExtent> extents = findExtentsForRange(manager.getContext(), 
tableId, r);
+    LOG.debug("Setting tablet hosting goal to {} requested for: {} ", goal, 
extents);
+    try (TabletsMutator mutator = 
manager.getContext().getAmple().mutateTablets()) {
+      extents.forEach(e -> 
mutator.mutateTablet(e).setHostingGoal(goal).mutate());

Review Comment:
   
   Thinking through how this might be handled using only conditional mutations 
(and no table locks), something like the following may work using multiple fate 
steps.  The algorithm tries to reserve tablets before making the changes 
inorder to detect concurrent collisions with other FATE transactions trying to 
set the goal on the same range.
   
   The following is the first fate step.
   
   ```
   while(true) {
      foreach tablet in range {
           Do a conditional mutation settting coulumn changingGoal=<Fate tx id> 
IF column changingGoal is absent
      }  
   
      if conditional mutations failed {
         if there are other fate tx also changingGoal
            if the other fate tx id is lower then ours then delete our 
changingGoal columns and wait for the other fate tx to go away
            if the other fate tx id is higher than our then wait for them to go 
away
      } else {
        break;
      }
   }
   ```
   
   The second fate step would set the goals.  When we get to this step, all of 
the tablets are reserved for changing the goal so can go ahead and do it.
   
   ```
   while(true) {
      
      foreach tablet {
           Do a conditional mutation settting goal <Fate tx id> IF changing 
goal is set to my transaction id.
      }
     
      if conditional mutations failed {
        if changingGoal column is not set, then throw an error this is 
unexpected.
      } else {
         break;
      } 
   }
   ```
   
   The third fate step would delete the changingGoal columns in the range.



-- 
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