com.tesora.dve.tools.libmy.AsyncExample.java Source code

Java tutorial

Introduction

Here is the source code for com.tesora.dve.tools.libmy.AsyncExample.java

Source

package com.tesora.dve.tools.libmy;

/*
 * #%L
 * Tesora Inc.
 * Database Virtualization Engine
 * %%
 * Copyright (C) 2011 - 2014 Tesora Inc.
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License, version 3,
 * as published by the Free Software Foundation.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 * #L%
 */

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.UnpooledByteBufAllocator;
import io.netty.channel.Channel;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPromise;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.CharsetUtil;

import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

import com.tesora.dve.db.mysql.MyFieldType;
import com.tesora.dve.db.mysql.common.JavaCharsetCatalog;
import com.tesora.dve.db.mysql.common.SimpleCredentials;
import com.tesora.dve.db.mysql.libmy.MyFieldPktResponse;
import com.tesora.dve.db.mysql.libmy.MyTextResultRow;
import com.tesora.dve.db.mysql.portal.protocol.ClientCapabilities;
import com.tesora.dve.db.mysql.portal.protocol.MSPComQueryRequestMessage;
import com.tesora.dve.db.mysql.portal.protocol.MSPComQuitRequestMessage;
import com.tesora.dve.db.mysql.portal.protocol.MyBackendDecoder;
import com.tesora.dve.db.mysql.portal.protocol.MysqlClientAuthenticationHandler;

public class AsyncExample {

    public static void main(String[] args) throws Exception {
        final String mysqlHost = "localhost";
        final int mysqlPort = 3307;
        final String username = "root";
        final String password = "password";
        final boolean isClearText = true;

        final InetSocketAddress serverAddress = new InetSocketAddress(mysqlHost, mysqlPort);

        final MyBackendDecoder.CharsetDecodeHelper charsetHelper = constructCharsetDecodeHelper();
        final SimpleCredentials cred = constructCredentials(username, password, isClearText);
        final JavaCharsetCatalog javaCharsetCatalog = constructJavaCharsetCatalog();
        final MysqlClientAuthenticationHandler authHandler = new MysqlClientAuthenticationHandler(cred,
                ClientCapabilities.DEFAULT_PSITE_CAPABILITIES, javaCharsetCatalog, new AtomicReference<Charset>());

        final NioEventLoopGroup connectionEventGroup = new NioEventLoopGroup(1);
        final Bootstrap mysqlBootstrap = new Bootstrap();
        mysqlBootstrap // .group(inboundChannel.eventLoop())
                .channel(NioSocketChannel.class).group(connectionEventGroup)
                .option(ChannelOption.ALLOCATOR, UnpooledByteBufAllocator.DEFAULT)
                .handler(new ChannelInitializer<Channel>() {
                    @Override
                    protected void initChannel(Channel ch) throws Exception {

                        ch.pipeline().addLast(authHandler).addLast(MyBackendDecoder.class.getSimpleName(),
                                new MyBackendDecoder(charsetHelper)).addLast(new ChannelDuplexHandler() {

                                    @Override
                                    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise)
                                            throws Exception {
                                        System.out.println("WRITE:" + msg);
                                        super.write(ctx, msg, promise);
                                    }

                                    @Override
                                    public void channelRead(ChannelHandlerContext ctx, Object msg)
                                            throws Exception {
                                        if (msg instanceof MyFieldPktResponse) {
                                            final MyFieldPktResponse myFieldPktResponse = (MyFieldPktResponse) msg;
                                            System.out.println("COLUMN: " + myFieldPktResponse.getOrig_column()
                                                    + "," + myFieldPktResponse.getColumn_type());
                                        } else if (msg instanceof MyTextResultRow) {
                                            final StringBuilder builder = new StringBuilder();
                                            builder.append("ROW:");
                                            final MyTextResultRow textRow = (MyTextResultRow) msg;
                                            for (int i = 0; i < textRow.size(); i++) {
                                                builder.append('\t');
                                                builder.append(textRow.getString(i));
                                            }
                                            System.out.println(builder.toString());
                                        }
                                        super.channelRead(ctx, msg);
                                    }

                                    @Override
                                    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
                                        super.channelInactive(ctx);
                                        System.out.println("CLOSE. ");
                                    }
                                });
                    }
                });

        final ChannelFuture connectFut = mysqlBootstrap.connect(serverAddress);
        connectFut.sync();
        System.out.println("Waiting to finish authenticate handshake");

        authHandler.assertAuthenticated();//don't write a request until you know the login is complete.

        System.out.println("Connected, and authenticated, getting channel to write requests");

        final Channel chan = connectFut.channel();

        System.out.println("Sending two pipelined requests without blocking for first response.");

        chan.write(MSPComQueryRequestMessage.newMessage("show databases", CharsetUtil.UTF_8));
        chan.write(
                MSPComQueryRequestMessage.newMessage("select * from information_schema.tables", CharsetUtil.UTF_8));
        chan.flush();//NOTE:  nothing is sent until this is called.  Use writeAndFlush if you want it to go out immediately.

        System.out.println("Sleeping 5 sec so all results come back"); //normally you would sync to responses here.
        TimeUnit.SECONDS.sleep(5);
        System.out.println("Closing socket.");
        chan.writeAndFlush(MSPComQuitRequestMessage.newMessage());//send friendly hangup message. Probably correct to also wait for server close or an OK packet.

        chan.close();
        chan.closeFuture().sync();
        System.out.println("Exiting.");
        System.exit(0);
    }

    protected static JavaCharsetCatalog constructJavaCharsetCatalog() {
        return new JavaCharsetCatalog() {
            @Override
            public Charset findJavaCharsetById(int clientCharsetId) {
                if (clientCharsetId == 33) {
                    return CharsetUtil.UTF_8;
                } else if (clientCharsetId == 8) {
                    return CharsetUtil.ISO_8859_1;
                } else {
                    return null;
                }
            }
        };
    }

    protected static SimpleCredentials constructCredentials(final String username, final String password,
            final boolean isClearText) {
        return new SimpleCredentials() {
            @Override
            public String getName() {
                return username;
            }

            @Override
            public String getPassword() {
                return password;
            }

            @Override
            public boolean isCleartext() {
                return isClearText;
            }
        };
    }

    protected static MyBackendDecoder.CharsetDecodeHelper constructCharsetDecodeHelper() {
        return new MyBackendDecoder.CharsetDecodeHelper() {

            @Override
            public long lookupMaxLength(byte mysqlCharsetID) {
                if (mysqlCharsetID == 33) {
                    return 3;
                } else if (mysqlCharsetID == 8) {
                    return 1;
                } else {
                    return -1;
                }
            }

            @Override
            public boolean typeSupported(MyFieldType fieldType, short flags, int maxDataLen) {
                return true;
            }
        };
    }
}