Search in sources :

Example 1 with TxnHeader

use of org.apache.zookeeper.txn.TxnHeader in project zookeeper by apache.

the class PrepRequestProcessor method pRequest2Txn.

/**
     * This method will be called inside the ProcessRequestThread, which is a
     * singleton, so there will be a single thread calling this code.
     *
     * @param type
     * @param zxid
     * @param request
     * @param record
     */
protected void pRequest2Txn(int type, long zxid, Request request, Record record, boolean deserialize) throws KeeperException, IOException, RequestProcessorException {
    request.setHdr(new TxnHeader(request.sessionId, request.cxid, zxid, Time.currentWallTime(), type));
    switch(type) {
        case OpCode.create:
        case OpCode.create2:
        case OpCode.createTTL:
        case OpCode.createContainer:
            {
                pRequest2TxnCreate(type, request, record, deserialize);
                break;
            }
        case OpCode.deleteContainer:
            {
                String path = new String(request.request.array());
                String parentPath = getParentPathAndValidate(path);
                ChangeRecord parentRecord = getRecordForPath(parentPath);
                ChangeRecord nodeRecord = getRecordForPath(path);
                if (nodeRecord.childCount > 0) {
                    throw new KeeperException.NotEmptyException(path);
                }
                if (EphemeralType.get(nodeRecord.stat.getEphemeralOwner()) == EphemeralType.NORMAL) {
                    throw new KeeperException.BadVersionException(path);
                }
                request.setTxn(new DeleteTxn(path));
                parentRecord = parentRecord.duplicate(request.getHdr().getZxid());
                parentRecord.childCount--;
                addChangeRecord(parentRecord);
                addChangeRecord(new ChangeRecord(request.getHdr().getZxid(), path, null, -1, null));
                break;
            }
        case OpCode.delete:
            zks.sessionTracker.checkSession(request.sessionId, request.getOwner());
            DeleteRequest deleteRequest = (DeleteRequest) record;
            if (deserialize)
                ByteBufferInputStream.byteBuffer2Record(request.request, deleteRequest);
            String path = deleteRequest.getPath();
            String parentPath = getParentPathAndValidate(path);
            ChangeRecord parentRecord = getRecordForPath(parentPath);
            ChangeRecord nodeRecord = getRecordForPath(path);
            checkACL(zks, request.cnxn, parentRecord.acl, ZooDefs.Perms.DELETE, request.authInfo, path, null);
            checkAndIncVersion(nodeRecord.stat.getVersion(), deleteRequest.getVersion(), path);
            if (nodeRecord.childCount > 0) {
                throw new KeeperException.NotEmptyException(path);
            }
            request.setTxn(new DeleteTxn(path));
            parentRecord = parentRecord.duplicate(request.getHdr().getZxid());
            parentRecord.childCount--;
            addChangeRecord(parentRecord);
            addChangeRecord(new ChangeRecord(request.getHdr().getZxid(), path, null, -1, null));
            break;
        case OpCode.setData:
            zks.sessionTracker.checkSession(request.sessionId, request.getOwner());
            SetDataRequest setDataRequest = (SetDataRequest) record;
            if (deserialize)
                ByteBufferInputStream.byteBuffer2Record(request.request, setDataRequest);
            path = setDataRequest.getPath();
            validatePath(path, request.sessionId);
            nodeRecord = getRecordForPath(path);
            checkACL(zks, request.cnxn, nodeRecord.acl, ZooDefs.Perms.WRITE, request.authInfo, path, null);
            int newVersion = checkAndIncVersion(nodeRecord.stat.getVersion(), setDataRequest.getVersion(), path);
            request.setTxn(new SetDataTxn(path, setDataRequest.getData(), newVersion));
            nodeRecord = nodeRecord.duplicate(request.getHdr().getZxid());
            nodeRecord.stat.setVersion(newVersion);
            addChangeRecord(nodeRecord);
            break;
        case OpCode.reconfig:
            if (!QuorumPeerConfig.isReconfigEnabled()) {
                LOG.error("Reconfig operation requested but reconfig feature is disabled.");
                throw new KeeperException.ReconfigDisabledException();
            }
            if (skipACL) {
                LOG.warn("skipACL is set, reconfig operation will skip ACL checks!");
            }
            zks.sessionTracker.checkSession(request.sessionId, request.getOwner());
            ReconfigRequest reconfigRequest = (ReconfigRequest) record;
            LeaderZooKeeperServer lzks;
            try {
                lzks = (LeaderZooKeeperServer) zks;
            } catch (ClassCastException e) {
                // standalone mode - reconfiguration currently not supported
                throw new KeeperException.UnimplementedException();
            }
            QuorumVerifier lastSeenQV = lzks.self.getLastSeenQuorumVerifier();
            // check that there's no reconfig in progress
            if (lastSeenQV.getVersion() != lzks.self.getQuorumVerifier().getVersion()) {
                throw new KeeperException.ReconfigInProgress();
            }
            long configId = reconfigRequest.getCurConfigId();
            if (configId != -1 && configId != lzks.self.getLastSeenQuorumVerifier().getVersion()) {
                String msg = "Reconfiguration from version " + configId + " failed -- last seen version is " + lzks.self.getLastSeenQuorumVerifier().getVersion();
                throw new KeeperException.BadVersionException(msg);
            }
            String newMembers = reconfigRequest.getNewMembers();
            if (newMembers != null) {
                //non-incremental membership change                  
                LOG.info("Non-incremental reconfig");
                // Input may be delimited by either commas or newlines so convert to common newline separated format
                newMembers = newMembers.replaceAll(",", "\n");
                try {
                    Properties props = new Properties();
                    props.load(new StringReader(newMembers));
                    request.qv = QuorumPeerConfig.parseDynamicConfig(props, lzks.self.getElectionType(), true, false);
                    request.qv.setVersion(request.getHdr().getZxid());
                } catch (IOException e) {
                    throw new KeeperException.BadArgumentsException(e.getMessage());
                } catch (ConfigException e) {
                    throw new KeeperException.BadArgumentsException(e.getMessage());
                }
            } else {
                //incremental change - must be a majority quorum system   
                LOG.info("Incremental reconfig");
                List<String> joiningServers = null;
                String joiningServersString = reconfigRequest.getJoiningServers();
                if (joiningServersString != null) {
                    joiningServers = StringUtils.split(joiningServersString, ",");
                }
                List<String> leavingServers = null;
                String leavingServersString = reconfigRequest.getLeavingServers();
                if (leavingServersString != null) {
                    leavingServers = StringUtils.split(leavingServersString, ",");
                }
                if (!(lastSeenQV instanceof QuorumMaj)) {
                    String msg = "Incremental reconfiguration requested but last configuration seen has a non-majority quorum system";
                    LOG.warn(msg);
                    throw new KeeperException.BadArgumentsException(msg);
                }
                Map<Long, QuorumServer> nextServers = new HashMap<Long, QuorumServer>(lastSeenQV.getAllMembers());
                try {
                    if (leavingServers != null) {
                        for (String leaving : leavingServers) {
                            long sid = Long.parseLong(leaving);
                            nextServers.remove(sid);
                        }
                    }
                    if (joiningServers != null) {
                        for (String joiner : joiningServers) {
                            // joiner should have the following format: server.x = server_spec;client_spec               
                            String[] parts = StringUtils.split(joiner, "=").toArray(new String[0]);
                            if (parts.length != 2) {
                                throw new KeeperException.BadArgumentsException("Wrong format of server string");
                            }
                            // extract server id x from first part of joiner: server.x
                            Long sid = Long.parseLong(parts[0].substring(parts[0].lastIndexOf('.') + 1));
                            QuorumServer qs = new QuorumServer(sid, parts[1]);
                            if (qs.clientAddr == null || qs.electionAddr == null || qs.addr == null) {
                                throw new KeeperException.BadArgumentsException("Wrong format of server string - each server should have 3 ports specified");
                            }
                            // check duplication of addresses and ports
                            for (QuorumServer nqs : nextServers.values()) {
                                if (qs.id == nqs.id) {
                                    continue;
                                }
                                qs.checkAddressDuplicate(nqs);
                            }
                            nextServers.remove(qs.id);
                            nextServers.put(Long.valueOf(qs.id), qs);
                        }
                    }
                } catch (ConfigException e) {
                    throw new KeeperException.BadArgumentsException("Reconfiguration failed");
                }
                request.qv = new QuorumMaj(nextServers);
                request.qv.setVersion(request.getHdr().getZxid());
            }
            if (QuorumPeerConfig.isStandaloneEnabled() && request.qv.getVotingMembers().size() < 2) {
                String msg = "Reconfig failed - new configuration must include at least 2 followers";
                LOG.warn(msg);
                throw new KeeperException.BadArgumentsException(msg);
            } else if (request.qv.getVotingMembers().size() < 1) {
                String msg = "Reconfig failed - new configuration must include at least 1 follower";
                LOG.warn(msg);
                throw new KeeperException.BadArgumentsException(msg);
            }
            if (!lzks.getLeader().isQuorumSynced(request.qv)) {
                String msg2 = "Reconfig failed - there must be a connected and synced quorum in new configuration";
                LOG.warn(msg2);
                throw new KeeperException.NewConfigNoQuorum();
            }
            nodeRecord = getRecordForPath(ZooDefs.CONFIG_NODE);
            checkACL(zks, request.cnxn, nodeRecord.acl, ZooDefs.Perms.WRITE, request.authInfo, null, null);
            request.setTxn(new SetDataTxn(ZooDefs.CONFIG_NODE, request.qv.toString().getBytes(), -1));
            nodeRecord = nodeRecord.duplicate(request.getHdr().getZxid());
            nodeRecord.stat.setVersion(-1);
            addChangeRecord(nodeRecord);
            break;
        case OpCode.setACL:
            zks.sessionTracker.checkSession(request.sessionId, request.getOwner());
            SetACLRequest setAclRequest = (SetACLRequest) record;
            if (deserialize)
                ByteBufferInputStream.byteBuffer2Record(request.request, setAclRequest);
            path = setAclRequest.getPath();
            validatePath(path, request.sessionId);
            List<ACL> listACL = fixupACL(path, request.authInfo, setAclRequest.getAcl());
            nodeRecord = getRecordForPath(path);
            checkACL(zks, request.cnxn, nodeRecord.acl, ZooDefs.Perms.ADMIN, request.authInfo, path, listACL);
            newVersion = checkAndIncVersion(nodeRecord.stat.getAversion(), setAclRequest.getVersion(), path);
            request.setTxn(new SetACLTxn(path, listACL, newVersion));
            nodeRecord = nodeRecord.duplicate(request.getHdr().getZxid());
            nodeRecord.stat.setAversion(newVersion);
            addChangeRecord(nodeRecord);
            break;
        case OpCode.createSession:
            request.request.rewind();
            int to = request.request.getInt();
            request.setTxn(new CreateSessionTxn(to));
            request.request.rewind();
            if (request.isLocalSession()) {
                // This will add to local session tracker if it is enabled
                zks.sessionTracker.addSession(request.sessionId, to);
            } else {
                // Explicitly add to global session if the flag is not set
                zks.sessionTracker.addGlobalSession(request.sessionId, to);
            }
            zks.setOwner(request.sessionId, request.getOwner());
            break;
        case OpCode.closeSession:
            // We don't want to do this check since the session expiration thread
            // queues up this operation without being the session owner.
            // this request is the last of the session so it should be ok
            //zks.sessionTracker.checkSession(request.sessionId, request.getOwner());
            Set<String> es = zks.getZKDatabase().getEphemerals(request.sessionId);
            synchronized (zks.outstandingChanges) {
                for (ChangeRecord c : zks.outstandingChanges) {
                    if (c.stat == null) {
                        // Doing a delete
                        es.remove(c.path);
                    } else if (c.stat.getEphemeralOwner() == request.sessionId) {
                        es.add(c.path);
                    }
                }
                for (String path2Delete : es) {
                    addChangeRecord(new ChangeRecord(request.getHdr().getZxid(), path2Delete, null, 0, null));
                }
                zks.sessionTracker.setSessionClosing(request.sessionId);
            }
            LOG.info("Processed session termination for sessionid: 0x" + Long.toHexString(request.sessionId));
            break;
        case OpCode.check:
            zks.sessionTracker.checkSession(request.sessionId, request.getOwner());
            CheckVersionRequest checkVersionRequest = (CheckVersionRequest) record;
            if (deserialize)
                ByteBufferInputStream.byteBuffer2Record(request.request, checkVersionRequest);
            path = checkVersionRequest.getPath();
            validatePath(path, request.sessionId);
            nodeRecord = getRecordForPath(path);
            checkACL(zks, request.cnxn, nodeRecord.acl, ZooDefs.Perms.READ, request.authInfo, path, null);
            request.setTxn(new CheckVersionTxn(path, checkAndIncVersion(nodeRecord.stat.getVersion(), checkVersionRequest.getVersion(), path)));
            break;
        default:
            LOG.warn("unknown type " + type);
            break;
    }
}
Also used : CheckVersionRequest(org.apache.zookeeper.proto.CheckVersionRequest) HashMap(java.util.HashMap) QuorumServer(org.apache.zookeeper.server.quorum.QuorumPeer.QuorumServer) QuorumMaj(org.apache.zookeeper.server.quorum.flexible.QuorumMaj) ConfigException(org.apache.zookeeper.server.quorum.QuorumPeerConfig.ConfigException) Properties(java.util.Properties) ReconfigRequest(org.apache.zookeeper.proto.ReconfigRequest) DeleteTxn(org.apache.zookeeper.txn.DeleteTxn) CreateSessionTxn(org.apache.zookeeper.txn.CreateSessionTxn) BadArgumentsException(org.apache.zookeeper.KeeperException.BadArgumentsException) StringReader(java.io.StringReader) SetACLRequest(org.apache.zookeeper.proto.SetACLRequest) CheckVersionTxn(org.apache.zookeeper.txn.CheckVersionTxn) ACL(org.apache.zookeeper.data.ACL) SetDataRequest(org.apache.zookeeper.proto.SetDataRequest) SetDataTxn(org.apache.zookeeper.txn.SetDataTxn) IOException(java.io.IOException) QuorumVerifier(org.apache.zookeeper.server.quorum.flexible.QuorumVerifier) BadArgumentsException(org.apache.zookeeper.KeeperException.BadArgumentsException) SetACLTxn(org.apache.zookeeper.txn.SetACLTxn) ChangeRecord(org.apache.zookeeper.server.ZooKeeperServer.ChangeRecord) DeleteRequest(org.apache.zookeeper.proto.DeleteRequest) KeeperException(org.apache.zookeeper.KeeperException) TxnHeader(org.apache.zookeeper.txn.TxnHeader) LeaderZooKeeperServer(org.apache.zookeeper.server.quorum.LeaderZooKeeperServer)

Example 2 with TxnHeader

use of org.apache.zookeeper.txn.TxnHeader in project zookeeper by apache.

the class Observer method processPacket.

/**
     * Controls the response of an observer to the receipt of a quorumpacket
     * @param qp
     * @throws Exception 
     */
protected void processPacket(QuorumPacket qp) throws Exception {
    switch(qp.getType()) {
        case Leader.PING:
            ping(qp);
            break;
        case Leader.PROPOSAL:
            LOG.warn("Ignoring proposal");
            break;
        case Leader.COMMIT:
            LOG.warn("Ignoring commit");
            break;
        case Leader.UPTODATE:
            LOG.error("Received an UPTODATE message after Observer started");
            break;
        case Leader.REVALIDATE:
            revalidate(qp);
            break;
        case Leader.SYNC:
            ((ObserverZooKeeperServer) zk).sync();
            break;
        case Leader.INFORM:
            TxnHeader hdr = new TxnHeader();
            Record txn = SerializeUtils.deserializeTxn(qp.getData(), hdr);
            Request request = new Request(hdr.getClientId(), hdr.getCxid(), hdr.getType(), hdr, txn, 0);
            ObserverZooKeeperServer obs = (ObserverZooKeeperServer) zk;
            obs.commitRequest(request);
            break;
        case Leader.INFORMANDACTIVATE:
            hdr = new TxnHeader();
            // get new designated leader from (current) leader's message
            ByteBuffer buffer = ByteBuffer.wrap(qp.getData());
            long suggestedLeaderId = buffer.getLong();
            byte[] remainingdata = new byte[buffer.remaining()];
            buffer.get(remainingdata);
            txn = SerializeUtils.deserializeTxn(remainingdata, hdr);
            QuorumVerifier qv = self.configFromString(new String(((SetDataTxn) txn).getData()));
            request = new Request(hdr.getClientId(), hdr.getCxid(), hdr.getType(), hdr, txn, 0);
            obs = (ObserverZooKeeperServer) zk;
            boolean majorChange = self.processReconfig(qv, suggestedLeaderId, qp.getZxid(), true);
            obs.commitRequest(request);
            if (majorChange) {
                throw new Exception("changes proposed in reconfig");
            }
            break;
        default:
            LOG.warn("Unknown packet type: {}", LearnerHandler.packetToString(qp));
            break;
    }
}
Also used : Request(org.apache.zookeeper.server.Request) Record(org.apache.jute.Record) SetDataTxn(org.apache.zookeeper.txn.SetDataTxn) ByteBuffer(java.nio.ByteBuffer) QuorumVerifier(org.apache.zookeeper.server.quorum.flexible.QuorumVerifier) IOException(java.io.IOException) TxnHeader(org.apache.zookeeper.txn.TxnHeader)

Example 3 with TxnHeader

use of org.apache.zookeeper.txn.TxnHeader in project zookeeper by apache.

the class ZKDatabase method loadDataBase.

/**
     * load the database from the disk onto memory and also add
     * the transactions to the committedlog in memory.
     * @return the last valid zxid on disk
     * @throws IOException
     */
public long loadDataBase() throws IOException {
    PlayBackListener listener = new PlayBackListener() {

        public void onTxnLoaded(TxnHeader hdr, Record txn) {
            Request r = new Request(0, hdr.getCxid(), hdr.getType(), hdr, txn, hdr.getZxid());
            addCommittedProposal(r);
        }
    };
    long zxid = snapLog.restore(dataTree, sessionsWithTimeouts, listener);
    initialized = true;
    return zxid;
}
Also used : PlayBackListener(org.apache.zookeeper.server.persistence.FileTxnSnapLog.PlayBackListener) Record(org.apache.jute.Record) TxnHeader(org.apache.zookeeper.txn.TxnHeader)

Example 4 with TxnHeader

use of org.apache.zookeeper.txn.TxnHeader in project zookeeper by apache.

the class LearnerTest method syncTest.

@Test
public void syncTest() throws Exception {
    File tmpFile = File.createTempFile("test", ".dir", testData);
    tmpFile.delete();
    try {
        FileTxnSnapLog ftsl = new FileTxnSnapLog(tmpFile, tmpFile);
        SimpleLearner sl = new SimpleLearner(ftsl);
        long startZxid = sl.zk.getLastProcessedZxid();
        // Set up bogus streams
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        BinaryOutputArchive oa = BinaryOutputArchive.getArchive(baos);
        sl.leaderOs = BinaryOutputArchive.getArchive(new ByteArrayOutputStream());
        // make streams and socket do something innocuous
        sl.bufferedOutput = new BufferedOutputStream(System.out);
        sl.sock = new Socket();
        // fake messages from the server
        QuorumPacket qp = new QuorumPacket(Leader.SNAP, 0, null, null);
        oa.writeRecord(qp, null);
        sl.zk.getZKDatabase().serializeSnapshot(oa);
        oa.writeString("BenWasHere", "signature");
        TxnHeader hdr = new TxnHeader(0, 0, 0, 0, ZooDefs.OpCode.create);
        CreateTxn txn = new CreateTxn("/foo", new byte[0], new ArrayList<ACL>(), false, sl.zk.getZKDatabase().getNode("/").stat.getCversion());
        ByteArrayOutputStream tbaos = new ByteArrayOutputStream();
        BinaryOutputArchive boa = BinaryOutputArchive.getArchive(tbaos);
        hdr.serialize(boa, "hdr");
        txn.serialize(boa, "txn");
        tbaos.close();
        qp = new QuorumPacket(Leader.PROPOSAL, 1, tbaos.toByteArray(), null);
        oa.writeRecord(qp, null);
        // setup the messages to be streamed to follower
        sl.leaderIs = BinaryInputArchive.getArchive(new ByteArrayInputStream(baos.toByteArray()));
        try {
            sl.syncWithLeader(3);
        } catch (EOFException e) {
        }
        sl.zk.shutdown();
        sl = new SimpleLearner(ftsl);
        Assert.assertEquals(startZxid, sl.zk.getLastProcessedZxid());
    } finally {
        TestUtils.deleteFileRecursively(tmpFile);
    }
}
Also used : BinaryOutputArchive(org.apache.jute.BinaryOutputArchive) ACL(org.apache.zookeeper.data.ACL) ByteArrayOutputStream(java.io.ByteArrayOutputStream) FileTxnSnapLog(org.apache.zookeeper.server.persistence.FileTxnSnapLog) CreateTxn(org.apache.zookeeper.txn.CreateTxn) ByteArrayInputStream(java.io.ByteArrayInputStream) EOFException(java.io.EOFException) File(java.io.File) BufferedOutputStream(java.io.BufferedOutputStream) Socket(java.net.Socket) TxnHeader(org.apache.zookeeper.txn.TxnHeader) Test(org.junit.Test)

Example 5 with TxnHeader

use of org.apache.zookeeper.txn.TxnHeader in project zookeeper by apache.

the class FileTxnSnapLogTest method attemptAutoCreateDb.

private void attemptAutoCreateDb(File dataDir, File snapDir, Map<Long, Integer> sessions, String priorAutocreateDbValue, String autoCreateValue, long expectedValue) throws IOException {
    sessions.clear();
    System.setProperty(FileTxnSnapLog.ZOOKEEPER_DB_AUTOCREATE, autoCreateValue);
    FileTxnSnapLog fileTxnSnapLog = new FileTxnSnapLog(dataDir, snapDir);
    try {
        long zxid = fileTxnSnapLog.restore(new DataTree(), sessions, new FileTxnSnapLog.PlayBackListener() {

            @Override
            public void onTxnLoaded(TxnHeader hdr, Record rec) {
            // empty by default
            }
        });
        Assert.assertEquals("unexpected zxid", expectedValue, zxid);
    } finally {
        if (priorAutocreateDbValue == null) {
            System.clearProperty(FileTxnSnapLog.ZOOKEEPER_DB_AUTOCREATE);
        } else {
            System.setProperty(FileTxnSnapLog.ZOOKEEPER_DB_AUTOCREATE, priorAutocreateDbValue);
        }
    }
}
Also used : DataTree(org.apache.zookeeper.server.DataTree) Record(org.apache.jute.Record) TxnHeader(org.apache.zookeeper.txn.TxnHeader)

Aggregations

TxnHeader (org.apache.zookeeper.txn.TxnHeader)24 Record (org.apache.jute.Record)15 IOException (java.io.IOException)13 File (java.io.File)9 SetDataTxn (org.apache.zookeeper.txn.SetDataTxn)8 ByteBuffer (java.nio.ByteBuffer)7 CreateTxn (org.apache.zookeeper.txn.CreateTxn)6 Test (org.junit.Test)6 BinaryOutputArchive (org.apache.jute.BinaryOutputArchive)5 KeeperException (org.apache.zookeeper.KeeperException)5 Request (org.apache.zookeeper.server.Request)5 ByteArrayOutputStream (java.io.ByteArrayOutputStream)4 BinaryInputArchive (org.apache.jute.BinaryInputArchive)4 Stat (org.apache.zookeeper.data.Stat)4 ZKDatabase (org.apache.zookeeper.server.ZKDatabase)4 FileTxnSnapLog (org.apache.zookeeper.server.persistence.FileTxnSnapLog)4 QuorumVerifier (org.apache.zookeeper.server.quorum.flexible.QuorumVerifier)4 ByteArrayInputStream (java.io.ByteArrayInputStream)3 EOFException (java.io.EOFException)3 ArrayList (java.util.ArrayList)3