This is an automated email from the ASF dual-hosted git repository. jxue pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/helix.git
commit 5389b173945b6f82cd5691a7c0457b1ccb98988a Author: Marcos Rico Peng <[email protected]> AuthorDate: Thu Jul 13 17:16:30 2023 -0400 MultiThreading Stress Test Lattice - Puppy Logic and Skeleton (Part 1) (#2549) --------- Co-authored-by: mapeng <[email protected]> --- .../helix/metaclient/puppy/AbstractPuppy.java | 95 ++++++++++++++++++++++ .../apache/helix/metaclient/puppy/ExecDelay.java | 63 ++++++++++++++ .../helix/metaclient/puppy/PuppyManager.java | 64 +++++++++++++++ .../apache/helix/metaclient/puppy/PuppyMode.java | 28 +++++++ .../apache/helix/metaclient/puppy/PuppySpec.java | 53 ++++++++++++ 5 files changed, 303 insertions(+) diff --git a/meta-client/src/test/java/org/apache/helix/metaclient/puppy/AbstractPuppy.java b/meta-client/src/test/java/org/apache/helix/metaclient/puppy/AbstractPuppy.java new file mode 100644 index 000000000..85137fc17 --- /dev/null +++ b/meta-client/src/test/java/org/apache/helix/metaclient/puppy/AbstractPuppy.java @@ -0,0 +1,95 @@ +package org.apache.helix.metaclient.puppy; + +/* + * 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 + * + * http://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. + */ + +import org.apache.helix.metaclient.api.MetaClientInterface; +import java.util.HashMap; + +/** + * AbstractPuppy object contains interfaces to implement puppy and main logics to manage puppy life cycle + */ +public abstract class AbstractPuppy implements Runnable { + + protected MetaClientInterface<String> _metaclient; + protected PuppySpec _puppySpec; + public HashMap<String, Integer> _eventChangeCounterMap; + protected int _unhandledErrorCounter; + + public AbstractPuppy(MetaClientInterface<String> metaclient, PuppySpec puppySpec) { + _metaclient = metaclient; + _puppySpec = puppySpec; + _eventChangeCounterMap = new HashMap<>(); + } + + /** + * Implements puppy's main logic. Puppy needs to implement its chaos logic, recovery logic based on + * errorRate, recoverDelay. For OneOff puppy, it will bark once with execDelay in spec, and for + * Repeat puppy, it will bark forever, with execDelay between 2 barks + */ + protected abstract void bark() throws Exception; + + /** + * Implements puppy's final cleanup logic - it will be called only once right before the puppy terminates. + * Before the puppy terminates, it needs to recover from all chaos it created. + */ + protected abstract void cleanup(); + + @Override + public void run() { + try { + while (true) { + try { + bark(); + } catch (Exception e) { + incrementUnhandledErrorCounter(); + e.printStackTrace(); + } + + if (getPuppySpec().getMode() == PuppyMode.ONE_OFF) { + cleanup(); + break; + } else { + try { + Thread.sleep(getPuppySpec().getExecDelay().getNextDelay()); + } catch (InterruptedException e) { + // Handle interruption if necessary + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public PuppySpec getPuppySpec() { + return _puppySpec; + } + + public int getUnhandledErrorCounter() { + return _unhandledErrorCounter; + } + + private void incrementUnhandledErrorCounter() { + _unhandledErrorCounter++; + } +} + + + diff --git a/meta-client/src/test/java/org/apache/helix/metaclient/puppy/ExecDelay.java b/meta-client/src/test/java/org/apache/helix/metaclient/puppy/ExecDelay.java new file mode 100644 index 000000000..da0bc529a --- /dev/null +++ b/meta-client/src/test/java/org/apache/helix/metaclient/puppy/ExecDelay.java @@ -0,0 +1,63 @@ +package org.apache.helix.metaclient.puppy; + +/* + * 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 + * + * http://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. + */ + +import java.util.Random; + +/** + * ExecDelay class definition + */ +public class ExecDelay { + private final long _duration; + private final float _jitter; + + private final long _delayBase; + private final long _delayRange; + private final Random _random; + + public ExecDelay(long duration, float jitter) { + if (jitter < 0 || jitter > 1 || duration < 0) { + throw new IllegalArgumentException( + String.format("Invalid _jitter (%s) or _duration (%s)", jitter, duration)); + } + _duration = duration; + _jitter = jitter; + _delayRange = Math.round(_duration * _jitter * 2); + _delayBase = _duration - _delayRange / 2; + _random = new Random(); + } + + /** + * Calculate the next delay based on the configured _duration and _jitter. + * @return The next delay in milliseconds. + */ + public long getNextDelay() { + long randomDelay = _delayBase + _random.nextLong() % _delayRange; + return Math.max(randomDelay, 0); + } + + public long getDuration() { + return _duration; + } + + public float getJitter() { + return _jitter; + } +} diff --git a/meta-client/src/test/java/org/apache/helix/metaclient/puppy/PuppyManager.java b/meta-client/src/test/java/org/apache/helix/metaclient/puppy/PuppyManager.java new file mode 100644 index 000000000..9ef948c59 --- /dev/null +++ b/meta-client/src/test/java/org/apache/helix/metaclient/puppy/PuppyManager.java @@ -0,0 +1,64 @@ +package org.apache.helix.metaclient.puppy; + +/* + * 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 + * + * http://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. + */ + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +/** + * This class is used to manage the lifecycle of a set of _puppies. + */ +public class PuppyManager { + private final List<AbstractPuppy> _puppies = new ArrayList<>(); + private final ExecutorService EXECUTOR_SERVICE = Executors.newCachedThreadPool(); + + public PuppyManager() { + } + + public void addPuppy(AbstractPuppy puppy) { + _puppies.add(puppy); + } + + public List<AbstractPuppy> getPuppies() { + return _puppies; + } + + public void start(long timeoutInSeconds) { + for (AbstractPuppy puppy : _puppies) { + EXECUTOR_SERVICE.submit(puppy); + } + + try { + EXECUTOR_SERVICE.awaitTermination(timeoutInSeconds, TimeUnit.SECONDS); + } catch (InterruptedException e) { + // Ignore + } + + stop(); + } + + public void stop() { + EXECUTOR_SERVICE.shutdownNow(); + } +} + diff --git a/meta-client/src/test/java/org/apache/helix/metaclient/puppy/PuppyMode.java b/meta-client/src/test/java/org/apache/helix/metaclient/puppy/PuppyMode.java new file mode 100644 index 000000000..d834f020e --- /dev/null +++ b/meta-client/src/test/java/org/apache/helix/metaclient/puppy/PuppyMode.java @@ -0,0 +1,28 @@ +package org.apache.helix.metaclient.puppy; + +/* + * 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 + * + * http://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. + */ + +/** + * Enum for Puppy mode (OneOff or Repeat) + */ +public enum PuppyMode { + ONE_OFF, + REPEAT +} diff --git a/meta-client/src/test/java/org/apache/helix/metaclient/puppy/PuppySpec.java b/meta-client/src/test/java/org/apache/helix/metaclient/puppy/PuppySpec.java new file mode 100644 index 000000000..ac6d527df --- /dev/null +++ b/meta-client/src/test/java/org/apache/helix/metaclient/puppy/PuppySpec.java @@ -0,0 +1,53 @@ +package org.apache.helix.metaclient.puppy; + +/* + * 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 + * + * http://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. + */ + +/** + * PuppySpec class definition + */ +public class PuppySpec { + private final PuppyMode _mode; + private final float _errorRate; + private final ExecDelay _execDelay; + private final int _numberDiffPaths; + + public PuppySpec(PuppyMode mode, float errorRate, ExecDelay execDelay, int numberDiffPaths) { + _mode = mode; + _errorRate = errorRate; + _execDelay = execDelay; + _numberDiffPaths = numberDiffPaths; + } + + public PuppyMode getMode() { + return _mode; + } + + public float getErrorRate() { + return _errorRate; + } + + public ExecDelay getExecDelay() { + return _execDelay; + } + + public int getNumberDiffPaths() { + return _numberDiffPaths; + } +}
