Throughout the design process, there were alternative approaches which were analyzed in order to decide the final design choice. This section addresses some of the alternatives and the final decision.
Several of the components and functions in the Status Server will require memory to be allocated or reallocated as part of its functionality. It is possible for calls to malloc() or realloc() to fail in the unlikely event that memory is not available on the machine. While this event hopefully will never happen, it is an error condition which must be managed. This section addresses the issue and some possible alternatives. A decision must still be made on the approach to be implemented in the Status Server. The API calls and pseudocode documented in the software design don't take into account error conditions caused by the inability to allocate enough memory.
In many cases, the memory allocation will occur as a result of a client request. In this case, it could be possible to send a return message to the client indicating that the request could not be processed. Other times, the memory allocation could occur when a client must be informed of a monitoring event and space can not be allocated in the client monitoring object to hold the new value. At this point, it could be possible to defer the monitor update by treating this a the same case as a full network buffer. Using the error message approach to handling ``out-of-memory'' errors, the Status Server would continue to operate in a somewhat degraded mode until additional memory becomes available. This would require the client to handle additional failed return values. A basic flow diagram for this approach is shown in figure 18.
Another alternative would be to have the Status Server add retry logic to both the malloc() and realloc() function calls. In this case, if memory was not available, it would sleep for some period of time before retrying. Since the Status Server is single-threaded, this means the entire Server process will block while memory is not available. Also, any client request currently in progress will block causing the client socket connection to remain tied up until the client-side socket timeout threshold is reached. This approach would eliminate the need to check for out-of-memory conditions simplifying the Client API and Status Server along with eliminating one possible return value the client may need to check for. The disadvantage is that the connection may remain tied up or time out. Hopefully, the process gobbling up the memory is not the Status Server itself. If so, this approach would cause the Status Server to slowly consume more and more memory. If the memory is being consumed by another process, it is possible that the process will soon die and normal operation can be quickly resumed. If a core dump of the process is triggered, it could take some time before the memory again becomes available. A basic flow diagram for this approach is shown in figure 19.
A final alternative could be to initiate a predefined number of retries and if the memory can not be allocated when retries are exhausted, serialize the contents of the Status Server and trigger an exit. This approach would require that buffers required for serialization be preallocated and that the IO processes used to write the data to a file do not require additional memory allocation. The total time available to retries must be set below the default socket timeout defined for socket connections. In this case, the client would not need to implement any additional error checking for individual command responses, and it will be guaranteed not to block if it has connected to the Status Server without the autoretry option. For clients connecting to the Status Server with the autoretry option, they will block until the Status Server is restarted. A basic flow diagram for this approach is shown in figure 20.
There is a good chance that this alternative would not work, since there is a good possibility that the IO processes used to write the data to a file will require an allocation of memory.
The Status Server will implement the second approach, which requires the Status Server to add retry logic to both the malloc() and realloc() function calls. In this case, if malloc() or realloc() function calls fail, the Status Server will sleep for a predefined time before retrying the memory allocation.