// Path: modbus-examples/src/main/java/com/digitalpetri/modbus/examples/master/MasterExample.java
// public class MasterExample {
// 
//     public static void main(String[] args) {
//         new MasterExample(100, 100).start();
//     }
// 
//     private final Logger logger = LoggerFactory.getLogger(getClass());
// 
//     private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
// 
//     private final List<ModbusTcpMaster> masters = new CopyOnWriteArrayList<>();
//     private volatile boolean started = false;
// 
//     private final int nMasters;
//     private final int nRequests;
// 
//     public MasterExample(int nMasters, int nRequests) {
//         this.nMasters = nMasters;
//         this.nRequests = nRequests;
//     }
// 
//     public void start() {
//         started = true;
// 
//         ModbusTcpMasterConfig config = new ModbusTcpMasterConfig.Builder("localhost")
//             .setPort(50200)
//             .build();
// 
//         new Thread(() -> {
//             while (started) {
//                 try {
//                     Thread.sleep(5000);
//                 } catch (InterruptedException e) {
//                     e.printStackTrace();
//                 }
// 
//                 double mean = 0.0;
//                 double oneMinute = 0.0;
// 
//                 for (ModbusTcpMaster master : masters) {
//                     mean += master.getResponseTimer().getMeanRate();
//                     oneMinute += master.getResponseTimer().getOneMinuteRate();
//                 }
// 
//                 logger.info("Mean rate={}, 1m rate={}", mean, oneMinute);
//             }
//         }).start();
// 
//         for (int i = 0; i < nMasters; i++) {
//             ModbusTcpMaster master = new ModbusTcpMaster(config);
//             master.connect();
// 
//             masters.add(master);
// 
//             for (int j = 0; j < nRequests; j++) {
//                 sendAndReceive(master);
//             }
//         }
//     }
// 
//     private void sendAndReceive(ModbusTcpMaster master) {
//         if (!started) return;
// 
//         CompletableFuture<ReadHoldingRegistersResponse> future =
//             master.sendRequest(new ReadHoldingRegistersRequest(0, 10), 0);
// 
//         future.whenCompleteAsync((response, ex) -> {
//             if (response != null) {
//                 ReferenceCountUtil.release(response);
//             } else {
//                 logger.error("Completed exceptionally, message={}", ex.getMessage(), ex);
//             }
//             scheduler.schedule(() -> sendAndReceive(master), 1, TimeUnit.SECONDS);
//         }, Modbus.sharedExecutor());
//     }
// 
//     public void stop() {
//         started = false;
//         masters.forEach(ModbusTcpMaster::disconnect);
//         masters.clear();
//     }
// 
// }
// 
// Path: modbus-examples/src/main/java/com/digitalpetri/modbus/examples/slave/SlaveExample.java
// public class SlaveExample {
// 
//     public static void main(String[] args) throws ExecutionException, InterruptedException {
//         final SlaveExample slaveExample = new SlaveExample();
// 
//         slaveExample.start();
// 
//         Runtime.getRuntime().addShutdownHook(new Thread("modbus-slave-shutdown-hook") {
//             @Override
//             public void run() {
//                 slaveExample.stop();
//             }
//         });
// 
//         Thread.sleep(Integer.MAX_VALUE);
//     }
// 
//     private final Logger logger = LoggerFactory.getLogger(getClass());
// 
//     private final ModbusTcpSlaveConfig config = new ModbusTcpSlaveConfig.Builder().build();
//     private final ModbusTcpSlave slave = new ModbusTcpSlave(config);
// 
//     public SlaveExample() {}
// 
//     public void start() throws ExecutionException, InterruptedException {
//         slave.setRequestHandler(new ServiceRequestHandler() {
//             @Override
//             public void onReadHoldingRegisters(ServiceRequest<ReadHoldingRegistersRequest, ReadHoldingRegistersResponse> service) {
//                 String clientRemoteAddress = service.getChannel().remoteAddress().toString();
//                 String clientIp = clientRemoteAddress.replaceAll(".*/(.*):.*", "$1");
//                 String clientPort = clientRemoteAddress.replaceAll(".*:(.*)", "$1");
// 
//                 ReadHoldingRegistersRequest request = service.getRequest();
// 
//                 ByteBuf registers = PooledByteBufAllocator.DEFAULT.buffer(request.getQuantity());
// 
//                 for (int i = 0; i < request.getQuantity(); i++) {
//                     registers.writeShort(i);
//                 }
// 
//                 service.sendResponse(new ReadHoldingRegistersResponse(registers));
// 
//                 ReferenceCountUtil.release(request);
//             }
//         });
// 
//         slave.bind("localhost", 50200).get();
//     }
// 
//     public void stop() {
//         slave.shutdown();
//     }
// 
// }


import java.util.concurrent.ExecutionException;
import com.digitalpetri.modbus.examples.master.MasterExample;
import com.digitalpetri.modbus.examples.slave.SlaveExample;
/*
 * Copyright 2016 Kevin Herron
 *
 * Licensed 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 com.digitalpetri.modbus.examples;



public class MasterSlaveThroughput {

    public static final int N_MASTERS = 100;
    public static final int N_REQUESTS = 100;

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        new SlaveExample().start();
// Path: modbus-examples/src/main/java/com/digitalpetri/modbus/examples/master/MasterExample.java
// public class MasterExample {
// 
//     public static void main(String[] args) {
//         new MasterExample(100, 100).start();
//     }
// 
//     private final Logger logger = LoggerFactory.getLogger(getClass());
// 
//     private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
// 
//     private final List<ModbusTcpMaster> masters = new CopyOnWriteArrayList<>();
//     private volatile boolean started = false;
// 
//     private final int nMasters;
//     private final int nRequests;
// 
//     public MasterExample(int nMasters, int nRequests) {
//         this.nMasters = nMasters;
//         this.nRequests = nRequests;
//     }
// 
//     public void start() {
//         started = true;
// 
//         ModbusTcpMasterConfig config = new ModbusTcpMasterConfig.Builder("localhost")
//             .setPort(50200)
//             .build();
// 
//         new Thread(() -> {
//             while (started) {
//                 try {
//                     Thread.sleep(5000);
//                 } catch (InterruptedException e) {
//                     e.printStackTrace();
//                 }
// 
//                 double mean = 0.0;
//                 double oneMinute = 0.0;
// 
//                 for (ModbusTcpMaster master : masters) {
//                     mean += master.getResponseTimer().getMeanRate();
//                     oneMinute += master.getResponseTimer().getOneMinuteRate();
//                 }
// 
//                 logger.info("Mean rate={}, 1m rate={}", mean, oneMinute);
//             }
//         }).start();
// 
//         for (int i = 0; i < nMasters; i++) {
//             ModbusTcpMaster master = new ModbusTcpMaster(config);
//             master.connect();
// 
//             masters.add(master);
// 
//             for (int j = 0; j < nRequests; j++) {
//                 sendAndReceive(master);
//             }
//         }
//     }
// 
//     private void sendAndReceive(ModbusTcpMaster master) {
//         if (!started) return;
// 
//         CompletableFuture<ReadHoldingRegistersResponse> future =
//             master.sendRequest(new ReadHoldingRegistersRequest(0, 10), 0);
// 
//         future.whenCompleteAsync((response, ex) -> {
//             if (response != null) {
//                 ReferenceCountUtil.release(response);
//             } else {
//                 logger.error("Completed exceptionally, message={}", ex.getMessage(), ex);
//             }
//             scheduler.schedule(() -> sendAndReceive(master), 1, TimeUnit.SECONDS);
//         }, Modbus.sharedExecutor());
//     }
// 
//     public void stop() {
//         started = false;
//         masters.forEach(ModbusTcpMaster::disconnect);
//         masters.clear();
//     }
// 
// }
// 
// Path: modbus-examples/src/main/java/com/digitalpetri/modbus/examples/slave/SlaveExample.java
// public class SlaveExample {
// 
//     public static void main(String[] args) throws ExecutionException, InterruptedException {
//         final SlaveExample slaveExample = new SlaveExample();
// 
//         slaveExample.start();
// 
//         Runtime.getRuntime().addShutdownHook(new Thread("modbus-slave-shutdown-hook") {
//             @Override
//             public void run() {
//                 slaveExample.stop();
//             }
//         });
// 
//         Thread.sleep(Integer.MAX_VALUE);
//     }
// 
//     private final Logger logger = LoggerFactory.getLogger(getClass());
// 
//     private final ModbusTcpSlaveConfig config = new ModbusTcpSlaveConfig.Builder().build();
//     private final ModbusTcpSlave slave = new ModbusTcpSlave(config);
// 
//     public SlaveExample() {}
// 
//     public void start() throws ExecutionException, InterruptedException {
//         slave.setRequestHandler(new ServiceRequestHandler() {
//             @Override
//             public void onReadHoldingRegisters(ServiceRequest<ReadHoldingRegistersRequest, ReadHoldingRegistersResponse> service) {
//                 String clientRemoteAddress = service.getChannel().remoteAddress().toString();
//                 String clientIp = clientRemoteAddress.replaceAll(".*/(.*):.*", "$1");
//                 String clientPort = clientRemoteAddress.replaceAll(".*:(.*)", "$1");
// 
//                 ReadHoldingRegistersRequest request = service.getRequest();
// 
//                 ByteBuf registers = PooledByteBufAllocator.DEFAULT.buffer(request.getQuantity());
// 
//                 for (int i = 0; i < request.getQuantity(); i++) {
//                     registers.writeShort(i);
//                 }
// 
//                 service.sendResponse(new ReadHoldingRegistersResponse(registers));
// 
//                 ReferenceCountUtil.release(request);
//             }
//         });
// 
//         slave.bind("localhost", 50200).get();
//     }
// 
//     public void stop() {
//         slave.shutdown();
//     }
// 
// }


// Path: modbus-examples/src/main/java/com/digitalpetri/modbus/examples/MasterSlaveThroughput.java
import java.util.concurrent.ExecutionException;
import com.digitalpetri.modbus.examples.master.MasterExample;
import com.digitalpetri.modbus.examples.slave.SlaveExample;

/*
 * Copyright 2016 Kevin Herron
 *
 * Licensed 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 com.digitalpetri.modbus.examples;



public class MasterSlaveThroughput {

    public static final int N_MASTERS = 100;
    public static final int N_REQUESTS = 100;

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        new SlaveExample().start();
        new MasterExample(N_MASTERS, N_REQUESTS).start();