/**
* 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.
*/
package org.apache.zookeeper_voltpatches.server;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
import org.apache.jute_voltpatches.BinaryOutputArchive;
import org.apache.jute_voltpatches.InputArchive;
import org.apache.jute_voltpatches.OutputArchive;
import org.apache.jute_voltpatches.Record;
import org.apache.log4j.Logger;
import org.apache.zookeeper_voltpatches.server.DataNode;
import org.apache.zookeeper_voltpatches.server.DataTree;
import org.apache.zookeeper_voltpatches.server.ServerCnxn;
import org.apache.zookeeper_voltpatches.server.ZKDatabase;
import org.apache.zookeeper_voltpatches.KeeperException;
import org.apache.zookeeper_voltpatches.Watcher;
import org.apache.zookeeper_voltpatches.KeeperException.NoNodeException;
import org.apache.zookeeper_voltpatches.data.ACL;
import org.apache.zookeeper_voltpatches.data.Stat;
import org.apache.zookeeper_voltpatches.server.DataTree.ProcessTxnResult;
import org.apache.zookeeper_voltpatches.server.util.SerializeUtils;
import org.apache.zookeeper_voltpatches.txn.TxnHeader;
/**
* This class maintains the in memory database of zookeeper
* server states that includes the sessions, datatree and the
* committed logs. It is booted up after reading the logs
* and snapshots from the disk.
*/
public class ZKDatabase {
private static final Logger LOG = Logger.getLogger(ZKDatabase.class);
/**
* make sure on a clear you take care of
* all these members.
*/
protected DataTree dataTree;
protected ConcurrentHashMap<Long, Long> sessionsWithTimeouts;
/**
* the filetxnsnaplog that this zk database
* maps to. There is a one to one relationship
* between a filetxnsnaplog and zkdatabase.
* @param snapLog the FileTxnSnapLog mapping this zkdatabase
*/
public ZKDatabase() {
dataTree = new DataTree();
sessionsWithTimeouts = new ConcurrentHashMap<Long, Long>();
}
/**
* the datatree for this zkdatabase
* @return the datatree for this zkdatabase
*/
public DataTree getDataTree() {
return this.dataTree;
}
/**
* get the last processed zxid from a datatree
* @return the last processed zxid of a datatree
*/
public long getDataTreeLastProcessedZxid() {
return dataTree.lastProcessedZxid;
}
/**
* set the datatree initialized or not
* @param b set the datatree initialized to b
*/
public void setDataTreeInit(boolean b) {
dataTree.initialized = b;
}
/**
* return the sessions in the datatree
* @return the data tree sessions
*/
public Collection<Long> getSessions() {
return dataTree.getSessions();
}
/**
* get sessions with timeouts
* @return the hashmap of sessions with timeouts
*/
public ConcurrentHashMap<Long, Long> getSessionWithTimeOuts() {
return sessionsWithTimeouts;
}
/**
* remove a cnxn from the datatree
* @param cnxn the cnxn to remove from the datatree
*/
public void removeCnxn(ServerCnxn cnxn) {
dataTree.removeCnxn(cnxn);
}
/**
* kill a given session in the datatree
* @param sessionId the session id to be killed
* @param zxid the zxid of kill session transaction
*/
public void killSession(long sessionId, long zxid) {
dataTree.killSession(sessionId, zxid);
}
/**
* write a text dump of all the ephemerals in the datatree
* @param pwriter the output to write to
*/
public void dumpEphemerals(PrintWriter pwriter) {
dataTree.dumpEphemerals(pwriter);
}
/**
* the node count of the datatree
* @return the node count of datatree
*/
public int getNodeCount() {
return dataTree.getNodeCount();
}
/**
* the paths for ephemeral session id
* @param sessionId the session id for which paths match to
* @return the paths for a session id
*/
public HashSet<String> getEphemerals(long sessionId) {
return dataTree.getEphemerals(sessionId);
}
/**
* the last processed zxid in the datatree
* @param zxid the last processed zxid in the datatree
*/
public void setlastProcessedZxid(long zxid) {
dataTree.lastProcessedZxid = zxid;
}
/**
* the process txn on the data
* @param hdr the txnheader for the txn
* @param txn the transaction that needs to be processed
* @return the result of processing the transaction on this
* datatree/zkdatabase
*/
public ProcessTxnResult processTxn(TxnHeader hdr, Record txn) {
return dataTree.processTxn(hdr, txn);
}
/**
* stat the path
* @param path the path for which stat is to be done
* @param serverCnxn the servercnxn attached to this request
* @return the stat of this node
* @throws KeeperException.NoNodeException
*/
public Stat statNode(String path, ServerCnxn serverCnxn) throws KeeperException.NoNodeException {
return dataTree.statNode(path, serverCnxn);
}
/**
* get the datanode for this path
* @param path the path to lookup
* @return the datanode for getting the path
*/
public DataNode getNode(String path) {
return dataTree.getNode(path);
}
/**
* convert from long to the acl entry
* @param aclL the long for which to get the acl
* @return the acl corresponding to this long entry
*/
public List<ACL> convertLong(Long aclL) {
return dataTree.convertLong(aclL);
}
/**
* get data and stat for a path
* @param path the path being queried
* @param stat the stat for this path
* @param watcher the watcher function
* @return
* @throws KeeperException.NoNodeException
*/
public byte[] getData(String path, Stat stat, Watcher watcher)
throws KeeperException.NoNodeException {
return dataTree.getData(path, stat, watcher);
}
/**
* set watches on the datatree
* @param relativeZxid the relative zxid that client has seen
* @param dataWatches the data watches the client wants to reset
* @param existWatches the exists watches the client wants to reset
* @param childWatches the child watches the client wants to reset
* @param watcher the watcher function
*/
public void setWatches(long relativeZxid, List<String> dataWatches,
List<String> existWatches, List<String> childWatches, Watcher watcher) {
dataTree.setWatches(relativeZxid, dataWatches, existWatches, childWatches, watcher);
}
/**
* get acl for a path
* @param path the path to query for acl
* @param stat the stat for the node
* @return the acl list for this path
* @throws NoNodeException
*/
public List<ACL> getACL(String path, Stat stat) throws NoNodeException {
return dataTree.getACL(path, stat);
}
/**
* get children list for this path
* @param path the path of the node
* @param stat the stat of the node
* @param watcher the watcher function for this path
* @return the list of children for this path
* @throws KeeperException.NoNodeException
*/
public List<String> getChildren(String path, Stat stat, Watcher watcher)
throws KeeperException.NoNodeException {
return dataTree.getChildren(path, stat, watcher);
}
/**
* check if the path is special or not
* @param path the input path
* @return true if path is special and false if not
*/
public boolean isSpecialPath(String path) {
return dataTree.isSpecialPath(path);
}
/**
* get the acl size of the datatree
* @return the acl size of the datatree
*/
public int getAclSize() {
return dataTree.longKeyMap.size();
}
/**
* deserialize a snapshot from an input archive
* @param ia the input archive you want to deserialize from
* @throws IOException
*/
public void deserializeSnapshot(InputArchive ia) throws IOException {
SerializeUtils.deserializeSnapshot(getDataTree(),ia,getSessionWithTimeOuts());
}
/**
* serialize the snapshot
* @param oa the output archive to which the snapshot needs to be serialized
* @throws IOException
* @throws InterruptedException
*/
public void serializeSnapshot(OutputArchive oa) throws IOException {
SerializeUtils.serializeSnapshot(getDataTree(), oa, getSessionWithTimeOuts());
}
}