//
//  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
//
//      https://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.
//
:imagesdir: ../../images/
:icons: font

== Connection Pool

There are situations where you don't want to carry around connections in your code.

For example if you have a microservice application, you might have multiple services accessing PLC data.

Keeping an open connection for each of these is rather problematic as in contrast to modern computers, PLCs usually are only able to manage a small number of concurrent connections.

I think a Siemens S7-1200 is limited to 7 concurrent connections and a Siemens LOGO can't do more than 3.

One alternative would be to open and close the connections all the time.
This however puts an unnecessary stress on the PLCs as for protocols like the S7 or the ADS protocol a handshake of multiple requests and responses has to be executed before being able to communicate.

As usually these services only require ad-hoc access to a PLC, it would be ideal to share connections between services.

Another problem occurs when you open a connection and keep it open for a prolonged time period.
Here it can happen quite often that a connection is terminated because the PLC has been turned off.

Per default the PLC connection has no means of automatically re-connecting.

The `PooledPlcDriverManager` can help you with both of these scenarios.

=== The PooledPlcDriverManager

The `PooledPlcDriverManager` is a wrapper around the normal `PlcDriverManager`.

The main difference is that as soon as a connection is requested, it will look if one already exists and return that.

If no connection exists it will create a new one and keep it in the pool.

There are no API differences from using the normal `PlcDriverManager` so you call `createConnection` and `close` just like with the normal PLC4X API.

The structure of the code is now more or less like if you would create a new connection for every request and close it afterwards.

Another benefit of the `PooledPlcDriverManager` is that it will check a connection for any problems before returning it to the client.

So if a connection was terminated, it will detect this and create a new connection.

=== Example

Here comes a little example program utilizing the `PooledPlcDriverManager`:

[source,java]
----
    PlcDriverManager driverManager = new PooledPlcDriverManager();

    // This just simulates a scenario where a lot of connections would be created and immediately destroyed again.
    for(int i = 0; i < 100; i++) {
        try(PlcConnection connection = driverManager.getConnection("...")) {

            ... do something ... (please refer to the PLC4J getting started for details)

        }
    }
----

NOTE: When sharing connections between multiple services, be sure to share the instance of the `PooledPldDriverManager` as otherwise you will result in having multiple pools.

