blob: d9c8a9f9ab413328689ff602b6e0d3d7849facd4 [file] [log] [blame]
Emeric Vigier2f625822012-08-06 11:09:52 -04001// Copyright (C) 1999-2005 Open Source Telecom Corporation.
2// Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
3//
4// This program is free software; you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation; either version 2 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program; if not, write to the Free Software
16// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17//
18// As a special exception, you may use this file as part of a free software
19// library without restriction. Specifically, if other files instantiate
20// templates or use macros or inline functions from this file, or you compile
21// this file and link it with other files to produce an executable, this
22// file does not by itself cause the resulting executable to be covered by
23// the GNU General Public License. This exception does not however
24// invalidate any other reasons why the executable file might be covered by
25// the GNU General Public License.
26//
27// This exception applies only to the code released under the name GNU
28// Common C++. If you copy code from other releases into a copy of GNU
29// Common C++, as the General Public License permits, the exception does
30// not apply to the code that you add in this way. To avoid misleading
31// anyone as to the status of such modified files, you must delete
32// this exception notice from them.
33//
34// If you write modifications of your own for GNU Common C++, it is your choice
35// whether to permit this exception to apply to your modifications.
36// If you do not wish that, delete this exception notice.
37//
38
39/**
40 * @file misc.h
41 * @short Memory management, configuration keydata objects and string
42 * tokenizer.
43 **/
44
45#ifndef CCXX_MISC_H_
46#define CCXX_MISC_H_
47
48#ifndef CCXX_MISSING_H_
49#include <cc++/missing.h>
50#endif
51
52#ifndef CCXX_THREAD_H_
53#include <cc++/thread.h>
54#endif
55
56#define KEYDATA_INDEX_SIZE 97
57#define KEYDATA_PAGER_SIZE 512
58
59#if defined(PATH_MAX)
60#if PATH_MAX > 512
61#define KEYDATA_PATH_SIZE 512
62#else
63#define KEYDATA_PATH_SIZE PATH_MAX
64#endif
65#else
66#define KEYDATA_PATH_SIZE 256
67#endif
68
69#ifdef CCXX_NAMESPACES
70namespace ost {
71#endif
72
73class __EXPORT Runlist;
74class __EXPORT Runable;
75
76/**
77 * The memory pager is used to allocate cumulative memory pages for
78 * storing object specific "persistant" data that is presumed to persist
79 * during the life of a given derived object. When the object is
80 * destroyed, all accumulated data is automatically purged.
81 *
82 * There are a number of odd and specialized utility classes found in Common
83 * C++. The most common of these is the "MemPager" class. This is basically
84 * a class to enable page-grouped "cumulative" memory allocation; all
85 * accumulated allocations are dropped during the destructor. This class has
86 * found it's way in a lot of other utility classes in Common C++.
87 *
88 * @author David Sugar <dyfet@ostel.com>
89 * @short Accumulative object memory allocator.
90 */
91class __EXPORT MemPager
92{
93private:
94 friend class String;
95 friend class MemPagerObject;
96
97 size_t pagesize;
98 unsigned int pages;
99
100 struct _page {
101 struct _page *next;
102 size_t used;
103 } *page;
104
105protected:
106 /**
107 * Allocate first workspace from paged memory. This method
108 * scans all currently allocated blocks for available space
109 * before adding new pages and hence is both slower and more
110 * efficient.
111 *
112 * @param size size of memory to allocate.
113 * @return pointer to allocated memory.
114 */
115 virtual void* first(size_t size);
116
117 /**
118 * Allocate memory from either the currently active page, or
119 * allocate a new page for the object.
120 *
121 * @param size size of memory to allocate.
122 * @return pointer to allocated memory.
123 */
124 virtual void* alloc(size_t size);
125
126 /**
127 * Allocate a string from the memory pager pool and copy the
128 * string into it's new memory area. This method allocates
129 * memory by first searching for an available page, and then
130 * allocating a new page if no space is found.
131 *
132 * @param str string to allocate and copy into paged memory pool.
133 * @return copy of string from allocated memory.
134 */
135 char* first(char *str);
136
137 /**
138 * Allocate a string from the memory pager pool and copy the
139 * string inti it's new memory area. This checks only the
140 * last active page for available space before allocating a
141 * new page.
142 *
143 * @param str string to allocate and copy into paged memory pool.
144 * @return copy of string from allocated memory.
145 */
146 char* alloc(const char *str);
147
148 /**
149 * Create a paged memory pool for cumulative storage. This
150 * pool allocates memory in fixed "pagesize" chunks. Ideal
151 * performance is achived when the pool size matches the
152 * system page size. This pool can only exist in derived
153 * objects.
154 *
155 * @param pagesize page size to allocate chunks.
156 */
157 MemPager(size_t pagesize = 4096);
158
159 /**
160 * purge the current memory pool.
161 */
162 void purge(void);
163
164 /**
165 * Clean for memory cleanup before exiting.
166 */
167 void clean(void);
168
169 /**
170 * Delete the memory pool and all allocated memory.
171 */
172 virtual ~MemPager();
173
174public:
175 /**
176 * Return the total number of pages that have been allocated
177 * for this memory pool.
178 *
179 * @return number of pages allocated.
180 */
181 inline int getPages(void)
182 {return pages;};
183};
184
185/**
186 * The StackPager provides a repository to stash and retrieve working
187 * data in last-in-first-out order. The use of a mempager to support
188 * it's operation allows storage of arbitrary sized objects with no
189 * fixed limit.
190 *
191 * @author David Sugar <dyfet@ostel.com>
192 * @short last in first out object pager.
193 */
194class __EXPORT StackPager : protected MemPager
195{
196private:
197 typedef struct frame {
198 struct frame *next;
199 char data[1];
200 } frame_t;
201
202 frame_t *stack;
203
204public:
205 /**
206 * Create a lifo pager as a mempager.
207 *
208 * @param pagesize for memory allocation
209 */
210 StackPager(size_t pagesize);
211
212 /**
213 * Push an arbitrary object onto the stack.
214 *
215 * @return stack memory location.
216 * @param object pointer to data
217 * @param size of data.
218 */
219 void *push(const void *object, size_t size);
220
221 /**
222 * Push a string onto the stack.
223 *
224 * @return stack memory location.
225 * @param string pointer.
226 */
227 void *push(const char *string);
228
229 /**
230 * Retrieve next object from stack.
231 *
232 * @return object.
233 */
234 void *pull(void);
235
236 /**
237 * Purge the stack of all objects and memory allocations.
238 */
239 void purge(void);
240};
241
242/**
243 * The shared mempager uses a mutex to protect key access methods.
244 * This class is used when a mempager will be shared by multiple
245 * threads.
246 *
247 * @author David Sugar <dyfet@ostel.com>
248 * @short mutex protected memory pager.
249 */
250class __EXPORT SharedMemPager : public MemPager, public Mutex
251{
252protected:
253 /**
254 * Create a mempager mutex pool.
255 *
256 * @param pagesize page size for allocation.
257 * @param name a name for the pool.
258 */
259 SharedMemPager(size_t pagesize = 4096, const char *name = NULL);
260
261 /**
262 * Purge the memory pool while locked.
263 */
264 void purge(void);
265
266 /**
267 * Get the first memory page after locking.
268 *
269 * @return allocated memory space.
270 * @param size of request.
271 */
272 void* first(size_t size);
273
274 /**
275 * Get the last memory page after locking.
276 *
277 * @return allocated memory space.
278 * @param size of request.
279 */
280 void* alloc(size_t size);
281};
282
283__EXPORT void endKeydata(void);
284
285/**
286 * Keydata objects are used to load and hold "configuration" data for
287 * a given application.
288 *
289 * This class is used to load and then hold "<code>keyword = value</code>" pairs parsed from a text
290 * based "config" file that has been divided into "<code>[sections]</code>". The syntax is:
291 *
292 * <code><pre>
293 * [section_name]
294 * key1=value1
295 * key2=value2</pre></code>
296 *
297 * Essentially, the "path" is a "keypath" into a theoretical namespace of key
298 * pairs, hence one does not use "real" filepaths that may be OS dependent. The "<code>/</code>" path refers
299 * to "<code>/etc</code>" prefixed (on UNIX) directories and this is processed within the constructor. It
300 * could refer to the <code>/config</code> prefix on QNX, or even, gasp, a "<code>C:\WINDOWS</code>". Hence, a keypath of
301 * "<code>/bayonne.d/vmhost/smtp</code>" actually resolves to a "<code>/etc/bayonne.d/vmhost.conf</code>" and loads key
302 * value pairs from the <code>[smtp]</code> section of that <code>.conf</code> file.
303 *
304 * Similarly, something like "<code>~bayonne/smtp</code>" path refers to a "<code>~/.bayonnerc</code>" and loads key pairs
305 * from the <code>[smtp]</code> section. This coercion occurs before the name is passed to the open call.
306 *
307 * I actually use derived keydata based classes as global initialized objects, and they hence
308 * automatically load and parse config file entries even before "main" has started.
309 *
310 * Keydata can hold multiple values for the same key pair. This can
311 * occur either from storing a "list" of data items in a config file,
312 * or when overlaying multiple config sources (such as <code>/etc/....conf</code> and
313 * <code>~/.confrc</code> segments) into a single object. The keys are stored as
314 * cumulative (read-only/replacable) config values under a hash index
315 * system for quick retrieval.
316 *
317 * Keydata can
318 * also load a table of "initialization" values for keyword pairs that were
319 * not found in the external file.
320 *
321 * One typically derives an application specific keydata class to load a
322 * specific portion of a known config file and initialize it's values. One
323 * can then declare a global instance of these objects and have
324 * configuration data initialized automatically as the executable is loaded.
325 *
326 * Hence, if I have a "[paths]" section in a "<code>/etc/server.conf?</code>" file, I might
327 * define something like:
328 *
329 * <code><pre>
330 * class KeyPaths : public Keydata
331 * {
332 * public:
333 * KeyPaths() : Keydata("/server/paths")
334 * {
335 * static Keydata::Define *defvalues = {
336 * {"datafiles", "/var/server"},
337 * {NULL, NULL}};
338 *
339 * // override with [paths] from "~/.serverrc" if avail.
340 *
341 * load("~server/paths");
342 * load(defvalues);
343 * }
344 * };
345 *
346 * KeyPaths keypaths;
347 * </pre></code>
348 *
349 * @author David Sugar <dyfet@ostel.com>
350 * @short load text configuration files into keyword pairs.
351 */
352class __EXPORT Keydata : protected MemPager
353{
354public:
355#ifdef CCXX_PACKED
356#pragma pack(1)
357#endif
358
359 struct Keyval {
360 Keyval *next;
361 char val[1];
362 };
363
364 struct Keysym {
365 Keysym *next;
366 Keyval *data;
367 const char **list;
368 short count;
369 char sym[1];
370 };
371
372 struct Define {
373 const char *keyword;
374 const char *value;
375 };
376
377#ifdef CCXX_PACKED
378#pragma pack()
379#endif
380
381private:
382 static std::ifstream *cfgFile;
383 static char lastpath[KEYDATA_PATH_SIZE + 1];
384 static int count;
385 static int sequence;
386
387 int link;
388
389 Keysym *keys[KEYDATA_INDEX_SIZE];
390
391 /**
392 * Compute a hash key signature id for a symbol name.
393 *
394 * @return key signature index path.
395 * @param sym symbol name.
396 */
397 unsigned getIndex(const char *sym);
398
399protected:
400 Keysym* getSymbol(const char *sym, bool create);
401
402public:
403 /**
404 * Load additional key values into the currrent object from
405 * the specfied config source (a config file/section pair).
406 * These values will overlay the current keywords when matches
407 * are found. This can be used typically in a derived config
408 * object class constructor to first load a <code>/etc</code> section, and
409 * then load a matching user specific entry from <code>~/.</code> to override
410 * default system values with user specific keyword values.
411 *
412 * @param keypath (filepath/section)
413 */
414 void load(const char *keypath);
415
416 /**
417 * Load additional key values into the currrent object from
418 * the specfied config source (a config file/section pair).
419 * These values will overlay the current keywords when matches
420 * are found. This can be used typically in a derived config
421 * object class constructor to first load a <code>/etc</code> section, and
422 * then load a matching user specific entry from <code>~/.</code> to override
423 * default system values with user specific keyword values.
424 * This varient puts a prefix in front of the key name.
425 *
426 * @param prefix
427 * @param keypath (filepath/section)
428 */
429 void loadPrefix(const char *prefix, const char *keypath);
430
431 /**
432 * Load additional keys into the current object using a real
433 * filename that is directly passed rather than a computed key
434 * path. This also uses a [keys] section as passed to the object.
435 *
436 * @param filepath to load from
437 * @param keys section to parse from, or NULL to parse from head
438 * @param pre optional key prefix
439 */
440 void loadFile(const char *filepath, const char *keys = NULL, const char *pre = NULL);
441
442 /**
443 * Load default keywords into the current object. This only
444 * loads keyword entries which have not already been defined
445 * to reduce memory usage. This form of Load is also commonly
446 * used in the constructor of a derived Keydata class.
447 *
448 * @param pairs list of NULL terminated default keyword/value pairs.
449 */
450 void load(Define *pairs);
451
452 /**
453 * Create an empty key data object.
454 */
455 Keydata();
456
457 /**
458 * Create a new key data object and use "Load" method to load an
459 * initial config file section into it.
460 *
461 * @param keypath (filepath/section)
462 * specifies the home path.
463 */
464 Keydata(const char *keypath);
465
466 /**
467 * Alternate constructor can take a define list and an optional
468 * pathfile to parse.
469 *
470 * @param pairs of keyword values from a define list
471 * @param keypath of optional file and section to load from
472 */
473 Keydata(Define *pairs, const char *keypath = NULL);
474
475 /**
476 * Destroy the keydata object and all allocated memory. This
477 * may also clear the "cache" file stream if no other keydata
478 * objects currently reference it.
479 */
480 virtual ~Keydata();
481
482 /**
483 * Unlink the keydata object from the cache file stream. This
484 * should be used if you plan to keepa Keydata object after it
485 * is loaded once all keydata objects have been loaded, otherwise
486 * the cfgFile stream will remain open. You can also use
487 * endKeydata().
488 */
489 void unlink(void);
490
491 /**
492 * Get a count of the number of data "values" that is associated
493 * with a specific keyword. Each value is from an accumulation of
494 * "<code>load()</code>" requests.
495 *
496 * @param sym keyword symbol name.
497 * @return count of values associated with keyword.
498 */
499 int getCount(const char *sym);
500
501 /**
502 * Get the first data value for a given keyword. This will
503 * typically be the <code>/etc</code> set global default.
504 *
505 * @param sym keyword symbol name.
506 * @return first set value for this symbol.
507 */
508 const char* getFirst(const char *sym);
509
510 /**
511 * Get the last (most recently set) value for a given keyword.
512 * This is typically the value actually used.
513 *
514 * @param sym keyword symbol name.
515 * @return last set value for this symbol.
516 */
517 const char* getLast(const char *sym);
518
519 /**
520 * Find if a given key exists.
521 *
522 * @param sym keyword to find.
523 * @return true if exists.
524 */
525 bool isKey(const char *sym);
526
527 /**
528 * Get a string value, with an optional default if missing.
529 *
530 * @param sym keyword name.
531 * @param default if not present.
532 * @return string value of key.
533 */
534 const char *getString(const char *sym, const char *def = NULL);
535
536 /**
537 * Get a long value, with an optional default if missing.
538 *
539 * @param sym keyword name.
540 * @param default if not present.
541 * @return long value of key.
542 */
543 long getLong(const char *sym, long def = 0);
544
545 /**
546 * Get a bool value.
547 *
548 * @param sym keyword name.
549 * @return true or false.
550 */
551 bool getBool(const char *key);
552
553 /**
554 * Get a floating value.
555 *
556 * @param sym keyword name.
557 * @param default if not set.
558 * @return value of key.
559 */
560 double getDouble(const char *key, double def = 0.);
561
562 /**
563 * Get an index array of ALL keywords that are stored by the
564 * current keydata object.
565 *
566 * @return number of keywords found.
567 * @param data pointer of array to hold keyword strings.
568 * @param max number of entries the array can hold.
569 */
570 unsigned getIndex(char **data, unsigned max);
571
572 /**
573 * Get the count of keyword indexes that are actually available
574 * so one can allocate a table to receive getIndex.
575 *
576 * @return number of keywords found.
577 */
578 unsigned getCount(void);
579
580 /**
581 * Set (replace) the value of a given keyword. This new value
582 * will become the value returned from getLast(), while the
583 * prior value will still be stored and found from <code>getList()</code>.
584 *
585 * @param sym keyword name to set.
586 * @param data string to store for the keyword.
587 */
588 void setValue(const char *sym, const char *data);
589
590 /**
591 * Return a list of all values set for the given keyword
592 * returned in order.
593 *
594 * @return list pointer of array holding all keyword values.
595 * @param sym keyword name to fetch.
596 */
597 const char * const* getList(const char *sym);
598
599 /**
600 * Clear all values associated with a given keyword. This does
601 * not de-allocate the keyword from memory, however.
602 *
603 * @return keyword name to clear.
604 */
605 void clrValue(const char *sym);
606
607 /**
608 * A convient notation for accessing the keydata as an associative
609 * array of keyword/value pairs through the [] operator.
610 */
611 inline const char *operator[](const char *keyword)
612 {return getLast(keyword);};
613
614 /**
615 * static member to end keydata i/o allocations.
616 */
617 static void end(void);
618
619 /**
620 * Shutdown the file stream cache. This should be used before
621 * detaching a deamon, <code>exec()</code>, <code>fork()</code>, etc.
622 */
623 friend inline void endKeydata(void)
624 {Keydata::end();};
625};
626
627/**
628 * This class is used to create derived classes which are constructed
629 * within a memory pager pool.
630 *
631 * @short create objects in a memory pager.
632 * @author David Sugar <dyfet@ostel.com>
633 */
634class __EXPORT MemPagerObject
635{
636public:
637 /**
638 * Allocate memory from a memory pager.
639 *
640 * @param size of new passed from operator.
641 * @param pager to allocate from.
642 */
643 inline void *operator new(size_t size, MemPager &pager)
644 {return pager.alloc(size);};
645
646 /**
647 * Allocate array from a memory pager.
648 *
649 * @param size of new passed from operator.
650 * @param pager to allocate from.
651 */
652 inline void *operator new[](size_t size, MemPager &pager)
653 {return pager.alloc(size);};
654
655 /**
656 * Mempager delete does nothing; the pool purges.
657 */
658 inline void operator delete(void *) {};
659
660 /**
661 * Array mempager delete does nothing; the pool purges.
662 */
663 inline void operator delete[](void *) {};
664};
665
666/**
667 * This class is used to associate (object) pointers with named strings.
668 * A virtual is used to allocate memory which can be overriden in the
669 * derived class.
670 *
671 * @author David Sugar <dyfet@ostel.com>
672 * @short associate names with pointers.
673 */
674class __EXPORT Assoc
675{
676private:
677 struct entry {
678 const char *id;
679 entry *next;
680 void *data;
681 };
682
683 entry *entries[KEYDATA_INDEX_SIZE];
684
685protected:
686 Assoc();
687 virtual ~Assoc();
688
689 void clear(void);
690
691 virtual void *getMemory(size_t size) = 0;
692
693public:
694 void *getPointer(const char *id) const;
695 void setPointer(const char *id, void *data);
696};
697
698/**
699 * A runlist is used to restrict concurrent exection to a limited set
700 * of concurrent sessions, much like a semaphore. However, the runlist
701 * differs in that it notifies objects when they become ready to run,
702 * rather than requiring them to wait and "block" for the semaphore
703 * count to become low enough to continue.
704 *
705 * @author David Sugar <dyfet@ostel.com>
706 * @short list of runable objects.
707 */
708class __EXPORT Runlist : public Mutex
709{
710private:
711 Runable *first, *last;
712
713protected:
714 unsigned limit, used;
715 void check(void);
716
717public:
718 /**
719 * Create a new runlist with a specified limit.
720 *
721 * @param count limit before wait queuing.
722 */
723 Runlist(unsigned count = 1);
724
725 /**
726 * Add a runable object to this runlist. If the number of
727 * entries running is below the limit, then add returns true
728 * otherwise the entry is added to the list.
729 *
730 * @return true if immediately ready to run
731 * @param run pointer to runable object.
732 */
733 bool add(Runable *run);
734
735 /**
736 * Remove a runable object from the wait list or notify when
737 * it is done running so that the used count can be decremented.
738 *
739 * @param run pointer to runable object.
740 */
741 void del(Runable *run);
742
743 /**
744 * Set the limit.
745 *
746 * @param limit to use.
747 */
748 void set(unsigned limit);
749};
750
751/**
752 * A container for objects that can be queued against a runlist.
753 *
754 * @author David Sugar <dyfet@ostel.com>
755 * @short runable object with notify when ready.
756 */
757class __EXPORT Runable
758{
759private:
760 friend class Runlist;
761 Runlist *list;
762 Runable *next, *prev;
763
764protected:
765 Runable();
766 virtual ~Runable();
767
768 /**
769 * Method handler that is invoked when a wait-listed object
770 * becomes ready to run.
771 */
772 virtual void ready(void) = 0;
773
774public:
775 /**
776 * Start the object against a run list.
777 *
778 * @return true if immediately available to run.
779 * @param list to start under.
780 */
781 bool starting(Runlist *list);
782
783 /**
784 * Stop the object, called when stopping or ready completes.
785 * May also be used for a task that has not yet started to
786 * remove it from the wait list.
787 */
788 void stoping(void);
789};
790
791#ifdef CCXX_NAMESPACES
792}
793#endif
794
795#endif
796
797/** EMACS **
798 * Local variables:
799 * mode: c++
800 * c-basic-offset: 4
801 * End:
802 */