From 84adefa331c4159d432d22840663c38f155cd4c1 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Fri, 20 Nov 2009 14:54:40 +0000 Subject: The R13B03 release. --- lib/erl_interface/src/registry/hash.h | 47 ++++ lib/erl_interface/src/registry/hash_dohash.c | 45 ++++ lib/erl_interface/src/registry/hash_foreach.c | 44 ++++ lib/erl_interface/src/registry/hash_freetab.c | 58 +++++ lib/erl_interface/src/registry/hash_insert.c | 108 +++++++++ lib/erl_interface/src/registry/hash_isprime.c | 57 +++++ lib/erl_interface/src/registry/hash_lookup.c | 42 ++++ lib/erl_interface/src/registry/hash_newtab.c | 52 +++++ lib/erl_interface/src/registry/hash_remove.c | 87 +++++++ lib/erl_interface/src/registry/hash_resize.c | 67 ++++++ lib/erl_interface/src/registry/hash_rlookup.c | 43 ++++ lib/erl_interface/src/registry/reg.h | 46 ++++ lib/erl_interface/src/registry/reg_close.c | 68 ++++++ lib/erl_interface/src/registry/reg_delete.c | 36 +++ lib/erl_interface/src/registry/reg_dirty.c | 36 +++ lib/erl_interface/src/registry/reg_dump.c | 321 +++++++++++++++++++++++++ lib/erl_interface/src/registry/reg_free.c | 47 ++++ lib/erl_interface/src/registry/reg_get.c | 94 ++++++++ lib/erl_interface/src/registry/reg_getf.c | 35 +++ lib/erl_interface/src/registry/reg_geti.c | 35 +++ lib/erl_interface/src/registry/reg_getp.c | 39 ++++ lib/erl_interface/src/registry/reg_gets.c | 38 +++ lib/erl_interface/src/registry/reg_make.c | 49 ++++ lib/erl_interface/src/registry/reg_open.c | 41 ++++ lib/erl_interface/src/registry/reg_purge.c | 76 ++++++ lib/erl_interface/src/registry/reg_resize.c | 36 +++ lib/erl_interface/src/registry/reg_restore.c | 323 ++++++++++++++++++++++++++ lib/erl_interface/src/registry/reg_set.c | 78 +++++++ lib/erl_interface/src/registry/reg_setf.c | 61 +++++ lib/erl_interface/src/registry/reg_seti.c | 62 +++++ lib/erl_interface/src/registry/reg_setp.c | 62 +++++ lib/erl_interface/src/registry/reg_sets.c | 65 ++++++ lib/erl_interface/src/registry/reg_stat.c | 41 ++++ lib/erl_interface/src/registry/reg_tabstat.c | 37 +++ 34 files changed, 2376 insertions(+) create mode 100644 lib/erl_interface/src/registry/hash.h create mode 100644 lib/erl_interface/src/registry/hash_dohash.c create mode 100644 lib/erl_interface/src/registry/hash_foreach.c create mode 100644 lib/erl_interface/src/registry/hash_freetab.c create mode 100644 lib/erl_interface/src/registry/hash_insert.c create mode 100644 lib/erl_interface/src/registry/hash_isprime.c create mode 100644 lib/erl_interface/src/registry/hash_lookup.c create mode 100644 lib/erl_interface/src/registry/hash_newtab.c create mode 100644 lib/erl_interface/src/registry/hash_remove.c create mode 100644 lib/erl_interface/src/registry/hash_resize.c create mode 100644 lib/erl_interface/src/registry/hash_rlookup.c create mode 100644 lib/erl_interface/src/registry/reg.h create mode 100644 lib/erl_interface/src/registry/reg_close.c create mode 100644 lib/erl_interface/src/registry/reg_delete.c create mode 100644 lib/erl_interface/src/registry/reg_dirty.c create mode 100644 lib/erl_interface/src/registry/reg_dump.c create mode 100644 lib/erl_interface/src/registry/reg_free.c create mode 100644 lib/erl_interface/src/registry/reg_get.c create mode 100644 lib/erl_interface/src/registry/reg_getf.c create mode 100644 lib/erl_interface/src/registry/reg_geti.c create mode 100644 lib/erl_interface/src/registry/reg_getp.c create mode 100644 lib/erl_interface/src/registry/reg_gets.c create mode 100644 lib/erl_interface/src/registry/reg_make.c create mode 100644 lib/erl_interface/src/registry/reg_open.c create mode 100644 lib/erl_interface/src/registry/reg_purge.c create mode 100644 lib/erl_interface/src/registry/reg_resize.c create mode 100644 lib/erl_interface/src/registry/reg_restore.c create mode 100644 lib/erl_interface/src/registry/reg_set.c create mode 100644 lib/erl_interface/src/registry/reg_setf.c create mode 100644 lib/erl_interface/src/registry/reg_seti.c create mode 100644 lib/erl_interface/src/registry/reg_setp.c create mode 100644 lib/erl_interface/src/registry/reg_sets.c create mode 100644 lib/erl_interface/src/registry/reg_stat.c create mode 100644 lib/erl_interface/src/registry/reg_tabstat.c (limited to 'lib/erl_interface/src/registry') diff --git a/lib/erl_interface/src/registry/hash.h b/lib/erl_interface/src/registry/hash.h new file mode 100644 index 0000000000..3886e8664b --- /dev/null +++ b/lib/erl_interface/src/registry/hash.h @@ -0,0 +1,47 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#ifndef _HASH_H +#define _HASH_H + +#include + +#include "ei.h" /* We need our types there */ + +#define ei_hash_size(tab) ((tab)->size) +#define ei_hash_count(tab) ((tab)->count) + +#define ALIGN_QUAD 0x7 +#define ei_align(size) while (((unsigned)size) & ALIGN_QUAD) (size)++ + +int ei_isprime(int n); +int ei_dohash(const char *key); +void *ei_hash_lookup(ei_hash *tab, const char *key); +const char *ei_hash_rlookup(ei_hash *tab, const void *value); +int ei_hash_foreach(ei_hash *tab, int (*f)(const char *key, const void *value)); +void *ei_hash_insert(ei_hash *tab, const char *key, const void *value); +void *ei_hash_remove(ei_hash *tab, const char *key); +ei_hash *ei_hash_newtab(int tabsize); +ei_hash *ei_hash_resize(ei_hash *oldtab, int newsize); +int ei_hash_freetab(ei_hash *tab, void (*f)(void *)); +void ei_hash_stats(ei_hash *tab, FILE *out); +void ei_hash_bfree(ei_hash *tab, ei_bucket *b); + +#endif /* _HASH_H */ diff --git a/lib/erl_interface/src/registry/hash_dohash.c b/lib/erl_interface/src/registry/hash_dohash.c new file mode 100644 index 0000000000..f672dce9b3 --- /dev/null +++ b/lib/erl_interface/src/registry/hash_dohash.c @@ -0,0 +1,45 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#include "hash.h" + +/* This is hashpjw, from the dragon book */ +/* Note that this function is only used as a default hash function. + * All calls are made through the hash pointer in the tab structure. + * The only place this function is explicitly referenced is in + * hash_newtab(); Users can use hash_setfunc() to change the hash function. + */ +int ei_dohash(const char *key) +{ + const char *s; + unsigned h = 0; + unsigned g; + + for (s=key; *s; s++) { + h = (h << 4) + *s; + if ((g = (h & 0xf0000000))) { /* assumes 32-bit int */ + h = h^(g >> 24); + h = h^g; + } + } + return h; +} + + diff --git a/lib/erl_interface/src/registry/hash_foreach.c b/lib/erl_interface/src/registry/hash_foreach.c new file mode 100644 index 0000000000..77afc7ade1 --- /dev/null +++ b/lib/erl_interface/src/registry/hash_foreach.c @@ -0,0 +1,44 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#include "hash.h" + +/* perform f(key,value) on each key-value pair in the table. + * hash_foreach() will traverse the table until the end is reached or + * until f() returns a non-zero value, whichever comes first. The + * return value from f() will be returned to the caller, or 0 if the + * entire table was traversed. + */ +int ei_hash_foreach(ei_hash *tab, int (*f)(const char *key, const void *value)) +{ + ei_bucket *b; + int i; + int r; + + for (i=0; isize; i++) { + b=tab->tab[i]; + while (b) { + if (f && (r=f(b->key,b->value))) return r; + b = b->next; + } + } + return 0; +} + diff --git a/lib/erl_interface/src/registry/hash_freetab.c b/lib/erl_interface/src/registry/hash_freetab.c new file mode 100644 index 0000000000..cd428e55cf --- /dev/null +++ b/lib/erl_interface/src/registry/hash_freetab.c @@ -0,0 +1,58 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#include +#include "hash.h" + +/* remove all the key-values from a table. The + * values are removed with + * the user-provided function f. + */ +int ei_hash_freetab(ei_hash *tab, void (*f)(void *)) +{ + ei_bucket *b, *next; + int i; + + for (i=0; isize; i++) { + b=tab->tab[i]; + while (b) { + next = b->next; + + if (f) f((void *)b->value); + + /* no point in saving these buckets on freelist */ + free(b); + b = next; + } + } + + /* remove the freelist */ + b = tab->freelist; + while (b) { + next = b->next; + free(b); + b = next; + } + + /* remove the table */ + free(tab); + + return 0; +} diff --git a/lib/erl_interface/src/registry/hash_insert.c b/lib/erl_interface/src/registry/hash_insert.c new file mode 100644 index 0000000000..dbe76282ae --- /dev/null +++ b/lib/erl_interface/src/registry/hash_insert.c @@ -0,0 +1,108 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#include +#include +#include "hash.h" + +/* this function returns a bucket - from the freelist if one was found + * there, or from malloc(). Only "small" buckets, i.e. those whose + * keys are short enough to be stored in the bucket itself, are saved + * on the freelist. + */ +static ei_bucket *ei_hash_bmalloc(ei_hash *tab) +{ + ei_bucket *new; + + if (tab->freelist) { + new = tab->freelist; + tab->freelist = new->next; + /* fprintf(stderr,"getting bucket from freelist\n"); */ + } + else { + new = malloc(sizeof(*new)); + /* fprintf(stderr,"allocating new (small) bucket\n"); */ + } + + return new; +} + +/* insert a new key-value pair. The old value (if any) is returned. If + * the malloc fails the function returns NULL. This is potentially a + * problem since the function returns the same thing when malloc fails + * as when a item is inserted that did not previously exist in the + * table. */ +void *ei_hash_insert(ei_hash *tab, const char *key, const void *value) +{ + const void *oldval=NULL; + ei_bucket *b=NULL; + int h, rh; + + rh = tab->hash(key); + h = rh % tab->size; + + b=tab->tab[h]; + while (b) { + if ((rh == b->rawhash) && (!strcmp(key,b->key))) + break; + b=b->next; + } + + if (b) { + /* replace existing value, return old value */ + oldval = b->value; + b->value = value; + } + else { + int keylen = strlen(key); + + /* this element is new */ + if (keylen < EI_SMALLKEY) { + /* short keys stored directly in bucket */ + /* try to get bucket from freelist */ + if ((b = ei_hash_bmalloc(tab)) == NULL) return NULL; + b->key = b->keybuf; + } + else { + /* for longer keys we allocate space */ + int keypos=sizeof(*b); + + ei_align(keypos); + if ((b = malloc(keypos+keylen+1)) == NULL) return NULL; + b->key = (char *)b + keypos; + /* fprintf(stderr,"allocating new (large) bucket\n"); */ + } + + /* fill in the blanks */ + b->rawhash = rh; + strcpy((char *)b->key,key); + b->value = value; + + /* some statistiscs */ + if (!tab->tab[h]) tab->npos++; + tab->nelem++; + + /* link in the new element */ + b->next = tab->tab[h]; + tab->tab[h] = b; + } + return (void *)oldval; +} + diff --git a/lib/erl_interface/src/registry/hash_isprime.c b/lib/erl_interface/src/registry/hash_isprime.c new file mode 100644 index 0000000000..cdef2591ab --- /dev/null +++ b/lib/erl_interface/src/registry/hash_isprime.c @@ -0,0 +1,57 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#include "hash.h" + +/* this is a general prime factoring function + * we get one prime factor each time we call it + * we only use it here to determine if n is prime, + * by checking if factor(n) == n . + */ +static int factor(int n) +{ + /* FIXME problem for threaded?! */ + static int a[] = { 0, 4, 1, 2, 0, 2 }; + static int m = 0; + static int d = 0; + + if (n) { + m = n; + d = 2; + } + + while ((d*d) <= m) { + if (!(m%d)) { + m /= d; + return d; + } + d += a[d%6]; + } + n = m; + m = 0; + + return n; +} + +/* true if n prime */ +int ei_isprime(int n) +{ + return (n == factor(n)); +} diff --git a/lib/erl_interface/src/registry/hash_lookup.c b/lib/erl_interface/src/registry/hash_lookup.c new file mode 100644 index 0000000000..0a466cc519 --- /dev/null +++ b/lib/erl_interface/src/registry/hash_lookup.c @@ -0,0 +1,42 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#include +#include +#include "hash.h" + +void *ei_hash_lookup(ei_hash *tab, const char *key) +{ + int h, rh; + ei_bucket *b=NULL; + + rh = tab->hash(key); + h = rh % tab->size; + + b=tab->tab[h]; + while (b) { + if ((rh == b->rawhash) && (!strcmp(key,b->key))) + return (void *)b->value; + b=b->next; + } + return NULL; +} + + diff --git a/lib/erl_interface/src/registry/hash_newtab.c b/lib/erl_interface/src/registry/hash_newtab.c new file mode 100644 index 0000000000..b900de1f69 --- /dev/null +++ b/lib/erl_interface/src/registry/hash_newtab.c @@ -0,0 +1,52 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#include +#include +#include "hash.h" + +ei_hash *ei_hash_newtab(int tabsize) +{ + ei_hash *tab=NULL; + int bucketpos=sizeof(*tab); + + /* make sure size is odd, then increase until prime */ + tabsize |= 0x1; + while (!ei_isprime(tabsize)) tabsize +=2; + + /* we will only do one malloc, so "sizeof(*tab)" + * must be adjusted to align tab->tab properly + */ + ei_align(bucketpos); + + /* single malloc, then fill in all fields */ + if ((tab = malloc(bucketpos + (tabsize * (sizeof(*(tab->tab))))))) { + tab->tab = (ei_bucket **)((char *)tab + bucketpos); + memset(tab->tab,0,tabsize*sizeof(*(tab->tab))); + tab->hash = ei_dohash; + tab->size = tabsize; + tab->npos = 0; + tab->nelem = 0; + tab->freelist = NULL; + } + + return tab; +} + diff --git a/lib/erl_interface/src/registry/hash_remove.c b/lib/erl_interface/src/registry/hash_remove.c new file mode 100644 index 0000000000..cebe00da1c --- /dev/null +++ b/lib/erl_interface/src/registry/hash_remove.c @@ -0,0 +1,87 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#include +#include +#include "hash.h" + +/* free a hash bucket. If the bucket contained a long key (more that + * EI_SMALLKEY) the bucket is thrown away (really freed). If the + * bucket contained a short key, then it can be saved on the freelist + * for later use. Buckets with short keys have (key == keybuf). + */ +void ei_hash_bfree(ei_hash *tab, ei_bucket *b) +{ + if (!b) return; + + /* we throw away buckets with long keys (i.e. non-standard buckets) */ + if (b->key != b->keybuf) { + /* fprintf(stderr,"freeing bucket with long key (%s)\n",b->key); */ + free(b); + } + + else { + /* others we save on (tab-local) freelist */ + /* fprintf(stderr,"saving bucket with short key (%s)\n",b->key); */ + b->next = tab->freelist; + tab->freelist = b; + } + + return; +} + +void *ei_hash_remove(ei_hash *tab, const char *key) +{ + ei_bucket *b=NULL, *tmp=NULL; + const void *oldval=NULL; + int h, rh; + + rh = tab->hash(key); + h = rh % tab->size; + + /* is it in the first position? */ + if ((b=tab->tab[h])) { + if ((rh == b->rawhash) && (!strcmp(key,b->key))) { + tab->tab[h] = b->next; + oldval = b->value; + ei_hash_bfree(tab,b); + + tab->nelem--; + if (!tab->tab[h]) tab->npos--; + } + else { + /* is it later in the chain? */ + while (b->next) { + if ((rh == b->next->rawhash) && (!strcmp(key,b->next->key))) { + tmp = b->next; + b->next = tmp->next; + oldval = tmp->value; + ei_hash_bfree(tab,tmp); + + tab->nelem--; + break; + } + b=b->next; + } + } + } + return (void *)oldval; +} + diff --git a/lib/erl_interface/src/registry/hash_resize.c b/lib/erl_interface/src/registry/hash_resize.c new file mode 100644 index 0000000000..9c34a0d41c --- /dev/null +++ b/lib/erl_interface/src/registry/hash_resize.c @@ -0,0 +1,67 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#include +#include "hash.h" + +/* move the elements from oldtab to a new table newsize. The old table + * is freed and the caller should discard the pointer. On failure + * (i.e. if malloc fails) return the old table and do nothing. +*/ +ei_hash *ei_hash_resize(ei_hash *oldtab, int newsize) +{ + ei_hash *newtab=NULL; + ei_bucket *b, *next; + int i,h; + + /* make sure size is odd, then increase until prime */ + newsize |= 0x1; + while (!ei_isprime(newsize)) newsize +=2; + + if (newsize == oldtab->size) return oldtab; + + /* make a new table */ + if (!(newtab = ei_hash_newtab(newsize))) return oldtab; + newtab->hash = oldtab->hash; + + /* move the buckets, rehashing */ + /* note that this will reverse the order of any chains */ + for (i=0; isize; i++) { + b=oldtab->tab[i]; + while (b) { + next = b->next; + h = b->rawhash % newtab->size; + b->next=newtab->tab[h]; + if (!newtab->tab[h]) newtab->npos++; + newtab->tab[h]=b; + b = next; + } + } + /* the new table has the same number of elements as the old one */ + newtab->nelem = oldtab->nelem; + + /* the new table takes over the freelist from the old one */ + newtab->freelist = oldtab->freelist; + + /* now it's safe to remove the old table */ + free(oldtab); + + return newtab; +} diff --git a/lib/erl_interface/src/registry/hash_rlookup.c b/lib/erl_interface/src/registry/hash_rlookup.c new file mode 100644 index 0000000000..5d401555d8 --- /dev/null +++ b/lib/erl_interface/src/registry/hash_rlookup.c @@ -0,0 +1,43 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#include +#include "hash.h" + +/* this function does a reverse lookup and returns the first key whose + * value matches value. This operation may be lengthy! Also, there is + * no guarantee that the *values* are unique in the hash table, so the + * returned key might not be the one you expect. + */ +const char *ei_hash_rlookup(ei_hash *tab, const void *value) +{ + ei_bucket *b; + int i; + + for (i=0; isize; i++) { + b=tab->tab[i]; + while (b) { + if (b->value == value) return b->key; + b = b->next; + } + } + return NULL; +} + diff --git a/lib/erl_interface/src/registry/reg.h b/lib/erl_interface/src/registry/reg.h new file mode 100644 index 0000000000..cb7685506c --- /dev/null +++ b/lib/erl_interface/src/registry/reg.h @@ -0,0 +1,46 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#ifndef _REG_H +#define _REG_H + +#include "ei.h" /* Our public defines, types and declarations */ +#include "hash.h" + +#define EI_MNESIA_MODULE "mnesia_registry" + +#define EI_MNESIA_DUMP "start_dump" +#define EI_MNESIA_WRITE "write" +#define EI_MNESIA_DELETE "delete" +#define EI_MNESIA_COMMIT "commit" + +#define EI_MNESIA_RESTORE "start_restore" +#define EI_MNESIA_SEND "send_records" +#define EI_MNESIA_RECV "restore" +#define EI_MNESIA_SIZE "size" + +#define EI_REG_TYPEMASK 0xf8 /* all but lowest bits */ +#define ei_reg_typeof(r) (r->attr & EI_REG_TYPEMASK) + +ei_reg_obj *ei_reg_make(ei_reg *reg, int attr); + +void ei_reg_free(ei_reg *reg, ei_reg_obj *obj); + +#endif /* _REG_H */ diff --git a/lib/erl_interface/src/registry/reg_close.c b/lib/erl_interface/src/registry/reg_close.c new file mode 100644 index 0000000000..b699e59ac8 --- /dev/null +++ b/lib/erl_interface/src/registry/reg_close.c @@ -0,0 +1,68 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#include +#include "reg.h" + +/* really remove an object (help function to hash_freetab) */ +static void obj_free(void *p) +{ + ei_reg_obj *obj = p; + + if (obj) { + switch (ei_reg_typeof(obj)) { + case EI_STR: + free(obj->val.s); + break; + + case EI_BIN: + free(obj->val.p); + break; + } + + /* really remove the inode (don't use freelist here) */ + free(obj); + } + return; +} + +/* close an open registry */ +int ei_reg_close(ei_reg *reg) +{ + ei_reg_obj *obj, *next; + + if (!reg) return -1; /* return EI_BADARG; */ + + /* remove hash_table */ + ei_hash_freetab(reg->tab,obj_free); + + /* remove freelist */ + obj = reg->freelist; + while (obj) { + next = obj->next; + free(obj); + obj = next; + } + + /* remove registry */ + free(reg); + + return 0; +} diff --git a/lib/erl_interface/src/registry/reg_delete.c b/lib/erl_interface/src/registry/reg_delete.c new file mode 100644 index 0000000000..8e84e205ee --- /dev/null +++ b/lib/erl_interface/src/registry/reg_delete.c @@ -0,0 +1,36 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#include "reg.h" + +int ei_reg_delete(ei_reg *reg, const char *key) +{ + ei_hash *tab; + ei_reg_obj *obj; + + if (!key || !reg) return -1; /* return EI_BADARG; */ + tab = reg->tab; + if (!(obj = ei_hash_lookup(tab,key))) return -1; /* return EI_NOTFOUND; */ + + /* just mark the object deleted */ + obj->attr |= (EI_DELET | EI_DIRTY); + + return 0; +} diff --git a/lib/erl_interface/src/registry/reg_dirty.c b/lib/erl_interface/src/registry/reg_dirty.c new file mode 100644 index 0000000000..730b4445c6 --- /dev/null +++ b/lib/erl_interface/src/registry/reg_dirty.c @@ -0,0 +1,36 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#include "reg.h" + +int ei_reg_markdirty(ei_reg *reg, const char *key) +{ + ei_hash *tab; + ei_reg_obj *obj; + + if (!key || !reg) return -1; /* EI_BADARG; */ + tab = reg->tab; + if (!(obj = ei_hash_lookup(tab,key))) return -1; /* return EI_NOTFOUND; */ + + /* just mark the object dirty */ + obj->attr |= EI_DIRTY; + + return 0; +} diff --git a/lib/erl_interface/src/registry/reg_dump.c b/lib/erl_interface/src/registry/reg_dump.c new file mode 100644 index 0000000000..50a6949177 --- /dev/null +++ b/lib/erl_interface/src/registry/reg_dump.c @@ -0,0 +1,321 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#include +#include +#include "eidef.h" +#include "eiext.h" +#include "reg.h" +#include "eisend.h" +#include "eirecv.h" +#include "ei_connect_int.h" + +static int mn_start_dump(int fd, const erlang_pid *self, + erlang_pid *mnesia, const char *mntab) +{ + char buf[EISMALLBUF]; + char *bufp = buf; + char tmpbuf[64]; + int index = 0; + erlang_msg msg; + int type; + int arity; + int version; + int msglen; + int i; + int needlink; + int needpid; + + /* set up rpc arguments */ + /* { PidFrom, { call, Mod, Fun, Args, user }} */ + ei_encode_version(buf,&index); + ei_encode_tuple_header(buf,&index,2); + ei_encode_pid(buf,&index,self); /* PidFrom */ + ei_encode_tuple_header(buf,&index,5); + ei_encode_atom(buf,&index,"call"); /* call */ + ei_encode_atom(buf,&index,EI_MNESIA_MODULE); /* Mod */ + ei_encode_atom(buf,&index,EI_MNESIA_DUMP); /* Fun */ + ei_encode_list_header(buf,&index,2); /* Args: [ table, self() ] */ + ei_encode_atom(buf,&index,mntab); + ei_encode_pid(buf,&index,self); + ei_encode_empty_list(buf,&index); + ei_encode_atom(buf,&index,"user"); /* user */ + + /* make the rpc call */ + if (ei_send_reg_encoded(fd,self,"rex",buf,index)) return -1; + + /* get the reply: expect link and pid (not sure which will come first though) */ + needlink = needpid = 1; + while (needlink || needpid) { + /* get message */ + while (1) { + index = EISMALLBUF; + if (!(i = ei_recv_internal(fd,&bufp,&index,&msg,&msglen,1,0))) continue; + else break; + } + + switch (i) { + case ERL_LINK: + /* got link */ + if (!needlink) return -1; + needlink = 0; + break; + + case ERL_SEND: + /* got message - does it contain a pid? */ + if (!needpid) return -1; + else { + /* expecting { rex, } */ + index = 0; + if (ei_decode_version(buf,&index,&version) + || ei_decode_tuple_header(buf,&index,&arity) + || (arity != 2) + || ei_decode_atom(buf,&index,tmpbuf) + || strcmp(tmpbuf,"rex") + || ei_get_type_internal(buf,&index,&type,&arity) + || (type != ERL_PID_EXT)) + return -1; /* bad response from other side */ + + if (ei_decode_pid(buf,&index,mnesia)) return -1; + + /* got pid */ + needpid = 0; + } + break; + + default: + return -1; /* wasn't link or pid */ + } + } + return 0; +} + +static int mn_send_commit(int fd, erlang_pid *mnesia, erlang_pid *self) +{ + char buf[EISMALLBUF]; + char *bufp=buf; + char string[256]; + int index = 0; + int version,arity; + int msglen; + erlang_msg msg; + int i; + + /* set up commit message { commit, self() } */ + ei_encode_version(buf,&index); + ei_encode_tuple_header(buf,&index,2); + ei_encode_atom(buf,&index,EI_MNESIA_COMMIT); + ei_encode_pid(buf,&index,self); + + /* send it */ + if (ei_send_encoded(fd,mnesia,buf,index)) return -1; + + /* get reply */ + while (1) { + index = EISMALLBUF; + if (!(i=ei_recv_internal(fd,&bufp,&index,&msg,&msglen,1,0))) continue; + else if (i < 0) return -1; + else break; + } + + if (i == ERL_SEND) { + index = 0; + if (ei_decode_version(buf,&index,&version) + || ei_decode_tuple_header(buf,&index,&arity) + || ei_decode_atom(buf,&index,string)) + return -1; + + if (!strcmp(string,"ok")) return 0; + } + /* wrong message type */ + return -1; +} + +static int mn_send_delete(int fd, erlang_pid *mnesia, const char *key) +{ + char sbuf[EISMALLBUF]; + char *dbuf = NULL; + char *msgbuf; + int index = 0; + int len = strlen(key) + 32; /* 32 is a slight overestimate */ + + if (len > EISMALLBUF) + if (!(dbuf = malloc(index))) + return -1; + msgbuf = (dbuf ? dbuf : sbuf); + + /* set up delete message { delete, Key } */ + ei_encode_version(msgbuf,&index); + ei_encode_tuple_header(msgbuf,&index,2); + ei_encode_atom(msgbuf,&index,EI_MNESIA_DELETE); + ei_encode_string(msgbuf,&index,key); + + /* send it */ + if (ei_send_encoded(fd,mnesia,msgbuf,index)) { + if (dbuf) free(dbuf); + return -1; + } + + if (dbuf) free(dbuf); + return 0; +} + +static int mn_send_write(int fd, erlang_pid *mnesia, const char *key, ei_reg_obj *obj) +{ + char sbuf[EISMALLBUF]; + char *dbuf = NULL; + char *msgbuf; + int index = 0; + int keylen = strlen(key) + 1; + int len = 32 + keylen + obj->size; + + if (len > EISMALLBUF) + if (!(dbuf = malloc(index))) + return -1; + msgbuf = (dbuf ? dbuf : sbuf); + + ei_encode_version(msgbuf,&index); + ei_encode_tuple_header(msgbuf,&index,6); + ei_encode_atom(msgbuf,&index,EI_MNESIA_WRITE); + ei_encode_string(msgbuf,&index,key); + ei_encode_long(msgbuf,&index,keylen); + ei_encode_long(msgbuf,&index,obj->attr); + ei_encode_long(msgbuf,&index,obj->size); + + switch (ei_reg_typeof(obj)) { + case EI_INT: + ei_encode_long(msgbuf,&index,obj->val.i); + break; + case EI_FLT: + ei_encode_double(msgbuf,&index,obj->val.f); + break; + case EI_STR: + if (obj->size > 0) ei_encode_string(msgbuf,&index,obj->val.s); + else ei_encode_long(msgbuf,&index, (long)NULL); /* just the NULL pointer */ + break; + case EI_BIN: + if (obj->size > 0) ei_encode_binary(msgbuf,&index,obj->val.p,obj->size); + else ei_encode_long(msgbuf,&index,(long)(obj->val.p)); /* just the pointer */ + break; + default: + return -1; + } + + /* send it */ + if (ei_send_encoded(fd,mnesia,msgbuf,index)) { + if (dbuf) free(dbuf); + return -1; + } + + if (dbuf) free(dbuf); + return 0; +} + +static int mn_get_unlink(int fd) +{ + erlang_msg msg; + char buf[EISMALLBUF]; + char *bufp=buf; + int index; + int msglen; + + /* wait for unlink or exit */ + while (1) { + index = EISMALLBUF; + switch (ei_recv_internal(fd,&bufp,&index,&msg,&msglen,1,0)) { + case 0: continue; + case ERL_UNLINK: return 0; + default: return -1; + } + } + return 0; +} + +/* dump to backup */ +/* fd is open connection to erlang node */ +int ei_reg_dump(int fd, ei_reg *reg, const char *mntab, int flags) +{ + ei_hash *tab; + erlang_pid self; + erlang_pid mnesia; + ei_bucket *b; + ei_reg_obj *obj; + const char *key; + ei_cnode *ec; + int i; + + if (!reg || !mntab) return -1; /* return EI_BADARG; */ + tab = reg->tab; + + /* make a self pid */ + + if ((ec = ei_fd_to_cnode(fd)) == NULL) { + return -1; + } + strcpy(self.node,ei_thisnodename(ec)); + self.num = fd; + self.serial = 0; + self.creation = ei_thiscreation(ec); + + if (mn_start_dump(fd,&self,&mnesia,mntab)) return -1; + + /* traverse the table, passing objects to mnesia */ + for (i=0; isize; i++) { + b=tab->tab[i]; + while (b) { + obj = (ei_reg_obj*)(b->value); /* cast to eliminate 'const' warning */ + key = b->key; + + if ((flags & EI_FORCE) || (obj->attr & EI_DIRTY)) { + if (obj->attr & EI_DELET) { + if (mn_send_delete(fd,&mnesia,key)) { + ei_send_exit(fd,&self,&mnesia,"delete failed"); + return -1; + } + } + else { + if (mn_send_write(fd,&mnesia,key,obj)) { + ei_send_exit(fd,&self,&mnesia,"update failed"); + return -1; + } + } + } + b = b->next; + } + } + + /* end the transaction */ + if (mn_send_commit(fd,&mnesia,&self)) { + ei_send_exit(fd,&self,&mnesia,"commit failed"); + return -1; + } + + /* wait for unlink */ + if (mn_get_unlink(fd)) return -1; + + /* this point only reached if all went ok so far... */ + + /* now remove all deleted objects, unless the caller asked us not to */ + if (!(flags & EI_NOPURGE)) ei_reg_purge(reg); + + /* success */ + return 0; + +} diff --git a/lib/erl_interface/src/registry/reg_free.c b/lib/erl_interface/src/registry/reg_free.c new file mode 100644 index 0000000000..e3245577a5 --- /dev/null +++ b/lib/erl_interface/src/registry/reg_free.c @@ -0,0 +1,47 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#include +#include "reg.h" + +/* free a registry object (inode) on the freelist. The "value" + * contained by the object is removed. + */ +void ei_reg_free(ei_reg *reg, ei_reg_obj *obj) +{ + /* free the value part */ + switch (ei_reg_typeof(obj)) { + case EI_STR: + free(obj->val.s); + break; + + case EI_BIN: + free(obj->val.p); + break; + } + + /* fprintf(stderr,"%s:%d: saving %p on freelist\n",__FILE__,__LINE__,obj);*/ + + /* save the rest on the freelist */ + obj->next = reg->freelist; + reg->freelist = obj; + + return; +} diff --git a/lib/erl_interface/src/registry/reg_get.c b/lib/erl_interface/src/registry/reg_get.c new file mode 100644 index 0000000000..d1909b3fed --- /dev/null +++ b/lib/erl_interface/src/registry/reg_get.c @@ -0,0 +1,94 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#ifdef VXWORKS +#include +#endif + +#include +#include "reg.h" + +/* this is the general "get" function. Values are copied into a buffer + * provided by the caller, and the return value indicates success or + * failure. This function can get all types except directorys. The user + * must specify the type of data he is expecting, or 0 if he doesn't + * care. On success, the data type is returned. If the requested data + * type does not match the data found, EI_TYPE is returned. + */ +int ei_reg_getval(ei_reg *reg, const char *key, int flags, ...) +{ + ei_hash *tab; + ei_reg_obj *obj=NULL; + va_list ap; + int rval; + int objtype; + + if (!key || !reg) return -1; /* return EI_BADARG; */ + tab = reg->tab; + if (!(obj=ei_hash_lookup(tab,key))) return -1; /* return EI_NOTFOUND; */ + if (obj->attr & EI_DELET) return -1; /* return EI_NOTFOUND; */ + + /* if type was specified then it must match object */ + objtype = ei_reg_typeof(obj); + if (flags && (flags != objtype)) return -1; /* return EI_TYPE; */ + + va_start(ap,flags); + + switch ((rval = objtype)) { + case EI_INT: { + long *ip; + + if (!(ip = va_arg(ap,long*))) rval = -1; /* EI_BADARG; */ + else *ip = obj->val.i; + break; + } + case EI_FLT: { + double *fp; + + if (!(fp = va_arg(ap,double*))) rval = -1; /* EI_BADARG; */ + else *fp = obj->val.f; + break; + } + case EI_STR: { + char **sp; + + if (!(sp = va_arg(ap,char**))) rval = -1; /* EI_BADARG; */ + else *sp = obj->val.s; + break; + } + case EI_BIN: { + void **pp; + int *size; + + if (!(pp = va_arg(ap,void**))) rval = -1; /* EI_BADARG; */ + else *pp = obj->val.p; + if ((size=va_arg(ap,int*))) *size=obj->size; + break; + } + default: + /* can't (should never) happen */ + rval = -1; + /* rval = EI_UNKNOWN; */ + } + + /* clean up & return */ + va_end(ap); + return rval; +} diff --git a/lib/erl_interface/src/registry/reg_getf.c b/lib/erl_interface/src/registry/reg_getf.c new file mode 100644 index 0000000000..faed2f2df9 --- /dev/null +++ b/lib/erl_interface/src/registry/reg_getf.c @@ -0,0 +1,35 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#include "reg.h" + +double ei_reg_getfval(ei_reg *reg, const char *key) +{ + ei_hash *tab; + ei_reg_obj *obj=NULL; + + if (!key || !reg) return -1; /* return (double)EI_BADARG; */ + tab = reg->tab; + if (!(obj=ei_hash_lookup(tab,key))) return -1; /* return EI_NOTFOUND; */ + if (obj->attr & EI_DELET) return -1; /* return EI_NOTFOUND; */ + if (ei_reg_typeof(obj) != EI_FLT) return -1; /* return (double)EI_TYPE; */ + + return obj->val.f; +} diff --git a/lib/erl_interface/src/registry/reg_geti.c b/lib/erl_interface/src/registry/reg_geti.c new file mode 100644 index 0000000000..b746a4a92b --- /dev/null +++ b/lib/erl_interface/src/registry/reg_geti.c @@ -0,0 +1,35 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#include "reg.h" + +long ei_reg_getival(ei_reg *reg, const char *key) +{ + ei_hash *tab; + ei_reg_obj *obj=NULL; + + if (!key || !reg) return -1; /* return EI_BADARG; */ + tab = reg->tab; + if (!(obj=ei_hash_lookup(tab,key))) return -1; /* return EI_NOTFOUND; */ + if (obj->attr & EI_DELET) return -1; /* return EI_NOTFOUND; */ + if (ei_reg_typeof(obj) != EI_INT) return -1; /* return EI_TYPE; */ + + return obj->val.i; +} diff --git a/lib/erl_interface/src/registry/reg_getp.c b/lib/erl_interface/src/registry/reg_getp.c new file mode 100644 index 0000000000..bacfdc05c4 --- /dev/null +++ b/lib/erl_interface/src/registry/reg_getp.c @@ -0,0 +1,39 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#include +#include "reg.h" + +const void *ei_reg_getpval(ei_reg *reg, const char *key, int *size) +{ + ei_hash *tab; + ei_reg_obj *obj; + + if (!key || !reg) return NULL; + tab = reg->tab; + + if ((!(obj=ei_hash_lookup(tab,key))) || /* return (const void *)EI_NOTFOUND; */ + (obj->attr & EI_DELET) || /* return (const void *)EI_NOTFOUND; */ + (ei_reg_typeof(obj) != EI_BIN)) /* return (const void *)EI_TYPE; */ + return NULL; + + if (size) *size=obj->size; + return obj->val.p; +} diff --git a/lib/erl_interface/src/registry/reg_gets.c b/lib/erl_interface/src/registry/reg_gets.c new file mode 100644 index 0000000000..d6e6d67ebe --- /dev/null +++ b/lib/erl_interface/src/registry/reg_gets.c @@ -0,0 +1,38 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#include +#include "reg.h" + +const char *ei_reg_getsval(ei_reg *reg, const char *key) +{ + ei_hash *tab; + ei_reg_obj *obj=NULL; + + if (!key || !reg) return NULL; /* return (const char *)EI_BADARG; */ + tab = reg->tab; + + if ((!(obj=ei_hash_lookup(tab,key))) || /* return (const char *)EI_NOTFOUND; */ + (obj->attr & EI_DELET) || /* return (const char *)EI_NOTFOUND; */ + (ei_reg_typeof(obj) != EI_STR)) /* return (const char *)EI_TYPE; */ + return NULL; + + return obj->val.s; +} diff --git a/lib/erl_interface/src/registry/reg_make.c b/lib/erl_interface/src/registry/reg_make.c new file mode 100644 index 0000000000..179cb8bf47 --- /dev/null +++ b/lib/erl_interface/src/registry/reg_make.c @@ -0,0 +1,49 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#include +#include "reg.h" + + +/* make a new ei_reg_obj object. If the freelist for this registry is + * not empty, an object will be returned from there. Otherwise one + * will be created with malloc(). + */ +ei_reg_obj *ei_reg_make(ei_reg *reg, int attr) +{ + ei_reg_obj *new=NULL; + + if (reg->freelist) { + new = reg->freelist; + reg->freelist = new->next; + /* fprintf(stderr,"%s:%d: found %p on freelist\n",__FILE__,__LINE__,new); */ + } + else { + new = malloc(sizeof(*new)); + /* fprintf(stderr,"%s:%d: allocated %p\n",__FILE__,__LINE__,new); */ + } + + if (new) { + new->attr=attr | EI_DIRTY; + new->size=0; + new->next = NULL; + } + return new; +} diff --git a/lib/erl_interface/src/registry/reg_open.c b/lib/erl_interface/src/registry/reg_open.c new file mode 100644 index 0000000000..0c2031707d --- /dev/null +++ b/lib/erl_interface/src/registry/reg_open.c @@ -0,0 +1,41 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#include +#include "reg.h" + +/* open a registry */ +ei_reg *ei_reg_open(int size) +{ + ei_reg *new; + + if (size <= 0) return NULL; + + if (!(new = malloc(sizeof(*new)))) return NULL; + + new->freelist = NULL; + + if (!(new->tab = ei_hash_newtab(size))) { + free(new); + return NULL; + } + + return new; +} diff --git a/lib/erl_interface/src/registry/reg_purge.c b/lib/erl_interface/src/registry/reg_purge.c new file mode 100644 index 0000000000..329fd32f23 --- /dev/null +++ b/lib/erl_interface/src/registry/reg_purge.c @@ -0,0 +1,76 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#include +#include "reg.h" + +static ei_bucket *do_purge(ei_reg *reg, int i) +{ + ei_hash *tab = reg->tab; + ei_bucket *head = tab->tab[i]; + ei_bucket *this, *next; + ei_reg_obj *obj; + + /* first position special case */ + while ((this=head)) { + obj = (ei_reg_obj*)(this->value); /* cast to eliminate 'const' warning */ + if (obj->attr & EI_DELET) { + head = this->next; + ei_reg_free(reg,obj); /* free obj to freelist */ + ei_hash_bfree(tab,this); /* free bucket to freelist */ + tab->nelem--; + } + else break; + } + + /* check remaining positions */ + this = head; + while (this && this->next) { + next = this->next; + obj = (ei_reg_obj*)(next->value); /* cast to eliminate 'const' warning */ + if (obj->attr & EI_DELET) { + this->next = next->next; + ei_reg_free(reg,obj); /* free object to freelist */ + ei_hash_bfree(tab,next); /* free bucket to freelist */ + tab->nelem--; + } + else this = this->next; + } + + return head; +} + +int ei_reg_purge(ei_reg *reg) +{ + ei_hash *tab; + int i; + + if (!reg) return -1; + tab = reg->tab; + + for (i=0;isize;i++) { + if ((tab->tab[i])) { + tab->tab[i] = do_purge(reg,i); + if (!tab->tab[i]) tab->npos--; + } + } + + return 0; +} diff --git a/lib/erl_interface/src/registry/reg_resize.c b/lib/erl_interface/src/registry/reg_resize.c new file mode 100644 index 0000000000..8e4794ccf7 --- /dev/null +++ b/lib/erl_interface/src/registry/reg_resize.c @@ -0,0 +1,36 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#include "reg.h" + +/* resize a registry - return the new size or -1 on error */ +int ei_reg_resize(ei_reg *reg, int newsize) +{ + ei_hash *newtab=NULL; + + if (!reg) return -1; + if (newsize <= 0) return -1; + + if ((newtab=ei_hash_resize(reg->tab,newsize))) { + reg->tab = newtab; + } + + return reg->tab->size; +} diff --git a/lib/erl_interface/src/registry/reg_restore.c b/lib/erl_interface/src/registry/reg_restore.c new file mode 100644 index 0000000000..27918d2364 --- /dev/null +++ b/lib/erl_interface/src/registry/reg_restore.c @@ -0,0 +1,323 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#include +#include +#include "eidef.h" +#include "eiext.h" +#include "reg.h" +#include "eisend.h" +#include "eirecv.h" +#include "ei_connect_int.h" + +static int mn_start_restore(int fd, const erlang_pid *self, erlang_pid *mnesia, const char *mntab, long *count, long *maxkey,long *maxobj) +{ + char buf[EISMALLBUF]; + char *bufp=buf; + char tmpbuf[64]; + int index = 0; + erlang_msg msg; + int arity; + int version; + int i; + int needlink; + int needmsg; + int msglen; + + /* set up rpc arguments */ + /* { PidFrom, { call, Mod, Fun, Args, user }} */ + ei_encode_version(buf,&index); + ei_encode_tuple_header(buf,&index,2); + ei_encode_pid(buf,&index,self); /* PidFrom */ + ei_encode_tuple_header(buf,&index,5); + ei_encode_atom(buf,&index,"call"); /* call */ + ei_encode_atom(buf,&index,EI_MNESIA_MODULE); /* Mod */ + ei_encode_atom(buf,&index,EI_MNESIA_RESTORE); /* Fun */ + ei_encode_list_header(buf,&index,2); /* Args: [ table, self() ] */ + ei_encode_atom(buf,&index,mntab); + ei_encode_pid(buf,&index,self); + ei_encode_empty_list(buf,&index); + ei_encode_atom(buf,&index,"user"); /* user */ + + /* make the rpc call */ + if (ei_send_reg_encoded(fd,self,"rex",buf,index)) return -1; + + /* get the reply: expect link and message (not sure which will come first though) */ + needlink = needmsg = 1; + while (needlink || needmsg) { + /* get message */ + index = EISMALLBUF; + while (!(i = ei_recv_internal(fd,&bufp,&index,&msg,&msglen,1,0))) index = EISMALLBUF; + + switch (i) { + case ERL_LINK: + /* got link */ + if (!needlink) return -1; + needlink = 0; + break; + + case ERL_SEND: + /* got message - is it the right one? */ + if (!needmsg) return -1; + else { + /* expecting { rex, { size, Pid, Count, MaxKey, MaxObj }} */ + index = 0; + if (ei_decode_version(buf,&index,&version) + || ei_decode_tuple_header(buf,&index,&arity) + || (arity != 2) + || ei_decode_atom(buf,&index,tmpbuf) + || strcmp(tmpbuf,"rex") + || ei_decode_tuple_header(buf,&index,&arity) + || (arity != 5) + || ei_decode_atom(buf,&index,tmpbuf) + || strcmp(tmpbuf,EI_MNESIA_SIZE) + || ei_decode_pid(buf,&index,mnesia) + || ei_decode_long(buf,&index,count) + || ei_decode_long(buf,&index,maxkey) + || ei_decode_long(buf,&index,maxobj)) + return -1; /* bad response from other side */ + + /* got msg */ + needmsg = 0; + } + break; + + default: + return -1; /* wasn't link or pid */ + } + } + return 0; +} + +static int mn_unlink(int fd) +{ + erlang_msg msg; + char buf[EISMALLBUF]; + char *bufp=buf; + int index; + int msglen; + + /* wait for unlink or exit */ + while (1) { + index = EISMALLBUF; + switch (ei_recv_internal(fd,&bufp,&index,&msg,&msglen,1,0)) { + case 0: continue; + case ERL_UNLINK: return 0; + default: return -1; + } + } + return 0; +} + +/* decode an object and insert it into the table */ +static int mn_decode_insert(ei_reg *reg, const char *msgbuf, int *index, char *key) +{ + long keylen; + long objlen; + long objtype; + void *objbuf = NULL; + long i; + double f; + + if (ei_decode_long(msgbuf,index,&keylen) + || ei_decode_long(msgbuf,index,&objlen) + || ei_decode_long(msgbuf,index,&objtype)) + return -1; + + + /* decode key */ + if (ei_decode_string(msgbuf,index,key)) { + if (objbuf) free(objbuf); + return -1; + } + + /* finally! decode object and insert in table */ + /* don't forget to fix attributes (dirty bit for example) */ + + /* FIXME: added cast but 64 bit trouble I think */ + switch ((int)objtype & EI_REG_TYPEMASK) { + case EI_INT: + if (ei_decode_long(msgbuf,index,&i)) return -1; + ei_reg_setival(reg,key,i); + break; + + case EI_FLT: + if (ei_decode_double(msgbuf,index,&f)) return -1; + ei_reg_setfval(reg,key,f); + break; + + case EI_STR: + objbuf = NULL; + if (objlen > 0) { + if (!(objbuf = malloc(objlen))) return -1; + if (ei_decode_string(msgbuf,index,objbuf)) { + free(objbuf); + return -1; + } + ei_reg_setsval(reg,key,objbuf); + } + else { + /* just a pointer to nothing */ + if (ei_decode_long(msgbuf,index,&i)) return -1; + ei_reg_setsval(reg,key,NULL); + } + break; + + case EI_BIN: + objbuf = NULL; + if (objlen > 0) { + if (!(objbuf = malloc(objlen))) return -1; + if (ei_decode_binary(msgbuf,index,objbuf,&i)) { + free(objbuf); + return -1; + } + /* assert(i == objlen) */ + ei_reg_setpval(reg,key,objbuf,objlen); + } + else { + /* just a pointer to nothing */ + if (ei_decode_long(msgbuf,index,&i)) return -1; + ei_reg_setpval(reg,key,(void *)i,0); + } + break; + + default: + /* unknown type */ + if (objbuf) free(objbuf); + return -1; + } /* switch */ + + return 0; +} + +/* help function passed to hash_foreach, to clear dirty bits */ +/* use after successful restore */ +static int clean_obj(const char *key, const void *p) +{ + ei_reg_obj *obj = (ei_reg_obj *)p; + + if (obj) obj->attr &= ~EI_DIRTY; + + return 0; +} + +int ei_reg_restore(int fd, ei_reg *reg, const char *mntab) +{ + int i,j; + char tag[32]; + char sbuf[EISMALLBUF]; + char *dbuf = NULL; + char *msgbuf = NULL; + char *keybuf = NULL; + erlang_pid self; + erlang_pid mnesia = {"",0,0,0}; + erlang_msg msg; + int index = 0; + int len = 0; + int msglen; + int version = 0; + int arity = 0; + long count = 0; + long maxkey = 0; + long maxobj = 0; + ei_cnode *ec; + + if (!reg || !mntab) return -1; /* return EI_BADARG; */ + + /* make a self pid */ + + if ((ec = ei_fd_to_cnode(fd)) == NULL) { + return -1; + } + strcpy(self.node,ei_thisnodename(ec)); + self.num = fd; + self.serial = 0; + self.creation = ei_thiscreation(ec); + + + if (mn_start_restore(fd,&self,&mnesia,mntab,&count,&maxkey,&maxobj)) { + /* send exit *only* if we have pid */ + if (mnesia.node[0]) ei_send_exit(fd,&self,&mnesia,"bad response from rpc start"); + return -1; + } + + if (count <= 0) { + ei_send_exit(fd,&self,&mnesia,"nothing to do"); + return 0; + } + + /* make sure receive buffer can handle largest expected message */ + len = maxkey + maxobj + 512; + if (len > EISMALLBUF) + if (!(dbuf = malloc(index))) { + ei_send_exit(fd,&self,&mnesia,"cannot allocate space for incoming data"); + return -1; + } + msgbuf = (dbuf ? dbuf : sbuf); + + /* allocate space for largest key */ + if (!(keybuf = malloc(maxkey+1))) goto restore_failure; + + /* get this ball rolling */ + index = 0; + ei_encode_version(msgbuf,&index); + ei_encode_tuple_header(msgbuf,&index,2); + ei_encode_atom(msgbuf,&index,"send_records"); + ei_encode_pid(msgbuf,&index,&self); + if (ei_send_encoded(fd,&mnesia,msgbuf,index)) goto restore_failure; + + /* read as much as possible, until count or EXIT */ + for (i=0; itab,clean_obj); + + /* success */ + if (keybuf) free(keybuf); + if (dbuf) free(dbuf); + return 0; + +restore_failure: + ei_send_exit(fd,&self,&mnesia,"restore failure"); + if (keybuf) free(keybuf); + if (dbuf) free(dbuf); + return -1; +} + diff --git a/lib/erl_interface/src/registry/reg_set.c b/lib/erl_interface/src/registry/reg_set.c new file mode 100644 index 0000000000..70ade09ffa --- /dev/null +++ b/lib/erl_interface/src/registry/reg_set.c @@ -0,0 +1,78 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#ifdef VXWORKS +#include +#endif + +#include +#include "reg.h" + +int ei_reg_setval(ei_reg *reg, const char *key, int flags, ...) +{ + va_list ap; + int rval = 0; + + if (!key || !reg) return -1; /* return EI_BADARG; */ + + va_start(ap,flags); + + switch (flags & EI_REG_TYPEMASK) { + case EI_INT: { + long i; + + i = va_arg(ap,long); + rval = ei_reg_setival(reg,key,i); + break; + } + case EI_FLT: { + double f; + + f = va_arg(ap,double); + rval = ei_reg_setfval(reg,key,f); + break; + } + case EI_STR: { + char *s; + + s = va_arg(ap,char*); + rval = ei_reg_setsval(reg,key,s); + break; + } + case EI_BIN: { + void *p; + int len; + + p = va_arg(ap,void*); + len = va_arg(ap,int); + rval = ei_reg_setpval(reg,key,p,len); + break; + } + + default: + rval = -1; + /* rval = EI_BADARG; */ + } + + /* clean up & return */ + va_end(ap); + return rval; +} + diff --git a/lib/erl_interface/src/registry/reg_setf.c b/lib/erl_interface/src/registry/reg_setf.c new file mode 100644 index 0000000000..1021174074 --- /dev/null +++ b/lib/erl_interface/src/registry/reg_setf.c @@ -0,0 +1,61 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#include +#include "reg.h" + +int ei_reg_setfval(ei_reg *reg, const char *key, double f) +{ + ei_hash *tab; + ei_reg_obj *obj=NULL; + + if (!key || !reg) return -1; /* return EI_BADARG; */ + tab = reg->tab; + + if ((obj=ei_hash_lookup(tab,key))) { + /* object with same name already exists */ + switch (ei_reg_typeof(obj)) { + case EI_INT: + break; + case EI_FLT: + break; + case EI_STR: + if (obj->size > 0) free(obj->val.s); + break; + case EI_BIN: + if (obj->size > 0) free(obj->val.p); + break; + default: + return -1; + /* return EI_UNKNOWN; */ + } + } + else { + /* object is new */ + if (!(obj=ei_reg_make(reg,EI_FLT))) return -1; /* return EI_NOMEM; */ + ei_hash_insert(tab,key,obj); + } + + obj->attr = EI_FLT | EI_DIRTY; + obj->val.f=f; + obj->size = 0; + + return 0; +} diff --git a/lib/erl_interface/src/registry/reg_seti.c b/lib/erl_interface/src/registry/reg_seti.c new file mode 100644 index 0000000000..430a3b6d47 --- /dev/null +++ b/lib/erl_interface/src/registry/reg_seti.c @@ -0,0 +1,62 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#include +#include "reg.h" + +/* set and get values */ +int ei_reg_setival(ei_reg *reg, const char *key, long i) +{ + ei_hash *tab; + ei_reg_obj *obj=NULL; + + if (!key || !reg) return -1; /* return EI_BADARG; */ + tab = reg->tab; + + if ((obj=ei_hash_lookup(tab,key))) { + /* object with same name already exists */ + switch (ei_reg_typeof(obj)) { + case EI_INT: + break; + case EI_FLT: + break; + case EI_STR: + if (obj->size > 0) free(obj->val.s); + break; + case EI_BIN: + if (obj->size > 0) free(obj->val.p); + break; + default: + return -1; + /* return EI_UNKNOWN; */ + } + } + else { + /* object is new */ + if (!(obj=ei_reg_make(reg,EI_INT))) return -1; /* return EI_NOMEM; */ + ei_hash_insert(tab,key,obj); + } + + obj->attr = EI_INT | EI_DIRTY; + obj->val.i=i; + obj->size = 0; + + return 0; +} diff --git a/lib/erl_interface/src/registry/reg_setp.c b/lib/erl_interface/src/registry/reg_setp.c new file mode 100644 index 0000000000..a994c14c78 --- /dev/null +++ b/lib/erl_interface/src/registry/reg_setp.c @@ -0,0 +1,62 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#include +#include "reg.h" + +int ei_reg_setpval(ei_reg *reg, const char *key, const void *p, int size) +{ + ei_hash *tab; + ei_reg_obj *obj=NULL; + + if (size < 0) return -1; + if (!key || !reg) return -1; /* return EI_BADARG; */ + tab = reg->tab; + + if ((obj=ei_hash_lookup(tab,key))) { + /* object with same name already exists */ + switch (ei_reg_typeof(obj)) { + case EI_INT: + break; + case EI_FLT: + break; + case EI_STR: + if (obj->size > 0) free(obj->val.s); + break; + case EI_BIN: + if (obj->size > 0) free(obj->val.p); + break; + default: + return -1; + /* return EI_UNKNOWN; */ + } + } + else { + /* object is new */ + if (!(obj=ei_reg_make(reg,EI_BIN))) return -1; /* return EI_NOMEM; */ + ei_hash_insert(tab,key,obj); + } + + obj->attr = EI_BIN | EI_DIRTY; + obj->val.p=(void *)p; + obj->size=size; + + return 0; +} diff --git a/lib/erl_interface/src/registry/reg_sets.c b/lib/erl_interface/src/registry/reg_sets.c new file mode 100644 index 0000000000..14bdb2699d --- /dev/null +++ b/lib/erl_interface/src/registry/reg_sets.c @@ -0,0 +1,65 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#include +#include +#include "reg.h" + +int ei_reg_setsval(ei_reg *reg, const char *key, const char *s) +{ + ei_hash *tab; + ei_reg_obj *obj=NULL; + int len = 0; + + + if (!key || !reg) return -1; /* return EI_BADARG; */ + tab = reg->tab; + if (s) len = strlen(s) +1; + + if ((obj=ei_hash_lookup(tab,key))) { + /* object with same name already exists */ + switch (ei_reg_typeof(obj)) { + case EI_INT: + break; + case EI_FLT: + break; + case EI_STR: + if (obj->size > 0) free(obj->val.s); + break; + case EI_BIN: + if (obj->size > 0) free(obj->val.p); + break; + default: + return -1; + /* return EI_UNKNOWN; */ + } + } + else { + /* object is new */ + if (!(obj=ei_reg_make(reg,EI_STR))) return -1; /* return EI_NOMEM; */ + ei_hash_insert(tab,key,obj); + } + + obj->attr = EI_STR | EI_DIRTY; + obj->val.s=(char *)s; + obj->size = len; + + return 0; +} diff --git a/lib/erl_interface/src/registry/reg_stat.c b/lib/erl_interface/src/registry/reg_stat.c new file mode 100644 index 0000000000..c3f669fd4f --- /dev/null +++ b/lib/erl_interface/src/registry/reg_stat.c @@ -0,0 +1,41 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#include "reg.h" + +/* Get object attributes. + * This function returns a COPY of the ei_reg_obj + * struct for an object. + */ +int ei_reg_stat(ei_reg *reg, const char *key, struct ei_reg_stat *obuf) +{ + ei_hash *tab; + ei_reg_obj *obj; + + if (!key || !obuf || !reg) return -1; /* return EI_BADARG; */ + tab = reg->tab; + + if (!(obj=ei_hash_lookup(tab,key))) return -1; /* return EI_NOTFOUND; */ + + obuf->attr = obj->attr; + obuf->size = obj->size; + + return 0; +} diff --git a/lib/erl_interface/src/registry/reg_tabstat.c b/lib/erl_interface/src/registry/reg_tabstat.c new file mode 100644 index 0000000000..edfb19fa00 --- /dev/null +++ b/lib/erl_interface/src/registry/reg_tabstat.c @@ -0,0 +1,37 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +#include "reg.h" + +/* get table information */ +int ei_reg_tabstat(ei_reg *reg, struct ei_reg_tabstat *obuf) +{ + ei_hash *tab; + + if (!reg || !obuf) return -1; /* return EI_BADARG; */ + tab = reg->tab; + + obuf->npos = tab-> npos; + obuf->size = tab->size; + obuf->nelem = tab->nelem; + obuf->collisions = tab->nelem - tab->npos; + + return 0; +} -- cgit v1.2.3