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


##########
server/manager/src/main/java/org/apache/accumulo/manager/upgrade/UpgradeProgressTracker.java:
##########
@@ -0,0 +1,127 @@
+/*
+ * 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.upgrade;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.accumulo.core.util.LazySingletons.GSON;
+
+import java.util.Objects;
+
+import org.apache.accumulo.core.Constants;
+import org.apache.accumulo.core.fate.zookeeper.ZooReaderWriter;
+import org.apache.accumulo.core.fate.zookeeper.ZooUtil.NodeExistsPolicy;
+import org.apache.accumulo.core.fate.zookeeper.ZooUtil.NodeMissingPolicy;
+import org.apache.accumulo.server.AccumuloDataVersion;
+import org.apache.accumulo.server.ServerContext;
+import org.apache.zookeeper.KeeperException;
+
+import com.google.common.base.Preconditions;
+
+public class UpgradeProgressTracker {
+
+  public static class ComponentVersions {
+    private int zooKeeperVersion;
+    private int rootVersion;
+    private int metadataVersion;
+
+    int getZooKeeperVersion() {
+      return zooKeeperVersion;
+    }
+
+    synchronized void updateZooKeeperVersion(ServerContext context, int 
newVersion)
+        throws KeeperException, InterruptedException {
+      Objects.requireNonNull(context, "ServerContext must be supplied");
+      Preconditions.checkArgument(newVersion > zooKeeperVersion,
+          "new version must be greater than current version");
+      zooKeeperVersion = newVersion;
+      put(context, this);
+    }
+
+    int getRootVersion() {
+      return rootVersion;
+    }
+
+    synchronized void updateRootVersion(ServerContext context, int newVersion)
+        throws KeeperException, InterruptedException {
+      Objects.requireNonNull(context, "ServerContext must be supplied");
+      Preconditions.checkArgument(newVersion > rootVersion,
+          "new version must be greater than current version");
+      rootVersion = newVersion;
+      put(context, this);
+    }
+
+    int getMetadataVersion() {
+      return metadataVersion;
+    }
+
+    synchronized void updateMetadataVersion(ServerContext context, int 
newVersion)
+        throws KeeperException, InterruptedException {
+      Objects.requireNonNull(context, "ServerContext must be supplied");
+      Preconditions.checkArgument(newVersion > metadataVersion,
+          "new version must be greater than current version");
+      metadataVersion = newVersion;
+      put(context, this);
+    }
+  }
+
+  private static String getZPath(ServerContext context) {
+    return context.getZooKeeperRoot() + Constants.ZUPGRADE_STATUS;
+  }
+
+  private static synchronized void put(ServerContext context, 
ComponentVersions cv)
+      throws KeeperException, InterruptedException {
+    final String zpath = getZPath(context);
+    final ZooReaderWriter zrw = context.getZooSession().asReaderWriter();
+    zrw.sync(zpath);
+    if (!zrw.exists(zpath)) {
+      zrw.mkdirs(zpath);
+    }
+    zrw.putPersistentData(zpath, GSON.get().toJson(cv).getBytes(UTF_8), 
NodeExistsPolicy.OVERWRITE);
+  }
+
+  static synchronized ComponentVersions get(ServerContext context)
+      throws KeeperException, InterruptedException {
+    final String zpath = getZPath(context);
+    final int currentVersion = AccumuloDataVersion.getCurrentVersion(context);
+    final ZooReaderWriter zrw = context.getZooSession().asReaderWriter();
+    zrw.sync(zpath);
+    if (!zrw.exists(zpath)) {
+      ComponentVersions cv = new ComponentVersions();
+      cv.zooKeeperVersion = currentVersion;
+      cv.rootVersion = currentVersion;
+      cv.metadataVersion = currentVersion;
+      put(context, cv);
+      return cv;
+    } else {
+      byte[] jsonData = zrw.getData(zpath);
+      return GSON.get().fromJson(new String(jsonData, UTF_8), 
ComponentVersions.class);
+    }
+  }
+
+  static synchronized void upgradeComplete(ServerContext context)
+      throws KeeperException, InterruptedException {
+    final String zpath = getZPath(context);
+    final ZooReaderWriter zrw = context.getZooSession().asReaderWriter();
+    zrw.sync(zpath);
+    if (!zrw.exists(zpath)) {
+      zrw.recursiveDelete(zpath, NodeMissingPolicy.SKIP);
+    }

Review Comment:
   Seems like this should be if `exists()` instead of if `!exists()`.  It may 
be ok to remove the exists check as long as recursiveDelete does not throw 
anything if its not there.
   
   ```suggestion
         zrw.recursiveDelete(zpath, NodeMissingPolicy.SKIP);
   ```



##########
server/manager/src/main/java/org/apache/accumulo/manager/upgrade/UpgradeProgressTracker.java:
##########
@@ -0,0 +1,127 @@
+/*
+ * 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.upgrade;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.accumulo.core.util.LazySingletons.GSON;
+
+import java.util.Objects;
+
+import org.apache.accumulo.core.Constants;
+import org.apache.accumulo.core.fate.zookeeper.ZooReaderWriter;
+import org.apache.accumulo.core.fate.zookeeper.ZooUtil.NodeExistsPolicy;
+import org.apache.accumulo.core.fate.zookeeper.ZooUtil.NodeMissingPolicy;
+import org.apache.accumulo.server.AccumuloDataVersion;
+import org.apache.accumulo.server.ServerContext;
+import org.apache.zookeeper.KeeperException;
+
+import com.google.common.base.Preconditions;
+
+public class UpgradeProgressTracker {
+
+  public static class ComponentVersions {
+    private int zooKeeperVersion;
+    private int rootVersion;
+    private int metadataVersion;
+
+    int getZooKeeperVersion() {
+      return zooKeeperVersion;
+    }
+
+    synchronized void updateZooKeeperVersion(ServerContext context, int 
newVersion)
+        throws KeeperException, InterruptedException {
+      Objects.requireNonNull(context, "ServerContext must be supplied");
+      Preconditions.checkArgument(newVersion > zooKeeperVersion,
+          "new version must be greater than current version");

Review Comment:
   When updating any single version can check all three. This is attempting to  
check the three versions are updated in the expected order relative to each 
other.
   
   ```suggestion
         Preconditions.checkArgument(newVersion > zooKeeperVersion,
             "new version must be greater than current version %s %s", 
newVersion, zooKeeperVersion);
         Preconditions.checkArgument(rootVersion < newVersion && 
metadataVersion == rootVersion,
             "other versions in unexpected state %s %s %s", newVersion, 
rootVersion, metadataVersion);
   ```



##########
server/manager/src/main/java/org/apache/accumulo/manager/upgrade/UpgradeProgressTracker.java:
##########
@@ -0,0 +1,127 @@
+/*
+ * 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.upgrade;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.accumulo.core.util.LazySingletons.GSON;
+
+import java.util.Objects;
+
+import org.apache.accumulo.core.Constants;
+import org.apache.accumulo.core.fate.zookeeper.ZooReaderWriter;
+import org.apache.accumulo.core.fate.zookeeper.ZooUtil.NodeExistsPolicy;
+import org.apache.accumulo.core.fate.zookeeper.ZooUtil.NodeMissingPolicy;
+import org.apache.accumulo.server.AccumuloDataVersion;
+import org.apache.accumulo.server.ServerContext;
+import org.apache.zookeeper.KeeperException;
+
+import com.google.common.base.Preconditions;
+
+public class UpgradeProgressTracker {
+
+  public static class ComponentVersions {
+    private int zooKeeperVersion;
+    private int rootVersion;
+    private int metadataVersion;

Review Comment:
   > With these changes, if ZK is upgraded but then root or metadata table 
fails, is it possible to start an older version of accumulo? Or would it fail 
due to ZK data already being in an upgraded state?
   
   By adding the following may be able to achieve this.  This assumes that we 
update the zookeeper node before making any changes and set the target version. 
 Also the older upgrade code would need to start checking for the precesence of 
this data in zookeeper.
   
   ```suggestion
      // The version we are working towards upgrading to
       private int targetVersion;
   ```
   
   Could support a situation like the following.
   
    1. Stop a 2.1 accumulo instance
    2. Start a 3.1 accumulo instance.  
    3. Before making any upgrade changes, the 3.1 code writes 
`zooKeeperVersion=10,rootVersion=10,metadataVersion=10,targetVersion=12` to ZK 
for upgrade tracking.
    4. The 3.1 code makes some zookeeper modifications for upgrade and fails 
before it updates the tracking data in zookeeper.
    5. At this point 2.1 code is started and looks at the ZK upgrade tracking 
and sees an upgrade is in progress w/ a target version newer than anything it 
knows about and fails to start.
   
   The upgrade code can look for existing tracking data when it starts and if 
it exists ensure the target version is its own version.
   



##########
server/manager/src/main/java/org/apache/accumulo/manager/upgrade/UpgradeProgressTracker.java:
##########
@@ -0,0 +1,127 @@
+/*
+ * 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.upgrade;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.accumulo.core.util.LazySingletons.GSON;
+
+import java.util.Objects;
+
+import org.apache.accumulo.core.Constants;
+import org.apache.accumulo.core.fate.zookeeper.ZooReaderWriter;
+import org.apache.accumulo.core.fate.zookeeper.ZooUtil.NodeExistsPolicy;
+import org.apache.accumulo.core.fate.zookeeper.ZooUtil.NodeMissingPolicy;
+import org.apache.accumulo.server.AccumuloDataVersion;
+import org.apache.accumulo.server.ServerContext;
+import org.apache.zookeeper.KeeperException;
+
+import com.google.common.base.Preconditions;
+
+public class UpgradeProgressTracker {
+
+  public static class ComponentVersions {
+    private int zooKeeperVersion;
+    private int rootVersion;
+    private int metadataVersion;
+
+    int getZooKeeperVersion() {
+      return zooKeeperVersion;
+    }
+
+    synchronized void updateZooKeeperVersion(ServerContext context, int 
newVersion)
+        throws KeeperException, InterruptedException {
+      Objects.requireNonNull(context, "ServerContext must be supplied");
+      Preconditions.checkArgument(newVersion > zooKeeperVersion,
+          "new version must be greater than current version");
+      zooKeeperVersion = newVersion;
+      put(context, this);
+    }
+
+    int getRootVersion() {
+      return rootVersion;
+    }
+
+    synchronized void updateRootVersion(ServerContext context, int newVersion)
+        throws KeeperException, InterruptedException {
+      Objects.requireNonNull(context, "ServerContext must be supplied");
+      Preconditions.checkArgument(newVersion > rootVersion,
+          "new version must be greater than current version");
+      rootVersion = newVersion;
+      put(context, this);
+    }
+
+    int getMetadataVersion() {
+      return metadataVersion;
+    }
+
+    synchronized void updateMetadataVersion(ServerContext context, int 
newVersion)
+        throws KeeperException, InterruptedException {
+      Objects.requireNonNull(context, "ServerContext must be supplied");
+      Preconditions.checkArgument(newVersion > metadataVersion,
+          "new version must be greater than current version");
+      metadataVersion = newVersion;
+      put(context, this);
+    }
+  }
+
+  private static String getZPath(ServerContext context) {
+    return context.getZooKeeperRoot() + Constants.ZUPGRADE_STATUS;
+  }
+
+  private static synchronized void put(ServerContext context, 
ComponentVersions cv)
+      throws KeeperException, InterruptedException {
+    final String zpath = getZPath(context);
+    final ZooReaderWriter zrw = context.getZooSession().asReaderWriter();
+    zrw.sync(zpath);
+    if (!zrw.exists(zpath)) {
+      zrw.mkdirs(zpath);
+    }
+    zrw.putPersistentData(zpath, GSON.get().toJson(cv).getBytes(UTF_8), 
NodeExistsPolicy.OVERWRITE);
+  }
+
+  static synchronized ComponentVersions get(ServerContext context)
+      throws KeeperException, InterruptedException {
+    final String zpath = getZPath(context);
+    final int currentVersion = AccumuloDataVersion.getCurrentVersion(context);
+    final ZooReaderWriter zrw = context.getZooSession().asReaderWriter();
+    zrw.sync(zpath);
+    if (!zrw.exists(zpath)) {
+      ComponentVersions cv = new ComponentVersions();
+      cv.zooKeeperVersion = currentVersion;
+      cv.rootVersion = currentVersion;
+      cv.metadataVersion = currentVersion;
+      put(context, cv);
+      return cv;
+    } else {
+      byte[] jsonData = zrw.getData(zpath);
+      return GSON.get().fromJson(new String(jsonData, UTF_8), 
ComponentVersions.class);
+    }
+  }
+
+  static synchronized void upgradeComplete(ServerContext context)
+      throws KeeperException, InterruptedException {
+    final String zpath = getZPath(context);

Review Comment:
   ```suggestion
       // This should be updated prior to deleting the tracking data in 
zookeeper.
       Preconditions.checkState(AccumuloDataVersion.getCurrentVersion(context) 
== AccumuloDataVersion.get());
       final String zpath = getZPath(context);
   ```



##########
server/manager/src/main/java/org/apache/accumulo/manager/upgrade/UpgradeProgressTracker.java:
##########
@@ -0,0 +1,127 @@
+/*
+ * 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.upgrade;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.accumulo.core.util.LazySingletons.GSON;
+
+import java.util.Objects;
+
+import org.apache.accumulo.core.Constants;
+import org.apache.accumulo.core.fate.zookeeper.ZooReaderWriter;
+import org.apache.accumulo.core.fate.zookeeper.ZooUtil.NodeExistsPolicy;
+import org.apache.accumulo.core.fate.zookeeper.ZooUtil.NodeMissingPolicy;
+import org.apache.accumulo.server.AccumuloDataVersion;
+import org.apache.accumulo.server.ServerContext;
+import org.apache.zookeeper.KeeperException;
+
+import com.google.common.base.Preconditions;
+
+public class UpgradeProgressTracker {
+
+  public static class ComponentVersions {
+    private int zooKeeperVersion;
+    private int rootVersion;
+    private int metadataVersion;
+
+    int getZooKeeperVersion() {
+      return zooKeeperVersion;
+    }
+
+    synchronized void updateZooKeeperVersion(ServerContext context, int 
newVersion)
+        throws KeeperException, InterruptedException {
+      Objects.requireNonNull(context, "ServerContext must be supplied");
+      Preconditions.checkArgument(newVersion > zooKeeperVersion,
+          "new version must be greater than current version");
+      zooKeeperVersion = newVersion;
+      put(context, this);
+    }
+
+    int getRootVersion() {
+      return rootVersion;
+    }
+
+    synchronized void updateRootVersion(ServerContext context, int newVersion)
+        throws KeeperException, InterruptedException {
+      Objects.requireNonNull(context, "ServerContext must be supplied");
+      Preconditions.checkArgument(newVersion > rootVersion,

Review Comment:
   Could  also check that `newVersion <= zooKeeperVersion && newVersion > 
metadataVersion`



##########
server/manager/src/main/java/org/apache/accumulo/manager/upgrade/UpgradeProgressTracker.java:
##########
@@ -0,0 +1,127 @@
+/*
+ * 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.upgrade;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.accumulo.core.util.LazySingletons.GSON;
+
+import java.util.Objects;
+
+import org.apache.accumulo.core.Constants;
+import org.apache.accumulo.core.fate.zookeeper.ZooReaderWriter;
+import org.apache.accumulo.core.fate.zookeeper.ZooUtil.NodeExistsPolicy;
+import org.apache.accumulo.core.fate.zookeeper.ZooUtil.NodeMissingPolicy;
+import org.apache.accumulo.server.AccumuloDataVersion;
+import org.apache.accumulo.server.ServerContext;
+import org.apache.zookeeper.KeeperException;
+
+import com.google.common.base.Preconditions;
+
+public class UpgradeProgressTracker {
+
+  public static class ComponentVersions {
+    private int zooKeeperVersion;
+    private int rootVersion;
+    private int metadataVersion;
+
+    int getZooKeeperVersion() {
+      return zooKeeperVersion;
+    }
+
+    synchronized void updateZooKeeperVersion(ServerContext context, int 
newVersion)
+        throws KeeperException, InterruptedException {
+      Objects.requireNonNull(context, "ServerContext must be supplied");
+      Preconditions.checkArgument(newVersion > zooKeeperVersion,
+          "new version must be greater than current version");
+      zooKeeperVersion = newVersion;
+      put(context, this);
+    }
+
+    int getRootVersion() {
+      return rootVersion;
+    }
+
+    synchronized void updateRootVersion(ServerContext context, int newVersion)
+        throws KeeperException, InterruptedException {
+      Objects.requireNonNull(context, "ServerContext must be supplied");
+      Preconditions.checkArgument(newVersion > rootVersion,
+          "new version must be greater than current version");
+      rootVersion = newVersion;
+      put(context, this);
+    }
+
+    int getMetadataVersion() {
+      return metadataVersion;
+    }
+
+    synchronized void updateMetadataVersion(ServerContext context, int 
newVersion)
+        throws KeeperException, InterruptedException {
+      Objects.requireNonNull(context, "ServerContext must be supplied");
+      Preconditions.checkArgument(newVersion > metadataVersion,

Review Comment:
   Could also check that `newVersion <= zooKeeperVersion && newVersion <= 
rootVersion`



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