Search in sources :

Example 1 with VersionChecker

use of org.voltcore.utils.VersionChecker in project voltdb by VoltDB.

the class SocketJoiner method processSSC.

/*
     * Pull all ready to accept sockets
     */
private void processSSC(ServerSocketChannel ssc) throws Exception {
    SocketChannel sc = null;
    while ((sc = ssc.accept()) != null) {
        try {
            sc.socket().setTcpNoDelay(true);
            sc.socket().setPerformancePreferences(0, 2, 1);
            final String remoteAddress = sc.socket().getRemoteSocketAddress().toString();
            /*
                 * Send the current time over the new connection for a clock skew check
                 */
            ByteBuffer currentTimeBuf = ByteBuffer.allocate(8);
            currentTimeBuf.putLong(System.currentTimeMillis());
            currentTimeBuf.flip();
            while (currentTimeBuf.hasRemaining()) {
                sc.write(currentTimeBuf);
            }
            /*
                 * Read a length prefixed JSON message
                 */
            JSONObject jsObj = readJSONObjFromWire(sc, remoteAddress);
            LOG.info(jsObj.toString(2));
            // get the connecting node's version string
            String remoteBuildString = jsObj.getString(VERSION_STRING);
            VersionChecker versionChecker = m_acceptor.getVersionChecker();
            // send a response with version/build data of this node
            JSONObject returnJs = new JSONObject();
            returnJs.put(VERSION_STRING, versionChecker.getVersionString());
            returnJs.put(BUILD_STRING, versionChecker.getBuildString());
            returnJs.put(VERSION_COMPATIBLE, versionChecker.isCompatibleVersionString(remoteBuildString));
            // inject acceptor fields
            m_acceptor.decorate(returnJs, Optional.of(m_paused.get()));
            byte[] jsBytes = returnJs.toString(4).getBytes(StandardCharsets.UTF_8);
            ByteBuffer returnJsBuffer = ByteBuffer.allocate(4 + jsBytes.length);
            returnJsBuffer.putInt(jsBytes.length);
            returnJsBuffer.put(jsBytes).flip();
            while (returnJsBuffer.hasRemaining()) {
                sc.write(returnJsBuffer);
            }
            /*
                 * The type of connection, it can be a new request to join the cluster
                 * or a node that is connecting to the rest of the cluster and publishing its
                 * host id or a request to add a new connection to the request node.
                 */
            String type = jsObj.getString(TYPE);
            /*
                 * The new connection may specify the address it is listening on,
                 * or it can be derived from the connection itself
                 */
            InetSocketAddress listeningAddress;
            if (jsObj.has(ADDRESS)) {
                listeningAddress = new InetSocketAddress(InetAddress.getByName(jsObj.getString(ADDRESS)), jsObj.getInt(PORT));
            } else {
                listeningAddress = new InetSocketAddress(((InetSocketAddress) sc.socket().getRemoteSocketAddress()).getAddress().getHostAddress(), jsObj.getInt(PORT));
            }
            hostLog.info("Received request type " + type);
            if (type.equals(ConnectionType.REQUEST_HOSTID.name())) {
                m_joinHandler.requestJoin(sc, listeningAddress, jsObj);
            } else if (type.equals(ConnectionType.PUBLISH_HOSTID.name())) {
                m_joinHandler.notifyOfJoin(jsObj.getInt(HOST_ID), sc, listeningAddress, jsObj);
            } else if (type.equals(ConnectionType.REQUEST_CONNECTION.name())) {
                m_joinHandler.notifyOfConnection(jsObj.getInt(HOST_ID), sc, listeningAddress);
            } else {
                throw new RuntimeException("Unexpected message type " + type + " from " + remoteAddress);
            }
        } catch (Exception ex) {
            // do not leak sockets when exception happens
            try {
                sc.close();
            } catch (IOException ioex) {
            // ignore the close exception on purpose
            }
            // re-throw the exception, it will be handled by the caller
            throw ex;
        }
    }
}
Also used : SocketChannel(java.nio.channels.SocketChannel) ServerSocketChannel(java.nio.channels.ServerSocketChannel) VersionChecker(org.voltcore.utils.VersionChecker) JSONObject(org.json_voltpatches.JSONObject) InetSocketAddress(java.net.InetSocketAddress) IOException(java.io.IOException) ByteBuffer(java.nio.ByteBuffer) IOException(java.io.IOException) EOFException(java.io.EOFException) JSONException(org.json_voltpatches.JSONException) ClosedByInterruptException(java.nio.channels.ClosedByInterruptException) ClosedSelectorException(java.nio.channels.ClosedSelectorException)

Example 2 with VersionChecker

use of org.voltcore.utils.VersionChecker in project voltdb by VoltDB.

the class SocketJoiner method processJSONResponse.

/**
     * Read version info from a socket and check compatibility.
     * After verifying versions return if "paused" start is indicated. True if paused start otherwise normal start.
     */
private JSONObject processJSONResponse(SocketChannel sc, String remoteAddress, Set<String> activeVersions, boolean checkVersion) throws IOException, JSONException {
    // read the json response from socketjoiner with version info
    JSONObject jsonResponse = readJSONObjFromWire(sc, remoteAddress);
    if (!checkVersion) {
        return jsonResponse;
    }
    VersionChecker versionChecker = m_acceptor.getVersionChecker();
    String remoteVersionString = jsonResponse.getString(VERSION_STRING);
    String remoteBuildString = jsonResponse.getString(BUILD_STRING);
    boolean remoteAcceptsLocalVersion = jsonResponse.getBoolean(VERSION_COMPATIBLE);
    if (remoteVersionString.equals(versionChecker.getVersionString())) {
        if (!versionChecker.getBuildString().equals(remoteBuildString)) {
            // ignore test/eclipse build string so tests still work
            if (!versionChecker.getBuildString().equals("VoltDB") && !remoteBuildString.equals("VoltDB")) {
                org.voltdb.VoltDB.crashLocalVoltDB("For VoltDB version " + versionChecker.getVersionString() + " git tag/hash is not identical across the cluster. Node join failed.\n" + "  joining build string:  " + versionChecker.getBuildString() + "\n" + "  existing build string: " + remoteBuildString, false, null);
                return null;
            }
        }
    } else if (!remoteAcceptsLocalVersion) {
        if (!versionChecker.isCompatibleVersionString(remoteVersionString)) {
            org.voltdb.VoltDB.crashLocalVoltDB("Cluster contains nodes running VoltDB version " + remoteVersionString + " which is incompatibile with local version " + versionChecker.getVersionString() + ".\n", false, null);
            return null;
        }
    }
    //Do this only after we think we are compatible.
    activeVersions.add(remoteVersionString);
    return jsonResponse;
}
Also used : VersionChecker(org.voltcore.utils.VersionChecker) JSONObject(org.json_voltpatches.JSONObject)

Example 3 with VersionChecker

use of org.voltcore.utils.VersionChecker in project voltdb by VoltDB.

the class SocketJoiner method requestHostId.

/**
     * Connection handshake to the leader, ask the leader to assign a host Id
     * for current node.
     * @param
     * @return array of two JSON objects, first is leader info, second is
     *         the response to our request
     * @throws Exception
     */
private RequestHostIdResponse requestHostId(SocketChannel socket, List<Long> skews, Set<String> activeVersions) throws Exception {
    // Read the timestamp off the wire and calculate skew for this connection
    ByteBuffer currentTimeBuf = ByteBuffer.allocate(8);
    while (currentTimeBuf.hasRemaining()) {
        socket.read(currentTimeBuf);
    }
    currentTimeBuf.flip();
    long skew = System.currentTimeMillis() - currentTimeBuf.getLong();
    skews.add(skew);
    VersionChecker versionChecker = m_acceptor.getVersionChecker();
    activeVersions.add(versionChecker.getVersionString());
    JSONObject jsObj = new JSONObject();
    jsObj.put(TYPE, ConnectionType.REQUEST_HOSTID.name());
    // put the version compatibility status in the json
    jsObj.put(VERSION_STRING, versionChecker.getVersionString());
    // Advertise the port we are going to listen on based on config
    jsObj.put(PORT, m_internalPort);
    // Otherwise the leader will echo back what we connected on
    if (!m_internalInterface.isEmpty()) {
        jsObj.put(ADDRESS, m_internalInterface);
    }
    // communicate configuration and node state
    m_acceptor.decorate(jsObj, Optional.empty());
    jsObj.put(MAY_EXCHANGE_TS, true);
    byte[] jsBytes = jsObj.toString(4).getBytes(StandardCharsets.UTF_8);
    ByteBuffer requestHostIdBuffer = ByteBuffer.allocate(4 + jsBytes.length);
    requestHostIdBuffer.putInt(jsBytes.length);
    requestHostIdBuffer.put(jsBytes).flip();
    while (requestHostIdBuffer.hasRemaining()) {
        socket.write(requestHostIdBuffer);
    }
    final String primaryAddress = socket.socket().getRemoteSocketAddress().toString();
    // read the json response from socketjoiner with version info and validate it
    JSONObject leaderInfo = processJSONResponse(socket, primaryAddress, activeVersions, true);
    // read the json response sent by HostMessenger with HostID
    JSONObject jsonObj = readJSONObjFromWire(socket, primaryAddress);
    return new RequestHostIdResponse(leaderInfo, jsonObj);
}
Also used : VersionChecker(org.voltcore.utils.VersionChecker) JSONObject(org.json_voltpatches.JSONObject) ByteBuffer(java.nio.ByteBuffer)

Aggregations

JSONObject (org.json_voltpatches.JSONObject)3 VersionChecker (org.voltcore.utils.VersionChecker)3 ByteBuffer (java.nio.ByteBuffer)2 EOFException (java.io.EOFException)1 IOException (java.io.IOException)1 InetSocketAddress (java.net.InetSocketAddress)1 ClosedByInterruptException (java.nio.channels.ClosedByInterruptException)1 ClosedSelectorException (java.nio.channels.ClosedSelectorException)1 ServerSocketChannel (java.nio.channels.ServerSocketChannel)1 SocketChannel (java.nio.channels.SocketChannel)1 JSONException (org.json_voltpatches.JSONException)1