Question

I have created a connection pooling process in Erlang that has sub-processes ( each being a connection ). The connection pooling process (supervisor) needs to hold the state of all children sub-processes, such as a flag that indicates if the sub-process is available to be leased to a requester. This state is stored on a ETS table.

POOL-MASTER :

  • connection process 1
  • connection process 2
  • connection process 3

When a client requests a connection to POOL-MASTER, it must find out which connection process is available looking at ETS and fetching the state. This phase is called "get-lease". Then the state is updated. Similarly, when a client returns the connection to the pool, it uses a "return-lease" function that flags the item to be available to the next client.

I want to have the functions above "get-lease and return-lease" to be thread-safe. In other words, I want to make sure that no client is concurrently using these functions otherwise it turns out the state of the connections can be mixed up ( two clients get the same connection ). In java a synchronized method would be used for this purpose.

Is there anything in erlang that can be done to achieve this ? For instance some sort of locking mechanism on the ETS table and then relasing the lock ? Or should this be done creating a single process that handles the specific functions to be locked/unlocked and send messages to this process (assuming the messaging is single threaded ) ?

Was it helpful?

Solution

Thread-safe ? What is it ? Erlang does'nt know it :) since we work on message passing between processes. This makes sure that access to any structure (maintained by a server erlang process) will always be in serialized manner [same what Don Branson has mentioned.]

What I would have done is:

1. Create a gen server process monitored by a supervisor process.

2. This server process would be the manager of your ETS table and exposes API/methods to be called by clients for requesting and releasing connections.

3. The requests will be handled by handle_call(for sync call) or by handle_cast(for async call)

4. You might even want to implement some Timeout functionality to release connections by iterating over your ETS table and deleting from it based on some criteria

The above would work just fine giving you decent performance as well (if performance came to your mind). AND no race conditions as the accesses are serilized.

OTHER TIPS

One approach would be to have a process dedicated to managing leases via messaging. Send a get_lease message to that process. It would receive the lease message, thus serializing access, and send a reply message to the requesting process when a lease becomes available. The lessee would send a return_lease message to the manager, which would add the lease back to the free-list.

The manager would also have to do something about processes that acquire a lease and fail to return it. It's a lease, so presumably there's an expiration that could be used for this, but the manager should also probably monitor the lessee and free the lease if a lessee fails.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top