org.couchbase.mock.control.handlers.PersistenceCommandHandler.java Source code

Java tutorial

Introduction

Here is the source code for org.couchbase.mock.control.handlers.PersistenceCommandHandler.java

Source

/*
 * Copyright 2013 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.handlers;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import java.security.AccessControlException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.gson.JsonObject;
import org.couchbase.mock.CouchbaseMock;
import org.couchbase.mock.control.CommandStatus;
import org.couchbase.mock.memcached.*;
import org.jetbrains.annotations.NotNull;

/**
 * Handler for various out-of-band key manipulations
 * @author Mark Nunberg <mnunberg@haskalah.org>
 */
public final class PersistenceCommandHandler extends KeyCommandHandler {

    private String error = null;

    private void executeReal(JsonObject payload, Command command) {
        final String value;
        long cas = 0;
        boolean onMaster;

        JsonElement eOnReplicas;

        Storage masterStore;
        List<Storage> stores = new ArrayList<Storage>();
        onMaster = payload.get("OnMaster").getAsBoolean();

        if (payload.has("CAS")) {
            cas = payload.get("CAS").getAsLong();
        }

        if (payload.has("Value")) {
            value = payload.get("Value").getAsString();
        } else {
            value = "";
        }

        masterStore = vbi.getOwner().getStorage();

        if (onMaster) {
            stores.add(masterStore);
        }

        // Figure out which replicas to affect
        eOnReplicas = payload.get("OnReplicas");
        if (eOnReplicas.isJsonArray()) {
            // An array of indices to use:
            for (JsonElement ix : eOnReplicas.getAsJsonArray()) {
                MemcachedServer mc = vbi.getReplicas().get(ix.getAsInt());
                Storage s = mc.getStorage();
                if (!stores.contains(s)) {
                    stores.add(s);
                }
            }
        } else {
            int maxReplicas = eOnReplicas.getAsInt();
            int replicasSelected = 0;
            for (MemcachedServer server : vbi.getReplicas()) {
                if (replicasSelected == maxReplicas) {
                    break;
                }
                if (!server.isActive()) {
                    continue;
                }
                stores.add(server.getStorage());
                replicasSelected++;
            }
        }

        Item source = masterStore.getCached(keySpec);
        Item newItem;

        if (source == null) {
            assert value != null;
            assert value.getBytes() != null;
            source = new Item(keySpec, 0, 0, value.getBytes(), null, cas);
        }

        if (cas < 0) {
            cas = (source.getCas() + 1) * 2;
        }

        if (cas != 0) {
            newItem = new Item(source.getKeySpec(), source.getFlags(), source.getExpiryTime(), value.getBytes(),
                    source.getXattr(), cas);

        } else {
            newItem = new Item(source);
        }

        if (stores.size() == 0) {
            System.err.println("No stores available for key");
        }

        for (Storage curStore : stores) {
            switch (command) {
            case PERSIST:
            case ENDURE:
                curStore.putPersisted(newItem);
                if (command == Command.PERSIST) {
                    break;
                }
                // ENDURE fallthrough
            case CACHE:
                curStore.putCached(newItem);
                break;

            case PURGE:
            case UNPERSIST:
                curStore.removePersisted(keySpec);
                if (command == Command.UNPERSIST) {
                    break;
                }

            case UNCACHE:
                curStore.removeCached(keySpec);
                break;

            default:
                throw new RuntimeException("Unrecognized command");
            }
        }
    }

    @NotNull
    @Override
    public CommandStatus execute(@NotNull CouchbaseMock mock, @NotNull Command command,
            @NotNull JsonObject payload) {
        super.execute(mock, command, payload);
        try {
            executeReal(payload, command);
        } catch (AccessControlException e) {
            error = e.getMessage();
        }

        return getResponse();
    }

    @NotNull
    @Override
    protected CommandStatus getResponse() {
        if (error == null) {
            return super.getResponse();
        }
        return new CommandStatus().fail(error);
    }
}