/**
* Copyright 2011 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;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Arrays;
import java.util.zip.CRC32;
import org.couchbase.mock.memcached.*;
import org.couchbase.mock.memcached.protocol.ErrorCode;
/**
* Representation of a membase bucket
*
* @author Trond Norbye
*/
public class CouchbaseBucket extends Bucket {
public CouchbaseBucket(CouchbaseMock cluster, BucketConfiguration config)
throws IOException
{
super(cluster, config);
}
@Override
public short getVbIndexForKey(String key) {
CRC32 crc32 = new CRC32();
crc32.update(key.getBytes());
long digest = ( crc32.getValue() >> 16 ) & 0x7fff;
long vbKey = digest & ( vbInfo.length - 1 );
return (short) vbKey;
}
@Override
public Map<String,Object> getConfigMap() {
Map<String, Object> map = getCommonConfig();
List<MemcachedServer> active = activeServers();
map.put("name", name);
map.put("bucketType", "membase");
map.put("authType", "sasl");
map.put("saslPassword", getPassword());
map.put("proxyPort", 0);
map.put("uri", "/pools/" + poolName + "/buckets/" + name);
map.put("streamingUri", "/pools/" + poolName + "/bucketsStreaming/" + name);
map.put("flushCacheUri", "/pools/" + poolName + "/buckets/" + name + "/controller/doFlush");
List<Map> nodes = new ArrayList<Map>();
List<Map> nodesExt = new ArrayList<Map>();
for (MemcachedServer server : active) {
Map<String,Object> nodeInfo = server.toNodeConfigInfo();
Map<String,Object> svcsTopLevel = new HashMap<String, Object>();
Map<String,Object> svcsInfo = new HashMap<String, Object>();
svcsTopLevel.put("services", svcsInfo);
if (cluster != null) {
// Add 'couchApiBase'
String capiBase = String.format("http://%s:%d/%s", server.getHostname(), cluster.getHttpPort(), name);
nodeInfo.put("couchApiBase", capiBase);
svcsTopLevel.put("hostname", server.getHostname());
svcsInfo.put("mgmt", cluster.getHttpPort());
svcsInfo.put("n1ql", cluster.getHttpPort());
svcsInfo.put("capi", cluster.getHttpPort());
}
nodes.add(nodeInfo);
svcsInfo.put("kv", server.getPort());
nodesExt.add(svcsTopLevel);
}
map.put("nodes", nodes);
map.put("nodesExt", nodesExt);
Map<String, String> stats = new HashMap<String, String>();
stats.put("uri", "/pools/" + poolName + "/buckets/" + name + "/stats");
map.put("stats", stats);
map.put("nodeLocator", "vbucket");
Map<String, Object> vbm = new HashMap<String, Object>();
vbm.put("hashAlgorithm", "CRC");
vbm.put("numReplicas", numReplicas);
List<String> serverList = new ArrayList<String>();
for (MemcachedServer server : active) {
serverList.add(server.getSocketName());
}
vbm.put("serverList", serverList);
ArrayList<ArrayList<Integer>> m = new ArrayList<ArrayList<Integer>>();
for (short ii = 0; ii < numVBuckets; ++ii) {
MemcachedServer master = vbInfo[ii].getOwner();
List<MemcachedServer> replicas = vbInfo[ii].getReplicas();
ArrayList<Integer> line = new ArrayList<Integer>();
line.add(active.indexOf(master));
for (MemcachedServer replica : replicas) {
line.add(active.indexOf(replica));
}
// If numReplicas is greater than list.size() - 1
// (because we also have the master) then fill it with
// zeros until we have the desired count
while (line.size()-1 < numReplicas) {
line.add(-1);
}
m.add(line);
}
vbm.put("vBucketMap", m);
map.put("vBucketServerMap", vbm);
map.put("bucketCapabilitiesVer", "");
map.put("bucketCapabilities", Arrays.asList("cbhello", "touch", "couchapi", "cccp", "nodesExt"));
return map;
}
@Override
public BucketType getType() {
return BucketType.COUCHBASE;
}
@Override
public ErrorCode storeItem(String key, byte[] value) {
short vbIndex = getVbIndexForKey(key);
KeySpec ks = new KeySpec(key, vbIndex);
Item item = new Item(ks, 0, 0, value, null, 0);
MemcachedServer server = vbInfo[vbIndex].getOwner();
VBucketStore vbStore = server.getStorage().getCache(vbIndex);
return vbStore.set(item).getStatus();
}
}