MXS-2122: Close listener socket on destruction

Even though directly closing the socket is not very neat in the
architectural sense of things, it allows the best of both worlds: the
socket is instantly closed and is open for reuse while the listener struct
is still available as a reference.

This change needs to be revised when the listeners are refactored into
separate objects.

Updated documentation to reflect the change in behavior.
This commit is contained in:
Markus Mäkelä 2018-10-29 16:05:04 +02:00
parent 47d2898818
commit cd92b6d4d7
No known key found for this signature in database
GPG Key ID: 72D48FCE664F7B19
6 changed files with 20 additions and 19 deletions

View File

@ -323,9 +323,6 @@ all the listeners pointing to the service have been destroyed. This means that
the `data.relationships` must be an empty object and `data.attributes.listeners`
must be an empty array in order for the service to qualify for destruction.
Once a service is destroyed, any listeners associated with it will be freed
after which the ports can be reused by other listeners.
If there are open client connections that use the service when it is destroyed,
they are allowed to gracefully close before the service is destroyed. This means
that the destruction of a service can be acknowledged via the REST API before
@ -466,6 +463,9 @@ DELETE /v1/services/:service/listeners/:name
In the URI , the _:name_ must map to a listener and the _:service_ must map to a
service. Both names must have all whitespace replaced with hyphens.
When a listener is destroyed, the network port it listens on is available for
reuse.
#### Response
Listener is destroyed:

View File

@ -1547,8 +1547,8 @@ Example: create listener my-service my-new-listener 192.168.0.101 4006
You can destroy created listeners with the `destroy listener` command. This will
remove the persisted configuration and it will not be created on the next
startup. The listener is stopped but it will remain a part of the runtime
configuration until the next restart.
startup. The listener is destroyed and the listening port is immediately
available for reuse.
```
destroy listener - Destroy a listener
@ -1558,7 +1558,7 @@ Usage: destroy listener SERVICE NAME
Parameters:
NAME Listener to destroy
The listener is stopped and it will be removed on the next restart of MaxScale
The listener is deleted
Example: destroy listener my-listener
```
@ -1615,9 +1615,7 @@ Example: alter monitor my-monitor user=maxuser password=maxpwd
### Destroying Monitors
To destroy a monitor, use the `destroy monitor` command. All servers need to be
removed from the monitor before it can be destroyed. Only created monitors
should be destroyed and they will remain a part of the runtime configuration
until the next restart.
removed from the monitor before it can be destroyed.
```
destroy monitor - Destroy a monitor
@ -1627,7 +1625,7 @@ Usage: destroy monitor NAME
Parameters:
NAME Monitor to destroy
The monitor is stopped and it will be removed on the next restart of MaxScale
The monitor is destroyed
Example: destroy monitor my-monitor
```

View File

@ -523,10 +523,7 @@ The monitor must be unlinked from all servers before it can be destroyed.
`Usage: destroy listener <service> <name>`
Destroying a monitor causes it to be removed on the next restart. Destroying a
listener at runtime stops it from accepting new connections but it will still be
bound to the listening socket. This means that new listeners cannot be created
to replace destroyed listeners without restarting MaxScale.
Destroying a listener closes the listening socket, opening it up for reuse.
### destroy service

View File

@ -34,11 +34,7 @@ exports.builder = function(yargs) {
})
})
.command('listener <service> <name>', 'Destroy an unused listener', function(yargs) {
return yargs.epilog('Destroying a monitor causes it to be removed on the next restart. ' +
'Destroying a listener at runtime stops it from accepting new ' +
'connections but it will still be bound to the listening socket. This ' +
'means that new listeners cannot be created to replace destroyed listeners ' +
'without restarting MaxScale.')
return yargs.epilog('Destroying a listener closes the listening socket, opening it up for reuse.')
.usage('Usage: destroy listener <service> <name>')
}, function(argv) {
maxctrl(argv, function(host) {

View File

@ -1274,6 +1274,11 @@ void dcb_final_close(DCB* dcb)
}
}
}
else
{
// Only listeners are closed with a fd of -1
mxb_assert(dcb->dcb_role == DCB_ROLE_SERVICE_LISTENER);
}
dcb->state = DCB_STATE_DISCONNECTED;
dcb_remove_from_list(dcb);

View File

@ -751,6 +751,11 @@ bool service_remove_listener(Service* service, const char* target)
{
listener->listener->session->state = SESSION_STATE_LISTENER_STOPPED;
rval = true;
// TODO: This is not pretty but it works, revise when listeners are refactored. This is
// thread-safe as the listener is freed on the same thread that closes the socket.
close(listener->listener->fd);
listener->listener->fd = -1;
}
break;
}