/*
* Copyright 2010 LinkedIn, 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 voldemort.performance.benchmark;
import voldemort.client.DefaultStoreClient;
import voldemort.client.StoreClient;
import voldemort.client.UpdateAction;
import voldemort.utils.Time;
import voldemort.versioning.VectorClock;
import voldemort.versioning.Versioned;
public class VoldemortWrapper {
public enum ReturnCode {
Ok,
Error
}
public enum WarningCode {
NO_CURRENT_VALUE
}
private StoreClient<Object, Object> voldemortStore;
private Metrics measurement;
private boolean verifyReads;
private boolean ignoreNulls;
private final boolean localMode;
public enum Operations {
Read("reads"),
Delete("deletes"),
Write("writes"),
Mixed("transactions");
private String opString;
public String getOpString() {
return this.opString;
}
Operations(String opString) {
this.opString = opString;
}
}
public VoldemortWrapper(StoreClient<Object, Object> storeClient,
boolean verifyReads,
boolean ignoreNulls,
boolean localMode) {
this.voldemortStore = storeClient;
this.measurement = Metrics.getInstance();
this.verifyReads = verifyReads;
this.ignoreNulls = ignoreNulls;
this.localMode = localMode;
}
public void read(Object key, Object expectedValue, Object transforms) {
long startNs = System.nanoTime();
Versioned<Object> returnedValue = voldemortStore.get(key, transforms);
long endNs = System.nanoTime();
measurement.recordLatency(Operations.Read.getOpString(),
(int) ((endNs - startNs) / Time.NS_PER_MS));
ReturnCode res = ReturnCode.Ok;
if(returnedValue == null && !this.ignoreNulls) {
res = ReturnCode.Error;
}
if(verifyReads && !expectedValue.equals(returnedValue.getValue())) {
res = ReturnCode.Error;
}
measurement.recordReturnCode(Operations.Read.getOpString(), res.ordinal());
}
public void mixed(final Object key, final Object newValue, final Object transforms) {
boolean updated = voldemortStore.applyUpdate(new UpdateAction<Object, Object>() {
@Override
public void update(StoreClient<Object, Object> storeClient) {
long startNs = System.nanoTime();
Versioned<Object> vs = storeClient.get(key);
boolean noCurrentValue = (vs == null);
if (localMode) {
VectorClock clock = (vs == null) ? new VectorClock() : (VectorClock) vs.getVersion();
clock = clock.incremented(1, System.currentTimeMillis());
Versioned<Object> versionedNewValue = new Versioned<Object>(newValue, clock);
((DefaultStoreClient<Object, Object>) storeClient).put(key, versionedNewValue, transforms);
} else {
storeClient.put(key, newValue, transforms);
}
long endNs = System.nanoTime();
measurement.recordLatency(Operations.Mixed.getOpString(),
(int) ((endNs - startNs) / Time.NS_PER_MS));
if (noCurrentValue) {
measurement.recordWarningCode(Operations.Mixed.getOpString(), WarningCode.NO_CURRENT_VALUE.ordinal());
}
}
});
ReturnCode res = ReturnCode.Error;
if(updated) {
res = ReturnCode.Ok;
}
measurement.recordReturnCode(Operations.Mixed.getOpString(), res.ordinal());
}
public void write(final Object key, final Object value, final Object transforms) {
boolean written = voldemortStore.applyUpdate(new UpdateAction<Object, Object>() {
@Override
public void update(StoreClient<Object, Object> storeClient) {
long startNs = System.nanoTime();
storeClient.put(key, value, transforms);
long endNs = System.nanoTime();
measurement.recordLatency(Operations.Write.getOpString(),
(int) ((endNs - startNs) / Time.NS_PER_MS));
}
});
ReturnCode res = ReturnCode.Error;
if(written) {
res = ReturnCode.Ok;
}
measurement.recordReturnCode(Operations.Write.getOpString(), res.ordinal());
}
public void delete(Object key) {
long startNs = System.nanoTime();
boolean deleted = voldemortStore.delete(key);
long endNs = System.nanoTime();
ReturnCode res = ReturnCode.Error;
if(deleted) {
res = ReturnCode.Ok;
}
measurement.recordLatency(Operations.Delete.getOpString(),
(int) ((endNs - startNs) / Time.NS_PER_MS));
measurement.recordReturnCode(Operations.Delete.getOpString(), res.ordinal());
}
}