I would like to announce that OpenSAF now has a policy regarding limits: limits should, in general, be possible to configure without recompiling the source code. This means that we would like to move away from using hard-coded limits, and we would like the code to be designed in scalable way so that limits can be increased. This way, we can ensure that OpenSAF is flexible enough to be used in a wide variety of applications and deployments.
The rest of this message contains some detailed discussions around limits. Read on if you are interested, but the main point of this message has already been covered. :-) First of all I would like to point out that instead of making a limit configurable, the limit could be removed altogether. However, in many cases there is a good reason to have a limit, especially in the case of resource limits that I will describe in more details below. The main reason for having a limit is to protect the system from a misbehaving application. There are many reasons why an application may misbehave so that it will exceed the limits we have set: * Due to a resource leak * Due to a fault in the program logic (e.g. miscalculating the size) * Due to memory corruption * Due to an attack By having a limit, we can detect the problem early and stop it before the whole system becomes unstable. EXPLICIT LIMITS =============== Resource limits --------------- By a resource limit I mean a limit for something that the application allocates and deallocates. Thus, if the application forgets to deallocate the resource, we have a resource leak. We are mainly concerned about resources that are visible outside the application process: a resource that is allocated either in the memory of an OpenSAF service, on disk, or in the Linux OS (e.g. a shared memory segment). If the resource is allocated locally inside the application then a resource leak could be regarded as an ordinary memory leak in the application. A typical example of a resource is a SAF handle returned by one of the saXxxInitalize() functions. Compare this with a file handle in Linux. In Linux, there are two limits for file handles: a per-process limit that can be configured using the setrlimit() system call, and a system-global limit that can configured using the /proc file system. The reason for having a per-process limit is that if the application process is leaking file handles, we don't want it to exhaust all available file handles in the entire system. Therefore, the per-process limit is set to a small value (1024 by default) that is much lower than the system-global limit. Size limits ----------- By size limit I mean typically the maximum size for an object. It could for example be a maximum string length. Again, if the string is just allocated locally in the application process, we don't have to be so concerned about it. But if the string is passed as a parameter to an OpenSAF service, we may wish to protect the service against receiving too large strings. Imagine that the application has a memory corruption bug, so that the variable containing the length of the string is garbled. The OpenSAF service would receive an insanely large string, which if not rejected is likely to cause problems to the service. Distinguished names, normally stored in the SaNameT type, is an example for which we have a size limit. Unfortunately, the size limit is in this particular case specified by the SAF standard, and is therefore difficult to change. However, there are suggestions for how we can make an OpenSAF extension that would allow longer distinguished names. Time limits ----------- Time limits, or maybe timeout limits, is yet another category of limits. There may be a need to configure time limits differently on different types of systems. OpenSAF can be used on large systems with many nodes, possibly geographically distributed, and with a large disk accessed over the network. Or it may be used on a small two-node embedded system with a fast node-local solid state disk or flash memory. IMPLICIT LIMITS =============== The different types of limits mentioned above are expressed explicitly in the code; there is a place in the code where we check if we are above or below the limit, and take different actions depending on this. I would also like to mention implicit limits; limits that are not expressed directly in the code, but rather are the results of the way the code is written: the data types, OS functions or algorithms that were chosen. The sections below describe different types of implicit limits: Limited range of (integer) data type ------------------------------------ A 64-bit integer can for all practical purposes be regarded as being able to hold an infinite range of numbers. There may be a perfectly good reason to use a smaller integer type in order to save memory, network bandwidth, or disk space. But please be careful to ensure that the data type has sufficient range to hold all possible values also in the case where the OpenSAF limits have been configured to be larger than default. Fixed-size buffers ------------------------- Prefer to use dynamically allocated buffers of variable size instead of fixed-size buffers. In C++, this is easy: use std::string or std::vector. In C, you can use malloc() to dynamically allocate a buffer. A fixed-size buffer may be sufficient for internal data that is only used within OpenSAF, for example as a scratch buffer for formatting a log message. But if the buffer contains application data, or if it contains something that can be configured, for example a path, then it is better to use a variable-size buffer. Using variable-size buffers will in general also be more memory efficient, since the buffer will only be as large as needed. Deprecated operating system interfaces -------------------------------------- Operating system interfaces can also have limits, and in many cases there is a new variant of the same interface where the limit has been removed. Prefer to use these newer variants; it is usually not more difficult than using the old ones, and sometimes easier. Some examples: * Use epoll() or poll() instead of select(). Otherwise we are limited to a maximum of 1024 file handles. This is especially important when writing code that will be used in an agent library, since it executes in the same process as an application program. * Use thread-safe variants (normally ending with the _r suffix) where available. E.g. use localtime_r() instead of localtime(). Otherwise we are limited to single-threaded programs. This is especially important when writing code that will be used in an agent library, since it executes in the same process as an application program. * Use fseeko() and ftello() instead of fseek() and ftell(). Otherwise file size is limited to 2 gigabytes on 32-bit systems. For the same reason, also make sure that the macro _LARGEFILE_SOURCE is defined. * When using functions for IP communication, use the newer variants that support both IPv4 and IPv6 instead of the old ones that only support IPv4. E.g. use inet_pton() instead inet_aton() or inet_addr(). Otherwise we are limited to using IPv4 addresses only. * Prefer the functions sysconf(), pathconf() and getrlimit() over the corresponding macros for reading system limits. E.g. use sysconf(_SC_HOST_NAME_MAX) instead of HOST_NAME_MAX, and pathconf(_PC_PATH_MAX) instead of PATH_MAX. This is mainly a portability issue since POSIX does not require these limit to be fixed, and the macros are not required to be defined. Inefficient algorithms ---------------------- Even though it may not cause a theoretical limit, the use of inefficient algorithms and data structures may in practice have the effect that the limits cannot be increased since the system would become too slow. Prefer to use efficient algorithms and design the code so that it is scalable. For example, use a tree data structure or a hash table instead of using linear search in a linked list. In C++, this is easy: just switch to a different container type. std::set and std::map provide tree data structures, and std::unordered_set and std::unordered_map provide provide hash tables. regards, Anders Widell ------------------------------------------------------------------------------ This SF.net email is sponsored by Windows: Build for Windows Store. http://p.sf.net/sfu/windows-dev2dev _______________________________________________ Opensaf-devel mailing list Opensaf-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/opensaf-devel