summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2016-10-30 10:50:07 +0200
committerSergey Poznyakoff <gray@gnu.org>2016-10-30 10:50:07 +0200
commitb54540cbbc95069b6d073246a575683170920275 (patch)
treebf7d188d6ae5fa434be6a71b9c415b0d163b8aab
parentc6848f52257191abb36b694be61ce333a8992b4b (diff)
downloadmailutils-b54540cbbc95069b6d073246a575683170920275.tar.gz
mailutils-b54540cbbc95069b6d073246a575683170920275.tar.bz2
Improve opool API
* configure.ac: Version 2.99.993 * NEWS: Update. * include/mailutils/opool.h (MU_OPOOL_DEFAULT) (MU_OPOOL_ENOMEMABRT): New defines. (mu_opool_create): Change meaning of the 2nd argument. All uses updated. (mu_opool_free, mu_opool_dup): New proto. * libmailutils/base/opool.c (_mu_opool) <memerr>: Replace with flags. <head,tail,free>: Rename. (mu_opool_free, mu_opool_dup): New functions. (mu_opool_head): Bugfix.
-rw-r--r--NEWS4
-rw-r--r--comsat/action.c2
-rw-r--r--configure.ac2
-rw-r--r--include/mailutils/opool.h18
-rw-r--r--lib/mailcap.c2
-rw-r--r--libmailutils/base/opool.c166
-rw-r--r--libmailutils/cfg/lexer.l2
-rw-r--r--libmailutils/cfg/parser.y2
-rw-r--r--libmailutils/url/urlstr.c2
-rw-r--r--libproto/pop/mbox.c2
-rw-r--r--mh/burst.c2
-rw-r--r--mh/mh_fmtgram.y2
-rw-r--r--mh/mh_format.c2
-rw-r--r--mh/mhn.c10
-rw-r--r--mh/prompter.c2
-rw-r--r--mh/repl.c2
-rw-r--r--mh/whatnowenv.c2
-rw-r--r--mimeview/mimetypes.l2
-rw-r--r--mu/dbm.c2
19 files changed, 140 insertions, 88 deletions
diff --git a/NEWS b/NEWS
index 40768fae3..4aa8610a1 100644
--- a/NEWS
+++ b/NEWS
@@ -1,11 +1,11 @@
-GNU mailutils NEWS -- history of user-visible changes. 2016-10-28
+GNU mailutils NEWS -- history of user-visible changes. 2016-10-30
Copyright (C) 2002-2016 Free Software Foundation, Inc.
See the end of file for copying conditions.
Please send mailutils bug reports to <bug-mailutils@gnu.org>.
-Version 2.99.992 (Git)
+Version 2.99.993 (Git)
This version is a major rewrite of GNU Mailutils. Quite a few parts
of the basic framework were rewritten from scratch, while some others
diff --git a/comsat/action.c b/comsat/action.c
index 0582637b2..dc5703274 100644
--- a/comsat/action.c
+++ b/comsat/action.c
@@ -144,7 +144,7 @@ expand_line (const char *str, mu_message_t msg)
if (!*str)
return NULL;
- mu_opool_create (&pool, 1);
+ mu_opool_create (&pool, MU_OPOOL_ENOMEMABRT);
for (p = str; *p; p++)
{
switch (*p)
diff --git a/configure.ac b/configure.ac
index b8161ec7a..92ac4a15e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -16,7 +16,7 @@ dnl You should have received a copy of the GNU General Public License along
dnl with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
AC_PREREQ(2.63)
-AC_INIT([GNU Mailutils], [2.99.992], [bug-mailutils@gnu.org], [mailutils],
+AC_INIT([GNU Mailutils], [2.99.993], [bug-mailutils@gnu.org], [mailutils],
[http://mailutils.org])
AC_CONFIG_SRCDIR([libmailutils/mailbox/mailbox.c])
AC_CONFIG_AUX_DIR([build-aux])
diff --git a/include/mailutils/opool.h b/include/mailutils/opool.h
index bc68e4aab..63c5a38f2 100644
--- a/include/mailutils/opool.h
+++ b/include/mailutils/opool.h
@@ -24,10 +24,12 @@
# define MU_OPOOL_BUCKET_SIZE 1024
#endif
-/* Create an object pool. If MEMERR is not 0, any operation of the
- resulting pool (including mu_opool_create itself) will abort on
- not enough memory condition, using mu_alloc_die. */
-int mu_opool_create (mu_opool_t *pret, int memerr);
+/* Flags for mu_opool_create call: */
+#define MU_OPOOL_DEFAULT 0
+#define MU_OPOOL_ENOMEMABRT 0x01 /* Abort on ENOMEM error */
+
+/* Create an object pool. */
+int mu_opool_create (mu_opool_t *pret, int flags);
int mu_opool_set_bucket_size (mu_opool_t opool, size_t size);
int mu_opool_get_bucket_size (mu_opool_t opool, size_t *psize);
@@ -39,6 +41,10 @@ int mu_opool_union (mu_opool_t *dst, mu_opool_t *src);
begin a new object. */
void mu_opool_clear (mu_opool_t opool);
+/* Free object OBJ from the pool. If OBJ is NULL, free all created objects,
+ including the one being built */
+void mu_opool_free (mu_opool_t pool, void *obj);
+
/* Destroy the pool, reclaim any memory associated with it. */
void mu_opool_destroy (mu_opool_t *popool);
@@ -80,6 +86,10 @@ void *mu_opool_head (mu_opool_t opool, size_t *psize);
return p; */
void *mu_opool_finish (mu_opool_t opool, size_t *psize);
+/* Append SIZE bytes from DATA to the pool and return the pointer to the
+ created object. */
+void *mu_opool_dup (mu_opool_t pool, void const *data, size_t size);
+
int mu_opool_get_iterator (mu_opool_t opool, mu_iterator_t *piterator);
#endif
diff --git a/lib/mailcap.c b/lib/mailcap.c
index 02f189413..503390c8e 100644
--- a/lib/mailcap.c
+++ b/lib/mailcap.c
@@ -686,7 +686,7 @@ display_stream_mailcap (const char *ident, mu_stream_t stream, mu_header_t hdr,
mailcap_path = mailcap_path_tmp;
}
- mu_opool_create (&expand_pool, 1);
+ mu_opool_create (&expand_pool, MU_OPOOL_ENOMEMABRT);
ws.ws_delim = ":";
if (mu_wordsplit (mailcap_path, &ws,
diff --git a/libmailutils/base/opool.c b/libmailutils/base/opool.c
index 77257f2c5..5e19081ac 100644
--- a/libmailutils/base/opool.c
+++ b/libmailutils/base/opool.c
@@ -41,11 +41,11 @@ struct mu_opool_bucket
struct _mu_opool
{
- int memerr;
- size_t bucket_size;
- size_t itr_count;
- struct mu_opool_bucket *head, *tail;
- struct mu_opool_bucket *free;
+ int flags; /* Flag bits */
+ size_t bucket_size; /* Default bucket size */
+ size_t itr_count; /* Number of iterators created for this pool */
+ struct mu_opool_bucket *bkt_head, *bkt_tail;
+ struct mu_opool_bucket *bkt_fini; /* List of finished objects */
};
static struct mu_opool_bucket *
@@ -54,7 +54,7 @@ alloc_bucket (struct _mu_opool *opool, size_t size)
struct mu_opool_bucket *p = malloc (sizeof (*p) + size);
if (!p)
{
- if (opool->memerr)
+ if (opool->flags & MU_OPOOL_ENOMEMABRT)
mu_alloc_die ();
}
else
@@ -73,11 +73,11 @@ alloc_pool (mu_opool_t opool, size_t size)
struct mu_opool_bucket *p = alloc_bucket (opool, opool->bucket_size);
if (!p)
return ENOMEM;
- if (opool->tail)
- opool->tail->next = p;
+ if (opool->bkt_tail)
+ opool->bkt_tail->next = p;
else
- opool->head = p;
- opool->tail = p;
+ opool->bkt_head = p;
+ opool->bkt_tail = p;
return 0;
}
@@ -86,32 +86,32 @@ copy_chars (mu_opool_t opool, const char *str, size_t n, size_t *psize)
{
size_t rest;
- if (!opool->head || opool->tail->level == opool->tail->size)
+ if (!opool->bkt_head || opool->bkt_tail->level == opool->bkt_tail->size)
if (alloc_pool (opool, opool->bucket_size))
return ENOMEM;
- rest = opool->tail->size - opool->tail->level;
+ rest = opool->bkt_tail->size - opool->bkt_tail->level;
if (n > rest)
n = rest;
- memcpy (opool->tail->buf + opool->tail->level, str, n);
- opool->tail->level += n;
+ memcpy (opool->bkt_tail->buf + opool->bkt_tail->level, str, n);
+ opool->bkt_tail->level += n;
*psize = n;
return 0;
}
int
-mu_opool_create (mu_opool_t *pret, int memerr)
+mu_opool_create (mu_opool_t *pret, int flags)
{
struct _mu_opool *x = malloc (sizeof (x[0]));
if (!x)
{
- if (memerr)
+ if (flags & MU_OPOOL_ENOMEMABRT)
mu_alloc_die ();
return ENOMEM;
}
- x->memerr = memerr;
+ x->flags = flags;
x->bucket_size = MU_OPOOL_BUCKET_SIZE;
x->itr_count = 0;
- x->head = x->tail = x->free = 0;
+ x->bkt_head = x->bkt_tail = x->bkt_fini = NULL;
*pret = x;
return 0;
}
@@ -140,11 +140,11 @@ mu_opool_clear (mu_opool_t opool)
if (!opool)
return;
- if (opool->tail)
+ if (opool->bkt_tail)
{
- opool->tail->next = opool->free;
- opool->free = opool->head;
- opool->head = opool->tail = NULL;
+ opool->bkt_tail->next = opool->bkt_fini;
+ opool->bkt_fini = opool->bkt_head;
+ opool->bkt_head = opool->bkt_tail = NULL;
}
}
@@ -156,15 +156,15 @@ mu_opool_destroy (mu_opool_t *popool)
{
mu_opool_t opool = *popool;
mu_opool_clear (opool);
- for (p = opool->free; p; )
+ for (p = opool->bkt_fini; p; )
{
struct mu_opool_bucket *next = p->next;
free (p);
p = next;
}
free (opool);
+ *popool = NULL;
}
- *popool = NULL;
}
int
@@ -174,13 +174,13 @@ mu_opool_alloc (mu_opool_t opool, size_t size)
{
size_t rest;
- if (!opool->head || opool->tail->level == opool->tail->size)
+ if (!opool->bkt_head || opool->bkt_tail->level == opool->bkt_tail->size)
if (alloc_pool (opool, opool->bucket_size))
return ENOMEM;
- rest = opool->tail->size - opool->tail->level;
+ rest = opool->bkt_tail->size - opool->bkt_tail->level;
if (size < rest)
rest = size;
- opool->tail->level += rest;
+ opool->bkt_tail->level += rest;
size -= rest;
}
return 0;
@@ -218,7 +218,7 @@ mu_opool_size (mu_opool_t opool)
{
size_t size = 0;
struct mu_opool_bucket *p;
- for (p = opool->head; p; p = p->next)
+ for (p = opool->bkt_head; p; p = p->next)
size += p->level;
return size;
}
@@ -230,7 +230,7 @@ mu_opool_copy (mu_opool_t opool, void *buf, size_t size)
size_t total = 0;
struct mu_opool_bucket *p;
- for (p = opool->head; p && total < size; p = p->next)
+ for (p = opool->bkt_head; p && total < size; p = p->next)
{
size_t cpsize = size - total;
if (cpsize > p->level)
@@ -249,27 +249,28 @@ mu_opool_coalesce (mu_opool_t opool, size_t *psize)
if (opool->itr_count)
return MU_ERR_FAILURE;
- if (opool->head && opool->head->next == NULL)
- size = opool->head->level;
- else {
- struct mu_opool_bucket *bucket;
- struct mu_opool_bucket *p;
+ if (opool->bkt_head && opool->bkt_head->next == NULL)
+ size = opool->bkt_head->level;
+ else
+ {
+ struct mu_opool_bucket *bucket;
+ struct mu_opool_bucket *p;
- size = mu_opool_size (opool);
+ size = mu_opool_size (opool);
- bucket = alloc_bucket (opool, size);
- if (!bucket)
- return ENOMEM;
- for (p = opool->head; p; )
- {
- struct mu_opool_bucket *next = p->next;
- memcpy (bucket->buf + bucket->level, p->buf, p->level);
- bucket->level += p->level;
- free (p);
- p = next;
- }
- opool->head = opool->tail = bucket;
- }
+ bucket = alloc_bucket (opool, size);
+ if (!bucket)
+ return ENOMEM;
+ for (p = opool->bkt_head; p; )
+ {
+ struct mu_opool_bucket *next = p->next;
+ memcpy (bucket->buf + bucket->level, p->buf, p->level);
+ bucket->level += p->level;
+ free (p);
+ p = next;
+ }
+ opool->bkt_head = opool->bkt_tail = bucket;
+ }
if (psize)
*psize = size;
return 0;
@@ -278,9 +279,9 @@ mu_opool_coalesce (mu_opool_t opool, size_t *psize)
void *
mu_opool_head (mu_opool_t opool, size_t *psize)
{
- if (*psize)
- *psize = opool->head ? opool->head->level : 0;
- return opool->head ? opool->head->buf : NULL;
+ if (psize)
+ *psize = opool->bkt_head ? opool->bkt_head->level : 0;
+ return opool->bkt_head ? opool->bkt_head->buf : NULL;
}
void *
@@ -289,7 +290,48 @@ mu_opool_finish (mu_opool_t opool, size_t *psize)
if (mu_opool_coalesce (opool, psize))
return NULL;
mu_opool_clear (opool);
- return opool->free->buf;
+ return opool->bkt_fini->buf;
+}
+
+void
+mu_opool_free (mu_opool_t pool, void *obj)
+{
+ if (!pool)
+ return;
+ if (!obj)
+ {
+ if (pool->bkt_head)
+ mu_opool_finish (pool, NULL);
+ while (pool->bkt_fini)
+ {
+ struct mu_opool_bucket *next = pool->bkt_fini->next;
+ free (pool->bkt_fini);
+ pool->bkt_fini = next;
+ }
+ }
+ else
+ {
+ struct mu_opool_bucket *bucket = pool->bkt_fini, **pprev = &pool->bkt_fini;
+ while (bucket)
+ {
+ if (bucket->buf == obj)
+ {
+ *pprev = bucket->next;
+ free (bucket);
+ return;
+ }
+ pprev = &bucket->next;
+ bucket = bucket->next;
+ }
+ }
+}
+
+void *
+mu_opool_dup (mu_opool_t pool, void const *data, size_t size)
+{
+ if (mu_opool_append (pool, data, size))
+ return NULL;
+ return mu_opool_finish (pool, NULL);
}
int
@@ -314,20 +356,20 @@ mu_opool_union (mu_opool_t *pdst, mu_opool_t *psrc)
else
dst = *pdst;
- if (dst->tail)
- dst->tail->next = src->head;
+ if (dst->bkt_tail)
+ dst->bkt_tail->next = src->bkt_head;
else
- dst->head = src->head;
- dst->tail = src->tail;
+ dst->bkt_head = src->bkt_head;
+ dst->bkt_tail = src->bkt_tail;
- if (src->free)
+ if (src->bkt_fini)
{
struct mu_opool_bucket *p;
- for (p = src->free; p->next; p = p->next)
+ for (p = src->bkt_fini; p->next; p = p->next)
;
- p->next = dst->free;
- dst->free = src->free;
+ p->next = dst->bkt_fini;
+ dst->bkt_fini = src->bkt_fini;
}
free (src);
@@ -347,7 +389,7 @@ static int
opitr_first (void *owner)
{
struct opool_iterator *itr = owner;
- itr->cur = itr->opool->head;
+ itr->cur = itr->opool->bkt_head;
return 0;
}
@@ -434,7 +476,7 @@ mu_opool_get_iterator (mu_opool_t opool, mu_iterator_t *piterator)
if (!itr)
return ENOMEM;
itr->opool = opool;
- itr->cur = opool->head;
+ itr->cur = opool->bkt_head;
status = mu_iterator_create (&iterator, itr);
if (status)
diff --git a/libmailutils/cfg/lexer.l b/libmailutils/cfg/lexer.l
index b6c49ecc1..2ecefce87 100644
--- a/libmailutils/cfg/lexer.l
+++ b/libmailutils/cfg/lexer.l
@@ -200,7 +200,7 @@ void
_mu_line_begin ()
{
if (!pool)
- mu_opool_create (&pool, 1);
+ mu_opool_create (&pool, MU_OPOOL_ENOMEMABRT);
else
mu_opool_clear (pool);
}
diff --git a/libmailutils/cfg/parser.y b/libmailutils/cfg/parser.y
index a530f10f5..9ad8e8d60 100644
--- a/libmailutils/cfg/parser.y
+++ b/libmailutils/cfg/parser.y
@@ -1110,7 +1110,7 @@ mu_cfg_tree_create (struct mu_cfg_tree **ptree)
struct mu_cfg_tree *tree = calloc (1, sizeof *tree);
if (!tree)
return errno;
- mu_opool_create (&tree->pool, 1);
+ mu_opool_create (&tree->pool, MU_OPOOL_ENOMEMABRT);
*ptree = tree;
return 0;
}
diff --git a/libmailutils/url/urlstr.c b/libmailutils/url/urlstr.c
index c57576a03..34c69f36a 100644
--- a/libmailutils/url/urlstr.c
+++ b/libmailutils/url/urlstr.c
@@ -111,7 +111,7 @@ mu_url_sget_name (const mu_url_t url, const char **retptr)
char *ptr, *newname;
size_t size;
- rc = mu_opool_create (&pool, 0);
+ rc = mu_opool_create (&pool, MU_OPOOL_DEFAULT);
if (rc)
return rc;
rc = url_reconstruct_to_pool (url, pool);
diff --git a/libproto/pop/mbox.c b/libproto/pop/mbox.c
index 64e375a81..b877b6f98 100644
--- a/libproto/pop/mbox.c
+++ b/libproto/pop/mbox.c
@@ -654,7 +654,7 @@ pop_header_blurb (mu_stream_t stream, size_t maxlines,
size_t n;
size_t nlines = 0;
- status = mu_opool_create (&opool, 0);
+ status = mu_opool_create (&opool, MU_OPOOL_DEFAULT);
if (status)
return status;
diff --git a/mh/burst.c b/mh/burst.c
index 173a8f719..4d5a3b791 100644
--- a/mh/burst.c
+++ b/mh/burst.c
@@ -678,7 +678,7 @@ main (int argc, char **argv)
mu_attribute_set_deleted (attr);
}
mu_mailbox_expunge (tmpbox);
- mu_opool_create (&pool, 1);
+ mu_opool_create (&pool, MU_OPOOL_ENOMEMABRT);
}
else
tmpbox = mbox;
diff --git a/mh/mh_fmtgram.y b/mh/mh_fmtgram.y
index 018bdcebf..9b690b7b9 100644
--- a/mh/mh_fmtgram.y
+++ b/mh/mh_fmtgram.y
@@ -499,7 +499,7 @@ mh_format_parse (char *format_str, mh_format_t *fmt)
if (p)
yydebug = 1;
start = curp = format_str;
- mu_opool_create (&tokpool, 1);
+ mu_opool_create (&tokpool, MU_OPOOL_ENOMEMABRT);
format.prog = NULL;
format.progsize = 0;
pc = 0;
diff --git a/mh/mh_format.c b/mh/mh_format.c
index 77e4e8531..c74a260b9 100644
--- a/mh/mh_format.c
+++ b/mh/mh_format.c
@@ -490,7 +490,7 @@ mh_format (mh_format_t *fmt, mu_message_t msg, size_t msgno,
mach.width = width - 1; /* Count the newline */
mach.pc = 1;
- mu_opool_create (&mach.pool, 1);
+ mu_opool_create (&mach.pool, MU_OPOOL_ENOMEMABRT);
mu_list_create (&mach.addrlist);
reset_fmt_defaults (&mach);
diff --git a/mh/mhn.c b/mh/mhn.c
index b3c2cb776..2ebd8c383 100644
--- a/mh/mhn.c
+++ b/mh/mhn.c
@@ -461,7 +461,7 @@ mhn_compose_command (char *typestr, char *typeargs, int *flags, char *file)
%F %f, and stdout is not redirected
%s subtype */
- mu_opool_create (&pool, 1);
+ mu_opool_create (&pool, MU_OPOOL_ENOMEMABRT);
p = mu_str_skip_class (str, MU_CTYPE_SPACE);
@@ -642,7 +642,7 @@ mhn_show_command (mu_message_t msg, msg_part_t part, int *flags,
%s subtype
%d content description */
- mu_opool_create (&pool, 1);
+ mu_opool_create (&pool, MU_OPOOL_ENOMEMABRT);
p = mu_str_skip_class (str, MU_CTYPE_SPACE);
@@ -814,7 +814,7 @@ mhn_store_command (mu_message_t msg, msg_part_t part, const char *name,
%p part
%s subtype */
- mu_opool_create (&pool, 1);
+ mu_opool_create (&pool, MU_OPOOL_ENOMEMABRT);
for (p = str; *p; p++)
{
@@ -1883,7 +1883,7 @@ parse_type_command (char **pcmd, struct compose_env *env, mu_header_t hdr)
return 1;
}
- mu_opool_create (&pool, 1);
+ mu_opool_create (&pool, MU_OPOOL_ENOMEMABRT);
mu_opool_appendz (pool, type);
mu_opool_append_char (pool, '/');
@@ -2050,7 +2050,7 @@ edit_extern (char *cmd, struct compose_env *env, mu_message_t *msg, int level)
mu_message_get_header (*msg, &hdr);
- mu_opool_create (&pool, 1);
+ mu_opool_create (&pool, MU_OPOOL_ENOMEMABRT);
mu_opool_append (pool, EXTCONTENT, sizeof (EXTCONTENT) - 1);
*--rest = ';'; /* FIXME */
rc = parse_content_type (env, pool, &rest, &id, NULL);
diff --git a/mh/prompter.c b/mh/prompter.c
index 5c4405fc5..2efde12f0 100644
--- a/mh/prompter.c
+++ b/mh/prompter.c
@@ -156,7 +156,7 @@ main (int argc, char **argv)
mu_opool_t opool;
const char *prompt = name;
- mu_opool_create (&opool, 1);
+ mu_opool_create (&opool, MU_OPOOL_ENOMEMABRT);
do
{
size_t len;
diff --git a/mh/repl.c b/mh/repl.c
index 13fa8c9eb..fefa6a28a 100644
--- a/mh/repl.c
+++ b/mh/repl.c
@@ -73,7 +73,7 @@ set_fcc (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
{
if (!has_fcc)
{
- mu_opool_create (&fcc_pool, 1);
+ mu_opool_create (&fcc_pool, MU_OPOOL_ENOMEMABRT);
has_fcc = 1;
}
else
diff --git a/mh/whatnowenv.c b/mh/whatnowenv.c
index f4af15622..81b9368ce 100644
--- a/mh/whatnowenv.c
+++ b/mh/whatnowenv.c
@@ -84,7 +84,7 @@ mh_whatnow_env_to_environ (struct mh_whatnow_env *wh)
int mrange = 0;
const char *s;
- mu_opool_create (&opool, 1);
+ mu_opool_create (&opool, MU_OPOOL_ENOMEMABRT);
mu_list_get_iterator (wh->anno_list, &itr);
for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
mu_iterator_next (itr))
diff --git a/mimeview/mimetypes.l b/mimeview/mimetypes.l
index 995b8de6f..9cdbf9d21 100644
--- a/mimeview/mimetypes.l
+++ b/mimeview/mimetypes.l
@@ -172,7 +172,7 @@ mimetypes_open (const char *name)
return -1;
}
line_num = 1;
- mu_opool_create (&pool, 1);
+ mu_opool_create (&pool, MU_OPOOL_ENOMEMABRT);
return 0;
}
diff --git a/mu/dbm.c b/mu/dbm.c
index 531a3cf54..0722456ea 100644
--- a/mu/dbm.c
+++ b/mu/dbm.c
@@ -610,7 +610,7 @@ newfmt_init (struct xfer_format *fmt, const char *version,
else
{
mu_opool_t pool;
- rc = mu_opool_create (&pool, 0);
+ rc = mu_opool_create (&pool, MU_OPOOL_DEFAULT);
if (rc)
{
mu_diag_funcall (MU_DIAG_ERROR, "mu_opool_create",

Return to:

Send suggestions and report system problems to the System administrator.