Permalink
Browse files

add 'hiccup' and 'truncate' commands to mock

Hiccup will force a delay for a response after sending <n> bytes
Truncate will only send up to <n> bytes for any output buffer

Change-Id: I89a441a62400c0ec82338c334b73450eede60d05
Reviewed-on: http://review.couchbase.org/13619
Reviewed-by: Sergey Avseyev <sergey.avseyev@gmail.com>
Tested-by: Sergey Avseyev <sergey.avseyev@gmail.com>
  • Loading branch information...
1 parent 32e40aa commit 30e77c2a413a149b889884b088aa0cb5c6cbb7bf @mnunberg mnunberg committed with ingenthr Feb 25, 2012
@@ -50,6 +50,10 @@ public Bucket(String name, String hostname, int port, int numNodes, int bucketSt
this(name, hostname, port, numNodes, bucketStartPort, numVBuckets, cluster, "");
}
+ public MemcachedServer[] getServers() {
+ return servers;
+ }
+
public Bucket(String name, String hostname, int port, int numNodes, int bucketStartPort, int numVBuckets, CouchbaseMock cluster, String password) throws IOException {
this.cluster = cluster;
this.name = name;
@@ -27,17 +27,24 @@
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Observable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
+
import org.couchbase.mock.Bucket.BucketType;
import org.couchbase.mock.http.Authenticator;
import org.couchbase.mock.http.PoolsHandler;
import org.couchbase.mock.util.Getopt;
import org.couchbase.mock.util.Getopt.CommandLineOption;
import org.couchbase.mock.util.Getopt.Entry;
+import org.couchbase.mock.control.MockControlCommandHandler;
+import org.couchbase.mock.control.FailoverCommandHandler;
+import org.couchbase.mock.control.RespawnCommandHandler;
+import org.couchbase.mock.control.HiccupCommandHandler;
+import org.couchbase.mock.control.TruncateCommandHandler;
/**
* This is a super-scaled down version of something that might look like
@@ -80,20 +87,6 @@ public String getPoolName() {
return buckets;
}
- private void failover(String bucketName, int idx) {
- Bucket bucket = buckets.get(bucketName);
- if (bucket != null) {
- bucket.failover(idx);
- }
- }
-
- private void respawn(String bucketName, int idx) {
- Bucket bucket = buckets.get(bucketName);
- if (bucket != null) {
- bucket.respawn(idx);
- }
- }
-
public HarakiriMonitor getMonitor() {
return monitor;
}
@@ -106,13 +99,22 @@ public HarakiriMonitor getMonitor() {
private OutputStream output;
private Socket sock;
private Thread thread;
+ private final Map<String,MockControlCommandHandler> commandHandlers;
+
public HarakiriMonitor(String host, int port, boolean terminate, CouchbaseMock mock) throws IOException {
this.mock = mock;
this.terminate = terminate;
sock = new Socket(host, port);
input = new BufferedReader(new InputStreamReader(sock.getInputStream()));
output = sock.getOutputStream();
+
+ commandHandlers = new HashMap<String, MockControlCommandHandler>();
+ commandHandlers.put("failover", new FailoverCommandHandler());
+ commandHandlers.put("respawn", new RespawnCommandHandler());
+ commandHandlers.put("hiccup", new HiccupCommandHandler());
+ commandHandlers.put("truncate", new TruncateCommandHandler());
+
}
public void start()
@@ -126,12 +128,33 @@ public void stop()
thread.interrupt();
}
+ private void dispatchMockCommand(String packet) {
+ List<String> tokens = new ArrayList<String>();
+ tokens.addAll(Arrays.asList(packet.split(",")));
+ String command = tokens.remove(0);
+
+ MockControlCommandHandler handler = commandHandlers.get(command);
+
+ if (handler == null) {
+ System.err.printf("Unknown command '%s'\n", command);
+ return;
+ }
+
+ try {
+ handler.execute(mock, tokens);
+ }
+ catch (NumberFormatException ex) {
+ System.err.printf("Got exception: %s\n", ex.toString());
+ return;
+ }
+ setChanged();
+ notifyObservers();
+ }
+
@Override
public void run() {
boolean closed = false;
- String[] tokens;
- String command, bucket, packet;
- int idx;
+ String packet;
String http = "" + mock.getHttpPort() + '\0';
try {
mock.waitForStartup();
@@ -148,33 +171,7 @@ public void run() {
if (packet == null) {
closed = true;
} else if (mock != null) {
- /* format (bucket name is optional):
- *
- * failover,123,default
- * respawn,123,default
- */
- tokens = packet.split(",");
- if (tokens.length >= 2) {
- try {
- command = tokens[0];
- idx = Integer.parseInt(tokens[1].trim());
- if (tokens.length == 3) {
- bucket = tokens[2];
- } else {
- bucket = "default";
- }
- if ("failover".equals(command)) {
- mock.failover(bucket, idx);
- setChanged();
- notifyObservers();
- } else if ("respawn".equals(command)) {
- mock.respawn(bucket, idx);
- setChanged();
- notifyObservers();
- }
- } catch (NumberFormatException ex) {
- }
- }
+ dispatchMockCommand(packet);
}
} catch (IOException e) {
// not exactly true, but who cares..
@@ -0,0 +1,46 @@
+/**
+ * Copyright 2012 Couchbase, Inc.
+ *
+ * Licensed 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.
+ */
+package org.couchbase.mock.control;
+
+import java.util.List;
+
+import org.couchbase.mock.Bucket;
+import org.couchbase.mock.CouchbaseMock;
+
+/**
+ * This is an abstract class which operates on a specific
+ * server on a specific bucket.
+ * @author M. Nunberg
+ *
+ */
+abstract public class BucketCommandHandler implements MockControlCommandHandler {
+
+ public Bucket bucket;
+ public int idx;
+
+ abstract void doBucketCommand();
+
+ @Override
+ public void execute(CouchbaseMock mock, List<String> tokens) {
+ idx = Integer.parseInt(tokens.get(0));
+ if (tokens.size() == 2) {
+ bucket = mock.getBuckets().get(tokens.get(1));
+ } else {
+ bucket = mock.getBuckets().get("default");
+ }
+ doBucketCommand();
+ }
+}
@@ -0,0 +1,24 @@
+/**
+ * Copyright 2012 Couchbase, Inc.
+ *
+ * Licensed 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.
+ */
+package org.couchbase.mock.control;
+
+public class FailoverCommandHandler extends BucketCommandHandler {
+
+ @Override
+ void doBucketCommand() {
+ bucket.failover(idx);
+ }
+}
@@ -0,0 +1,43 @@
+/**
+ * Copyright 2012 Couchbase, Inc.
+ *
+ * Licensed 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.
+ */
+package org.couchbase.mock.control;
+
+import java.util.List;
+
+import org.couchbase.mock.memcached.MemcachedServer;
+
+/**
+ * Hiccup will let all servers sleep after sending a specific amount of data.
+ *
+ * @author M. Nunberg
+ *
+ */
+public class HiccupCommandHandler extends ServersCommandHandler {
+
+ private int msecs;
+ private int offset;
+
+ @Override
+ void extractParams(List<String> tokens) {
+ msecs = Integer.parseInt(tokens.get(0));
+ offset = Integer.parseInt(tokens.get(1));
+ }
+
+ @Override
+ void doServerCommand(MemcachedServer server) {
+ server.setHiccup(msecs, offset);
+ }
+}
@@ -0,0 +1,30 @@
+/**
+ * Copyright 2012 Couchbase, Inc.
+ *
+ * Licensed 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.
+ */
+package org.couchbase.mock.control;
+
+import java.util.List;
+import org.couchbase.mock.CouchbaseMock;
+
+/**
+ * This provides an interface for mock commands. They are all issued by providing
+ * ','-delimited tokens.
+ * @author M. Nunberg
+ *
+ */
+public interface MockControlCommandHandler {
+
+ abstract void execute(CouchbaseMock mock, List<String> tokens);
+}
@@ -0,0 +1,24 @@
+/**
+ * Copyright 2012 Couchbase, Inc.
+ *
+ * Licensed 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.
+ */
+package org.couchbase.mock.control;
+
+public class RespawnCommandHandler extends BucketCommandHandler {
+
+ @Override
+ void doBucketCommand() {
+ bucket.respawn(idx);
+ }
+}
@@ -0,0 +1,47 @@
+/**
+ * Copyright 2012 Couchbase, Inc.
+ *
+ * Licensed 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.
+ */
+package org.couchbase.mock.control;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.couchbase.mock.Bucket;
+import org.couchbase.mock.CouchbaseMock;
+import org.couchbase.mock.memcached.MemcachedServer;
+
+public abstract class ServersCommandHandler implements MockControlCommandHandler {
+
+ abstract void doServerCommand(MemcachedServer server);
+
+ abstract void extractParams(List<String> tokens);
+
+ @Override
+ public void execute(CouchbaseMock mock, List<String> tokens) {
+ extractParams(tokens);
+ Set<MemcachedServer> servers = new HashSet<MemcachedServer>();
+
+ for (Bucket bucket : mock.getBuckets().values()) {
+ for (MemcachedServer server : bucket.getServers()) {
+ if (servers.contains(server) == false) {
+ doServerCommand(server);
+ servers.add(server);
+ }
+ }
+ }
+
+ }
+}
Oops, something went wrong.

0 comments on commit 30e77c2

Please sign in to comment.