/** * 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()); } }