http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/92b8098c/proton-c/src/object/object.c ---------------------------------------------------------------------- diff --git a/proton-c/src/object/object.c b/proton-c/src/object/object.c index d1b0e43..b0cfcc7 100644 --- a/proton-c/src/object/object.c +++ b/proton-c/src/object/object.c @@ -19,1031 +19,294 @@ * */ -#include "../platform.h" -#include <proton/error.h> #include <proton/object.h> -#include <stdio.h> #include <stdlib.h> -#include <string.h> #include <assert.h> -#include <ctype.h> -typedef struct { - const pn_class_t *clazz; - int refcount; -} pni_head_t; +#define pn_object_initialize NULL +#define pn_object_finalize NULL +#define pn_object_inspect NULL +uintptr_t pn_object_hashcode(void *object) { return (uintptr_t) object; } +intptr_t pn_object_compare(void *a, void *b) { return (intptr_t) b - (intptr_t) a; } -#define pni_head(PTR) \ - (((pni_head_t *) (PTR)) - 1) +const pn_class_t PNI_OBJECT = PN_CLASS(pn_object); +const pn_class_t *PN_OBJECT = &PNI_OBJECT; -void *pn_new(size_t size, const pn_class_t *clazz) +#define pn_void_initialize NULL +static void *pn_void_new(const pn_class_t *clazz, size_t size) { return malloc(size); } +static void pn_void_incref(void *object) {} +static void pn_void_decref(void *object) {} +static int pn_void_refcount(void *object) { return -1; } +#define pn_void_finalize NULL +static void pn_void_free(void *object) { free(object); } +static const pn_class_t *pn_void_reify(void *object) { return PN_VOID; } +uintptr_t pn_void_hashcode(void *object) { return (uintptr_t) object; } +intptr_t pn_void_compare(void *a, void *b) { return (intptr_t) b - (intptr_t) a; } +int pn_void_inspect(void *object, pn_string_t *dst) { return pn_string_addf(dst, "%p", object); } + +const pn_class_t PNI_VOID = PN_METACLASS(pn_void); +const pn_class_t *PN_VOID = &PNI_VOID; + +const char *pn_class_name(const pn_class_t *clazz) { - return pn_new2(size, clazz, NULL); + return clazz->name; } -void *pn_new2(size_t size, const pn_class_t *clazz, void *from) +pn_cid_t pn_class_id(const pn_class_t *clazz) { - pni_head_t *head = (pni_head_t *) malloc(sizeof(pni_head_t) + size); - void *object = head + 1; - pn_initialize(object, clazz); - return object; + return clazz->cid; } -void pn_initialize(void *object, const pn_class_t *clazz) +void *pn_class_new(const pn_class_t *clazz, size_t size) { - pni_head_t *head = pni_head(object); - head->clazz = clazz; - head->refcount = 1; - if (clazz && clazz->initialize) { + assert(clazz); + void *object = clazz->newinst(clazz, size); + if (clazz->initialize) { clazz->initialize(object); } -} - -void *pn_incref(void *object) { - return pn_incref2(object, NULL); -} - -void *pn_incref2(void *object, void *from) { - if (object) { - pni_head(object)->refcount++; - } return object; } -void pn_decref(void *object) { - pn_decref2(object, NULL); -} - -void pn_decref2(void *object, void *from) +void *pn_class_incref(const pn_class_t *clazz, void *object) { + assert(clazz); if (object) { - pni_head_t *head = pni_head(object); - assert(head->refcount > 0); - head->refcount--; - if (!head->refcount) { - pn_finalize(object); - // Check the refcount again in case finalize created a new - // reference. - if (!head->refcount) { - free(head); - } - } + clazz = clazz->reify(object); + clazz->incref(object); } + return object; } -void pn_finalize(void *object) +int pn_class_refcount(const pn_class_t *clazz, void *object) { - if (object) { - pni_head_t *head = pni_head(object); - assert(head->refcount == 0); - if (head->clazz && head->clazz->finalize) { - head->clazz->finalize(object); - } - } + assert(clazz); + clazz = clazz->reify(object); + return clazz->refcount(object); } -int pn_refcount(void *object) +int pn_class_decref(const pn_class_t *clazz, void *object) { - assert(object); - return pni_head(object)->refcount; -} + assert(clazz); -void pn_free(void *object) -{ if (object) { - assert(pn_refcount(object) == 1); - pn_decref(object); - } -} - -const pn_class_t *pn_class(void *object) -{ - assert(object); - return pni_head(object)->clazz; -} - -uintptr_t pn_hashcode(void *object) -{ - if (!object) return 0; - - pni_head_t *head = pni_head(object); - if (head->clazz && head->clazz->hashcode) { - return head->clazz->hashcode(object); - } else { - return (uintptr_t) head; - } -} - -intptr_t pn_compare(void *a, void *b) -{ - if (a == b) return 0; - if (a && b) { - pni_head_t *ha = pni_head(a); - pni_head_t *hb = pni_head(b); - - if (ha->clazz && hb->clazz && ha->clazz == hb->clazz) { - const pn_class_t *clazz = ha->clazz; - if (clazz->compare) { - return clazz->compare(a, b); + clazz = clazz->reify(object); + clazz->decref(object); + int rc = clazz->refcount(object); + if (rc == 0) { + if (clazz->finalize) { + clazz->finalize(object); + // check the refcount again in case the finalizer created a + // new reference + rc = clazz->refcount(object); } - } - } - - return (intptr_t) b - (intptr_t) a; -} - -bool pn_equals(void *a, void *b) -{ - return !pn_compare(a, b); -} - -int pn_inspect(void *object, pn_string_t *dst) -{ - if (!pn_string_get(dst)) { - pn_string_set(dst, ""); - } - - if (object) { - pni_head_t *head = pni_head(object); - const char *name; - if (head->clazz) { - const pn_class_t *clazz = head->clazz; - if (clazz->inspect) { - return clazz->inspect(object, dst); - } else if (clazz->name) { - name = clazz->name; - } else { - name = "object"; + if (rc == 0) { + clazz->free(object); + return 0; } } else { - name = "object"; - } - return pn_string_addf(dst, "%s<%p>", name, object); - } else { - return pn_string_addf(dst, "(null)"); - } -} - -struct pn_list_t { - size_t capacity; - size_t size; - void **elements; - int options; -}; - -size_t pn_list_size(pn_list_t *list) -{ - assert(list); - return list->size; -} - -void *pn_list_get(pn_list_t *list, int index) -{ - assert(list); assert(list->size); - return list->elements[index % list->size]; -} - -void pn_list_set(pn_list_t *list, int index, void *value) -{ - assert(list); assert(list->size); - void *old = list->elements[index % list->size]; - if (list->options & PN_REFCOUNT) pn_decref2(old, list); - list->elements[index % list->size] = value; - if (list->options & PN_REFCOUNT) pn_incref2(value, list); -} - -void pn_list_ensure(pn_list_t *list, size_t capacity) -{ - assert(list); - if (list->capacity < capacity) { - size_t newcap = list->capacity; - while (newcap < capacity) { newcap *= 2; } - list->elements = (void **) realloc(list->elements, newcap * sizeof(void *)); - assert(list->elements); - list->capacity = newcap; - } -} - -int pn_list_add(pn_list_t *list, void *value) -{ - assert(list); - pn_list_ensure(list, list->size + 1); - list->elements[list->size++] = value; - if (list->options & PN_REFCOUNT) pn_incref2(value, list); - return 0; -} - -ssize_t pn_list_index(pn_list_t *list, void *value) -{ - for (size_t i = 0; i < list->size; i++) { - if (pn_equals(list->elements[i], value)) { - return i; - } - } - - return -1; -} - -bool pn_list_remove(pn_list_t *list, void *value) -{ - assert(list); - ssize_t idx = pn_list_index(list, value); - if (idx < 0) { - return false; - } else { - pn_list_del(list, idx, 1); - } - - return true; -} - -void pn_list_del(pn_list_t *list, int index, int n) -{ - assert(list); - index %= list->size; - - if (list->options & PN_REFCOUNT) { - for (int i = 0; i < n; i++) { - pn_decref2(list->elements[index + i], list); - } - } - - size_t slide = list->size - (index + n); - for (size_t i = 0; i < slide; i++) { - list->elements[index + i] = list->elements[index + n + i]; - } - - list->size -= n; -} - -void pn_list_clear(pn_list_t *list) -{ - assert(list); - pn_list_del(list, 0, list->size); -} - -void pn_list_fill(pn_list_t *list, void *value, int n) -{ - for (int i = 0; i < n; i++) { - pn_list_add(list, value); - } -} - -typedef struct { - pn_list_t *list; - size_t index; -} pni_list_iter_t; - -static void *pni_list_next(void *ctx) -{ - pni_list_iter_t *iter = (pni_list_iter_t *) ctx; - if (iter->index < pn_list_size(iter->list)) { - return pn_list_get(iter->list, iter->index++); - } else { - return NULL; - } -} - -void pn_list_iterator(pn_list_t *list, pn_iterator_t *iter) -{ - pni_list_iter_t *liter = (pni_list_iter_t *) pn_iterator_start(iter, pni_list_next, sizeof(pni_list_iter_t)); - liter->list = list; - liter->index = 0; -} - -static void pn_list_finalize(void *object) -{ - assert(object); - pn_list_t *list = (pn_list_t *) object; - for (size_t i = 0; i < list->size; i++) { - if (list->options & PN_REFCOUNT) pn_decref2(pn_list_get(list, i), list); - } - free(list->elements); -} - -static uintptr_t pn_list_hashcode(void *object) -{ - assert(object); - pn_list_t *list = (pn_list_t *) object; - uintptr_t hash = 1; - - for (size_t i = 0; i < list->size; i++) { - hash = hash * 31 + pn_hashcode(pn_list_get(list, i)); - } - - return hash; -} - -static intptr_t pn_list_compare(void *oa, void *ob) -{ - assert(oa); assert(ob); - pn_list_t *a = (pn_list_t *) oa; - pn_list_t *b = (pn_list_t *) ob; - - size_t na = pn_list_size(a); - size_t nb = pn_list_size(b); - if (na != nb) { - return nb - na; - } else { - for (size_t i = 0; i < na; i++) { - intptr_t delta = pn_compare(pn_list_get(a, i), pn_list_get(b, i)); - if (delta) return delta; + return rc; } } return 0; } -static int pn_list_inspect(void *obj, pn_string_t *dst) -{ - assert(obj); - pn_list_t *list = (pn_list_t *) obj; - int err = pn_string_addf(dst, "["); - if (err) return err; - size_t n = pn_list_size(list); - for (size_t i = 0; i < n; i++) { - if (i > 0) { - err = pn_string_addf(dst, ", "); - if (err) return err; - } - err = pn_inspect(pn_list_get(list, i), dst); - if (err) return err; - } - return pn_string_addf(dst, "]"); -} - -#define pn_list_initialize NULL - -pn_list_t *pn_list(size_t capacity, int options) -{ - static const pn_class_t clazz = PN_CLASS(pn_list); - - pn_list_t *list = (pn_list_t *) pn_new(sizeof(pn_list_t), &clazz); - list->capacity = capacity ? capacity : 16; - list->elements = (void **) malloc(list->capacity * sizeof(void *)); - list->size = 0; - list->options = options; - return list; -} - -#define PNI_ENTRY_FREE (0) -#define PNI_ENTRY_LINK (1) -#define PNI_ENTRY_TAIL (2) - -typedef struct { - void *key; - void *value; - size_t next; - uint8_t state; -} pni_entry_t; - -struct pn_map_t { - pni_entry_t *entries; - size_t capacity; - size_t addressable; - size_t size; - uintptr_t (*hashcode)(void *key); - bool (*equals)(void *a, void *b); - float load_factor; - bool count_keys; - bool count_values; - bool inspect_keys; -}; - -static void pn_map_finalize(void *object) -{ - pn_map_t *map = (pn_map_t *) object; - - if (map->count_keys || map->count_values) { - for (size_t i = 0; i < map->capacity; i++) { - if (map->entries[i].state != PNI_ENTRY_FREE) { - if (map->count_keys) pn_decref2(map->entries[i].key, map); - if (map->count_values) pn_decref2(map->entries[i].value, map); - } - } - } - - free(map->entries); -} - -static uintptr_t pn_map_hashcode(void *object) +void pn_class_free(const pn_class_t *clazz, void *object) { - pn_map_t *map = (pn_map_t *) object; - - uintptr_t hashcode = 0; - - for (size_t i = 0; i < map->capacity; i++) { - if (map->entries[i].state != PNI_ENTRY_FREE) { - void *key = map->entries[i].key; - void *value = map->entries[i].value; - hashcode += pn_hashcode(key) ^ pn_hashcode(value); - } - } - - return hashcode; -} - -static void pni_map_allocate(pn_map_t *map) -{ - map->entries = (pni_entry_t *) malloc(map->capacity * sizeof (pni_entry_t)); - for (size_t i = 0; i < map->capacity; i++) { - map->entries[i].key = NULL; - map->entries[i].value = NULL; - map->entries[i].next = 0; - map->entries[i].state = PNI_ENTRY_FREE; - } - map->size = 0; -} - -static int pn_map_inspect(void *obj, pn_string_t *dst) -{ - assert(obj); - pn_map_t *map = (pn_map_t *) obj; - int err = pn_string_addf(dst, "{"); - if (err) return err; - pn_handle_t entry = pn_map_head(map); - bool first = true; - while (entry) { - if (first) { - first = false; - } else { - err = pn_string_addf(dst, ", "); - if (err) return err; - } - if (map->inspect_keys) { - err = pn_inspect(pn_map_key(map, entry), dst); + assert(clazz); + if (object) { + clazz = clazz->reify(object); + int rc = clazz->refcount(object); + assert(rc == 1 || rc == -1); + if (rc == 1) { + rc = pn_class_decref(clazz, object); + assert(rc == 0); } else { - err = pn_string_addf(dst, "%p", pn_map_key(map, entry)); + if (clazz->finalize) { + clazz->finalize(object); + } + clazz->free(object); } - if (err) return err; - err = pn_string_addf(dst, ": "); - if (err) return err; - err = pn_inspect(pn_map_value(map, entry), dst); - if (err) return err; - entry = pn_map_next(map, entry); } - return pn_string_addf(dst, "}"); -} - -#define pn_map_initialize NULL -#define pn_map_compare NULL - -pn_map_t *pn_map(size_t capacity, float load_factor, int options) -{ - static const pn_class_t clazz = PN_CLASS(pn_map); - - pn_map_t *map = (pn_map_t *) pn_new(sizeof(pn_map_t), &clazz); - map->capacity = capacity ? capacity : 16; - map->addressable = (size_t) (map->capacity * 0.86); - if (!map->addressable) map->addressable = map->capacity; - map->load_factor = load_factor; - map->hashcode = pn_hashcode; - map->equals = pn_equals; - map->count_keys = (options & PN_REFCOUNT) || (options & PN_REFCOUNT_KEY); - map->count_values = (options & PN_REFCOUNT) || (options & PN_REFCOUNT_VALUE); - map->inspect_keys = true; - pni_map_allocate(map); - return map; -} - -size_t pn_map_size(pn_map_t *map) -{ - assert(map); - return map->size; } -static float pni_map_load(pn_map_t *map) +const pn_class_t *pn_class_reify(const pn_class_t *clazz, void *object) { - return ((float) map->size) / ((float) map->addressable); -} - -static bool pni_map_ensure(pn_map_t *map, size_t capacity) -{ - float load = pni_map_load(map); - if (capacity <= map->capacity && load <= map->load_factor) { - return false; - } - - size_t oldcap = map->capacity; - - while (map->capacity < capacity || pni_map_load(map) > map->load_factor) { - map->capacity *= 2; - map->addressable = (size_t) (0.86 * map->capacity); - } - - pni_entry_t *entries = map->entries; - pni_map_allocate(map); - - for (size_t i = 0; i < oldcap; i++) { - if (entries[i].state != PNI_ENTRY_FREE) { - void *key = entries[i].key; - void *value = entries[i].value; - pn_map_put(map, key, value); - if (map->count_keys) pn_decref2(key, map); - if (map->count_values) pn_decref2(value, map); - } - } - - free(entries); - return true; + assert(clazz); + return clazz->reify(object); } -static pni_entry_t *pni_map_entry(pn_map_t *map, void *key, pni_entry_t **pprev, bool create) +uintptr_t pn_class_hashcode(const pn_class_t *clazz, void *object) { - uintptr_t hashcode = map->hashcode(key); + assert(clazz); - pni_entry_t *entry = &map->entries[hashcode % map->addressable]; - pni_entry_t *prev = NULL; - - if (entry->state == PNI_ENTRY_FREE) { - if (create) { - entry->state = PNI_ENTRY_TAIL; - entry->key = key; - if (map->count_keys) pn_incref2(key, map); - map->size++; - return entry; - } else { - return NULL; - } - } - - while (true) { - if (map->equals(entry->key, key)) { - if (pprev) *pprev = prev; - return entry; - } - - if (entry->state == PNI_ENTRY_TAIL) { - break; - } else { - prev = entry; - entry = &map->entries[entry->next]; - } - } + if (!object) return 0; - if (create) { - if (pni_map_ensure(map, map->size + 1)) { - // if we had to grow the table we need to start over - return pni_map_entry(map, key, pprev, create); - } + clazz = clazz->reify(object); - size_t empty = 0; - for (size_t i = 0; i < map->capacity; i++) { - size_t idx = map->capacity - i - 1; - if (map->entries[idx].state == PNI_ENTRY_FREE) { - empty = idx; - break; - } - } - entry->next = empty; - entry->state = PNI_ENTRY_LINK; - map->entries[empty].state = PNI_ENTRY_TAIL; - map->entries[empty].key = key; - if (map->count_keys) pn_incref2(key, map); - if (pprev) *pprev = entry; - map->size++; - return &map->entries[empty]; + if (clazz->hashcode) { + return clazz->hashcode(object); } else { - return NULL; + return (uintptr_t) object; } } -int pn_map_put(pn_map_t *map, void *key, void *value) -{ - assert(map); - pni_entry_t *entry = pni_map_entry(map, key, NULL, true); - if (map->count_values) pn_decref2(entry->value, map); - entry->value = value; - if (map->count_values) pn_incref2(value, map); - return 0; -} - -void *pn_map_get(pn_map_t *map, void *key) +intptr_t pn_class_compare(const pn_class_t *clazz, void *a, void *b) { - assert(map); - pni_entry_t *entry = pni_map_entry(map, key, NULL, false); - return entry ? entry->value : NULL; -} - -void pn_map_del(pn_map_t *map, void *key) -{ - assert(map); - pni_entry_t *prev = NULL; - pni_entry_t *entry = pni_map_entry(map, key, &prev, false); - if (entry) { - void *dref_key = (map->count_keys) ? entry->key : NULL; - void *dref_value = (map->count_values) ? entry->value : NULL; - if (prev) { - prev->next = entry->next; - prev->state = entry->state; - } else if (entry->next) { - assert(entry->state == PNI_ENTRY_LINK); - pni_entry_t *next = &map->entries[entry->next]; - *entry = *next; - entry = next; - } - entry->state = PNI_ENTRY_FREE; - entry->next = 0; - entry->key = NULL; - entry->value = NULL; - map->size--; - if (dref_key) pn_decref2(dref_key, map); - if (dref_value) pn_decref2(dref_value, map); - } -} + assert(clazz); -pn_handle_t pn_map_head(pn_map_t *map) -{ - assert(map); - for (size_t i = 0; i < map->capacity; i++) - { - if (map->entries[i].state != PNI_ENTRY_FREE) { - return i + 1; - } - } + if (a == b) return 0; - return 0; -} + clazz = clazz->reify(a); -pn_handle_t pn_map_next(pn_map_t *map, pn_handle_t entry) -{ - for (size_t i = entry; i < map->capacity; i++) { - if (map->entries[i].state != PNI_ENTRY_FREE) { - return i + 1; - } + if (a && b && clazz->compare) { + return clazz->compare(a, b); + } else { + return (intptr_t) b - (intptr_t) a; } - - return 0; -} - -void *pn_map_key(pn_map_t *map, pn_handle_t entry) -{ - assert(map); - assert(entry); - return map->entries[entry - 1].key; -} - -void *pn_map_value(pn_map_t *map, pn_handle_t entry) -{ - assert(map); - assert(entry); - return map->entries[entry - 1].value; -} - -struct pn_hash_t { - pn_map_t map; -}; - -static uintptr_t pni_identity_hashcode(void *obj) -{ - return (uintptr_t ) obj; -} - -static bool pni_identity_equals(void *a, void *b) -{ - return a == b; -} - -pn_hash_t *pn_hash(size_t capacity, float load_factor, int options) -{ - pn_hash_t *hash = (pn_hash_t *) pn_map(capacity, load_factor, 0); - hash->map.hashcode = pni_identity_hashcode; - hash->map.equals = pni_identity_equals; - hash->map.count_keys = false; - hash->map.count_values = options & PN_REFCOUNT; - hash->map.inspect_keys = false; - return hash; -} - -size_t pn_hash_size(pn_hash_t *hash) -{ - return pn_map_size(&hash->map); -} - -int pn_hash_put(pn_hash_t *hash, uintptr_t key, void *value) -{ - return pn_map_put(&hash->map, (void *) key, value); -} - -void *pn_hash_get(pn_hash_t *hash, uintptr_t key) -{ - return pn_map_get(&hash->map, (void *) key); -} - -void pn_hash_del(pn_hash_t *hash, uintptr_t key) -{ - pn_map_del(&hash->map, (void *) key); -} - -pn_handle_t pn_hash_head(pn_hash_t *hash) -{ - return pn_map_head(&hash->map); -} - -pn_handle_t pn_hash_next(pn_hash_t *hash, pn_handle_t entry) -{ - return pn_map_next(&hash->map, entry); } -uintptr_t pn_hash_key(pn_hash_t *hash, pn_handle_t entry) +bool pn_class_equals(const pn_class_t *clazz, void *a, void *b) { - return (uintptr_t) pn_map_key(&hash->map, entry); + return pn_class_compare(clazz, a, b) == 0; } -void *pn_hash_value(pn_hash_t *hash, pn_handle_t entry) +int pn_class_inspect(const pn_class_t *clazz, void *object, pn_string_t *dst) { - return pn_map_value(&hash->map, entry); -} - - -#define PNI_NULL_SIZE (-1) - -struct pn_string_t { - char *bytes; - ssize_t size; // PNI_NULL_SIZE (-1) means null - size_t capacity; -}; - -static void pn_string_finalize(void *object) -{ - pn_string_t *string = (pn_string_t *) object; - free(string->bytes); -} - -static uintptr_t pn_string_hashcode(void *object) -{ - pn_string_t *string = (pn_string_t *) object; - if (string->size == PNI_NULL_SIZE) { - return 0; - } + assert(clazz); - uintptr_t hashcode = 1; - for (ssize_t i = 0; i < string->size; i++) { - hashcode = hashcode * 31 + string->bytes[i]; - } - return hashcode; -} + clazz = clazz->reify(object); -static intptr_t pn_string_compare(void *oa, void *ob) -{ - pn_string_t *a = (pn_string_t *) oa; - pn_string_t *b = (pn_string_t *) ob; - if (a->size != b->size) { - return b->size - a->size; - } - - if (a->size == PNI_NULL_SIZE) { - return 0; - } else { - return memcmp(a->bytes, b->bytes, a->size); - } -} - -static int pn_string_inspect(void *obj, pn_string_t *dst) -{ - pn_string_t *str = (pn_string_t *) obj; - if (str->size == PNI_NULL_SIZE) { - return pn_string_addf(dst, "null"); + if (!pn_string_get(dst)) { + pn_string_set(dst, ""); } - int err = pn_string_addf(dst, "\""); - - for (int i = 0; i < str->size; i++) { - uint8_t c = str->bytes[i]; - if (isprint(c)) { - err = pn_string_addf(dst, "%c", c); - if (err) return err; - } else { - err = pn_string_addf(dst, "\\x%.2x", c); - if (err) return err; - } + if (object && clazz->inspect) { + return clazz->inspect(object, dst); } - return pn_string_addf(dst, "\""); -} + const char *name = clazz->name ? clazz->name : "<anon>"; -pn_string_t *pn_string(const char *bytes) -{ - return pn_stringn(bytes, bytes ? strlen(bytes) : 0); + return pn_string_addf(dst, "%s<%p>", name, object); } -#define pn_string_initialize NULL +typedef struct { + const pn_class_t *clazz; + int refcount; +} pni_head_t; +#define pni_head(PTR) \ + (((pni_head_t *) (PTR)) - 1) -pn_string_t *pn_stringn(const char *bytes, size_t n) +void *pn_object_new(const pn_class_t *clazz, size_t size) { - static const pn_class_t clazz = PN_CLASS(pn_string); - pn_string_t *string = (pn_string_t *) pn_new(sizeof(pn_string_t), &clazz); - string->capacity = n ? n * sizeof(char) : 16; - string->bytes = (char *) malloc(string->capacity); - pn_string_setn(string, bytes, n); - return string; + pni_head_t *head = (pni_head_t *) malloc(sizeof(pni_head_t) + size); + void *object = head + 1; + head->clazz = clazz; + head->refcount = 1; + return object; } -const char *pn_string_get(pn_string_t *string) +const pn_class_t *pn_object_reify(void *object) { - assert(string); - if (string->size == PNI_NULL_SIZE) { - return NULL; + if (object) { + return pni_head(object)->clazz; } else { - return string->bytes; + return PN_OBJECT; } } -size_t pn_string_size(pn_string_t *string) +void pn_object_incref(void *object) { - assert(string); - if (string->size == PNI_NULL_SIZE) { - return 0; - } else { - return string->size; + if (object) { + pni_head(object)->refcount++; } } -int pn_string_set(pn_string_t *string, const char *bytes) +int pn_object_refcount(void *object) { - return pn_string_setn(string, bytes, bytes ? strlen(bytes) : 0); -} - -int pn_string_grow(pn_string_t *string, size_t capacity) -{ - bool grow = false; - while (string->capacity < (capacity*sizeof(char) + 1)) { - string->capacity *= 2; - grow = true; - } - - if (grow) { - char *growed = (char *) realloc(string->bytes, string->capacity); - if (growed) { - string->bytes = growed; - } else { - return PN_ERR; - } - } - - return 0; + assert(object); + return pni_head(object)->refcount; } -int pn_string_setn(pn_string_t *string, const char *bytes, size_t n) +void pn_object_decref(void *object) { - int err = pn_string_grow(string, n); - if (err) return err; - - if (bytes) { - memcpy(string->bytes, bytes, n*sizeof(char)); - string->bytes[n] = '\0'; - string->size = n; - } else { - string->size = PNI_NULL_SIZE; - } - - return 0; + pni_head_t *head = pni_head(object); + assert(head->refcount > 0); + head->refcount--; } -ssize_t pn_string_put(pn_string_t *string, char *dst) +void pn_object_free(void *object) { - assert(string); - assert(dst); - - if (string->size != PNI_NULL_SIZE) { - memcpy(dst, string->bytes, string->size + 1); - } - - return string->size; + pni_head_t *head = pni_head(object); + free(head); } -void pn_string_clear(pn_string_t *string) +void *pn_incref(void *object) { - pn_string_set(string, NULL); + return pn_class_incref(PN_OBJECT, object); } -int pn_string_format(pn_string_t *string, const char *format, ...) +int pn_decref(void *object) { - va_list ap; - - va_start(ap, format); - int err = pn_string_vformat(string, format, ap); - va_end(ap); - return err; + return pn_class_decref(PN_OBJECT, object); } -int pn_string_vformat(pn_string_t *string, const char *format, va_list ap) +int pn_refcount(void *object) { - pn_string_set(string, ""); - return pn_string_vaddf(string, format, ap); + return pn_class_refcount(PN_OBJECT, object); } -int pn_string_addf(pn_string_t *string, const char *format, ...) +void pn_free(void *object) { - va_list ap; - - va_start(ap, format); - int err = pn_string_vaddf(string, format, ap); - va_end(ap); - return err; + pn_class_free(PN_OBJECT, object); } -int pn_string_vaddf(pn_string_t *string, const char *format, va_list ap) +const pn_class_t *pn_class(void *object) { - va_list copy; - - if (string->size == PNI_NULL_SIZE) { - return PN_ERR; - } - - while (true) { - va_copy(copy, ap); - int err = vsnprintf(string->bytes + string->size, string->capacity - string->size, format, copy); - va_end(copy); - if (err < 0) { - return err; - } else if ((size_t) err >= string->capacity - string->size) { - pn_string_grow(string, string->size + err); - } else { - string->size += err; - return 0; - } - } + return pn_class_reify(PN_OBJECT, object); } -char *pn_string_buffer(pn_string_t *string) +uintptr_t pn_hashcode(void *object) { - assert(string); - return string->bytes; + return pn_class_hashcode(PN_OBJECT, object); } -size_t pn_string_capacity(pn_string_t *string) +intptr_t pn_compare(void *a, void *b) { - assert(string); - return string->capacity - 1; + return pn_class_compare(PN_OBJECT, a, b); } -int pn_string_resize(pn_string_t *string, size_t size) +bool pn_equals(void *a, void *b) { - assert(string); - int err = pn_string_grow(string, size); - if (err) return err; - string->size = size; - string->bytes[size] = '\0'; - return 0; + return !pn_compare(a, b); } -int pn_string_copy(pn_string_t *string, pn_string_t *src) +int pn_inspect(void *object, pn_string_t *dst) { - assert(string); - return pn_string_setn(string, pn_string_get(src), pn_string_size(src)); + return pn_class_inspect(PN_OBJECT, object, dst); } -struct pn_iterator_t { - pn_iterator_next_t next; - size_t size; - void *state; -}; +#define pn_weakref_new NULL +#define pn_weakref_initialize NULL +#define pn_weakref_finalize NULL +#define pn_weakref_free NULL -static void pn_iterator_initialize(void *object) -{ - pn_iterator_t *it = (pn_iterator_t *) object; - it->next = NULL; - it->size = 0; - it->state = NULL; +static void pn_weakref_incref(void *object) {} +static void pn_weakref_decref(void *object) {} +static int pn_weakref_refcount(void *object) { return -1; } +static const pn_class_t *pn_weakref_reify(void *object) { + return PN_WEAKREF; } - -static void pn_iterator_finalize(void *object) -{ - pn_iterator_t *it = (pn_iterator_t *) object; - free(it->state); +static uintptr_t pn_weakref_hashcode(void *object) { + return pn_hashcode(object); } - -#define pn_iterator_hashcode NULL -#define pn_iterator_compare NULL -#define pn_iterator_inspect NULL - -pn_iterator_t *pn_iterator() -{ - static const pn_class_t clazz = PN_CLASS(pn_iterator); - pn_iterator_t *it = (pn_iterator_t *) pn_new(sizeof(pn_iterator_t), &clazz); - return it; +static intptr_t pn_weakref_compare(void *a, void *b) { + return pn_compare(a, b); } - -void *pn_iterator_start(pn_iterator_t *iterator, pn_iterator_next_t next, - size_t size) { - assert(iterator); - assert(next); - iterator->next = next; - if (iterator->size < size) { - iterator->state = realloc(iterator->state, size); - } - return iterator->state; +static int pn_weakref_inspect(void *object, pn_string_t *dst) { + return pn_inspect(object, dst); } -void *pn_iterator_next(pn_iterator_t *iterator) { - assert(iterator); - if (iterator->next) { - void *result = iterator->next(iterator->state); - if (!result) iterator->next = NULL; - return result; - } else { - return NULL; - } -} +const pn_class_t PNI_WEAKREF = PN_METACLASS(pn_weakref); +const pn_class_t *PN_WEAKREF = &PNI_WEAKREF;
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/92b8098c/proton-c/src/object/string.c ---------------------------------------------------------------------- diff --git a/proton-c/src/object/string.c b/proton-c/src/object/string.c new file mode 100644 index 0000000..7b900ca --- /dev/null +++ b/proton-c/src/object/string.c @@ -0,0 +1,270 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include "platform.h" + +#include <proton/error.h> +#include <proton/object.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <ctype.h> + +#define PNI_NULL_SIZE (-1) + +struct pn_string_t { + char *bytes; + ssize_t size; // PNI_NULL_SIZE (-1) means null + size_t capacity; +}; + +static void pn_string_finalize(void *object) +{ + pn_string_t *string = (pn_string_t *) object; + free(string->bytes); +} + +static uintptr_t pn_string_hashcode(void *object) +{ + pn_string_t *string = (pn_string_t *) object; + if (string->size == PNI_NULL_SIZE) { + return 0; + } + + uintptr_t hashcode = 1; + for (ssize_t i = 0; i < string->size; i++) { + hashcode = hashcode * 31 + string->bytes[i]; + } + return hashcode; +} + +static intptr_t pn_string_compare(void *oa, void *ob) +{ + pn_string_t *a = (pn_string_t *) oa; + pn_string_t *b = (pn_string_t *) ob; + if (a->size != b->size) { + return b->size - a->size; + } + + if (a->size == PNI_NULL_SIZE) { + return 0; + } else { + return memcmp(a->bytes, b->bytes, a->size); + } +} + +static int pn_string_inspect(void *obj, pn_string_t *dst) +{ + pn_string_t *str = (pn_string_t *) obj; + if (str->size == PNI_NULL_SIZE) { + return pn_string_addf(dst, "null"); + } + + int err = pn_string_addf(dst, "\""); + + for (int i = 0; i < str->size; i++) { + uint8_t c = str->bytes[i]; + if (isprint(c)) { + err = pn_string_addf(dst, "%c", c); + if (err) return err; + } else { + err = pn_string_addf(dst, "\\x%.2x", c); + if (err) return err; + } + } + + return pn_string_addf(dst, "\""); +} + +pn_string_t *pn_string(const char *bytes) +{ + return pn_stringn(bytes, bytes ? strlen(bytes) : 0); +} + +#define pn_string_initialize NULL + + +pn_string_t *pn_stringn(const char *bytes, size_t n) +{ + static const pn_class_t clazz = PN_CLASS(pn_string); + pn_string_t *string = (pn_string_t *) pn_class_new(&clazz, sizeof(pn_string_t)); + string->capacity = n ? n * sizeof(char) : 16; + string->bytes = (char *) malloc(string->capacity); + pn_string_setn(string, bytes, n); + return string; +} + +const char *pn_string_get(pn_string_t *string) +{ + assert(string); + if (string->size == PNI_NULL_SIZE) { + return NULL; + } else { + return string->bytes; + } +} + +size_t pn_string_size(pn_string_t *string) +{ + assert(string); + if (string->size == PNI_NULL_SIZE) { + return 0; + } else { + return string->size; + } +} + +int pn_string_set(pn_string_t *string, const char *bytes) +{ + return pn_string_setn(string, bytes, bytes ? strlen(bytes) : 0); +} + +int pn_string_grow(pn_string_t *string, size_t capacity) +{ + bool grow = false; + while (string->capacity < (capacity*sizeof(char) + 1)) { + string->capacity *= 2; + grow = true; + } + + if (grow) { + char *growed = (char *) realloc(string->bytes, string->capacity); + if (growed) { + string->bytes = growed; + } else { + return PN_ERR; + } + } + + return 0; +} + +int pn_string_setn(pn_string_t *string, const char *bytes, size_t n) +{ + int err = pn_string_grow(string, n); + if (err) return err; + + if (bytes) { + memcpy(string->bytes, bytes, n*sizeof(char)); + string->bytes[n] = '\0'; + string->size = n; + } else { + string->size = PNI_NULL_SIZE; + } + + return 0; +} + +ssize_t pn_string_put(pn_string_t *string, char *dst) +{ + assert(string); + assert(dst); + + if (string->size != PNI_NULL_SIZE) { + memcpy(dst, string->bytes, string->size + 1); + } + + return string->size; +} + +void pn_string_clear(pn_string_t *string) +{ + pn_string_set(string, NULL); +} + +int pn_string_format(pn_string_t *string, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + int err = pn_string_vformat(string, format, ap); + va_end(ap); + return err; +} + +int pn_string_vformat(pn_string_t *string, const char *format, va_list ap) +{ + pn_string_set(string, ""); + return pn_string_vaddf(string, format, ap); +} + +int pn_string_addf(pn_string_t *string, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + int err = pn_string_vaddf(string, format, ap); + va_end(ap); + return err; +} + +int pn_string_vaddf(pn_string_t *string, const char *format, va_list ap) +{ + va_list copy; + + if (string->size == PNI_NULL_SIZE) { + return PN_ERR; + } + + while (true) { + va_copy(copy, ap); + int err = vsnprintf(string->bytes + string->size, string->capacity - string->size, format, copy); + va_end(copy); + if (err < 0) { + return err; + } else if ((size_t) err >= string->capacity - string->size) { + pn_string_grow(string, string->size + err); + } else { + string->size += err; + return 0; + } + } +} + +char *pn_string_buffer(pn_string_t *string) +{ + assert(string); + return string->bytes; +} + +size_t pn_string_capacity(pn_string_t *string) +{ + assert(string); + return string->capacity - 1; +} + +int pn_string_resize(pn_string_t *string, size_t size) +{ + assert(string); + int err = pn_string_grow(string, size); + if (err) return err; + string->size = size; + string->bytes[size] = '\0'; + return 0; +} + +int pn_string_copy(pn_string_t *string, pn_string_t *src) +{ + assert(string); + return pn_string_setn(string, pn_string_get(src), pn_string_size(src)); +} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/92b8098c/proton-c/src/platform.c ---------------------------------------------------------------------- diff --git a/proton-c/src/platform.c b/proton-c/src/platform.c index 1f2cac7..8f8ac5f 100644 --- a/proton-c/src/platform.c +++ b/proton-c/src/platform.c @@ -21,7 +21,6 @@ #include "platform.h" #include "util.h" -#include "proton/util.h" // for pn_fatal() ?should pn_fatal() be public? /* Allow for systems that do not implement clock_gettime()*/ #ifdef USE_CLOCK_GETTIME @@ -29,7 +28,7 @@ pn_timestamp_t pn_i_now(void) { struct timespec now; - if (clock_gettime(CLOCK_REALTIME, &now)) pn_fatal("clock_gettime() failed\n"); + if (clock_gettime(CLOCK_REALTIME, &now)) pni_fatal("clock_gettime() failed\n"); return ((pn_timestamp_t)now.tv_sec) * 1000 + (now.tv_nsec / 1000000); } #elif defined(USE_WIN_FILETIME) @@ -49,7 +48,7 @@ pn_timestamp_t pn_i_now(void) pn_timestamp_t pn_i_now(void) { struct timeval now; - if (gettimeofday(&now, NULL)) pn_fatal("gettimeofday failed\n"); + if (gettimeofday(&now, NULL)) pni_fatal("gettimeofday failed\n"); return ((pn_timestamp_t)now.tv_sec) * 1000 + (now.tv_usec / 1000); } #endif @@ -93,12 +92,12 @@ char* pn_i_genuuid(void) { #ifdef USE_STRERROR_R #include <string.h> static void pn_i_strerror(int errnum, char *buf, size_t buflen) { - if (strerror_r(errnum, buf, buflen) != 0) pn_fatal("strerror_r() failed\n"); + if (strerror_r(errnum, buf, buflen) != 0) pni_fatal("strerror_r() failed\n"); } #elif USE_STRERROR_S #include <string.h> static void pn_i_strerror(int errnum, char *buf, size_t buflen) { - if (strerror_s(buf, buflen, errnum) != 0) pn_fatal("strerror_s() failed\n"); + if (strerror_s(buf, buflen, errnum) != 0) pni_fatal("strerror_s() failed\n"); } #elif USE_OLD_STRERROR // This is thread safe on some platforms, and the only option on others http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/92b8098c/proton-c/src/posix/driver.c ---------------------------------------------------------------------- diff --git a/proton-c/src/posix/driver.c b/proton-c/src/posix/driver.c index b128cb2..d71ca7d 100644 --- a/proton-c/src/posix/driver.c +++ b/proton-c/src/posix/driver.c @@ -37,11 +37,9 @@ #include <proton/io.h> #include <proton/sasl.h> #include <proton/ssl.h> -#include <proton/util.h> #include <proton/object.h> -#include "../util.h" -#include "../platform.h" -#include "../ssl/ssl-internal.h" +#include "util.h" +#include "platform.h" /* Decls */ @@ -342,12 +340,12 @@ void pn_connector_set_connection(pn_connector_t *ctor, pn_connection_t *connecti { if (!ctor) return; if (ctor->connection) { - pn_decref(ctor->connection); + pn_class_decref(PN_OBJECT, ctor->connection); pn_transport_unbind(ctor->transport); } ctor->connection = connection; if (ctor->connection) { - pn_incref(ctor->connection); + pn_class_incref(PN_OBJECT, ctor->connection); pn_transport_bind(ctor->transport, connection); } if (ctor->transport) pn_transport_trace(ctor->transport, ctor->trace); @@ -404,7 +402,7 @@ void pn_connector_free(pn_connector_t *ctor) if (ctor->driver) pn_driver_remove_connector(ctor->driver, ctor); pn_transport_free(ctor->transport); ctor->transport = NULL; - if (ctor->connection) pn_decref(ctor->connection); + if (ctor->connection) pn_class_decref(PN_OBJECT, ctor->connection); ctor->connection = NULL; free(ctor); } http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/92b8098c/proton-c/src/posix/io.c ---------------------------------------------------------------------- diff --git a/proton-c/src/posix/io.c b/proton-c/src/posix/io.c index 4fa223f..8fbbb0b 100644 --- a/proton-c/src/posix/io.c +++ b/proton-c/src/posix/io.c @@ -35,7 +35,7 @@ #include <fcntl.h> #include <assert.h> -#include "../platform.h" +#include "platform.h" #define MAX_HOST (1024) #define MAX_SERV (64) @@ -69,7 +69,7 @@ void pn_io_finalize(void *obj) pn_io_t *pn_io(void) { static const pn_class_t clazz = PN_CLASS(pn_io); - pn_io_t *io = (pn_io_t *) pn_new(sizeof(pn_io_t), &clazz); + pn_io_t *io = (pn_io_t *) pn_class_new(&clazz, sizeof(pn_io_t)); return io; } http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/92b8098c/proton-c/src/posix/selector.c ---------------------------------------------------------------------- diff --git a/proton-c/src/posix/selector.c b/proton-c/src/posix/selector.c index 14a97ee..9c870a7 100644 --- a/proton-c/src/posix/selector.c +++ b/proton-c/src/posix/selector.c @@ -24,9 +24,9 @@ #include <poll.h> #include <stdlib.h> #include <assert.h> -#include "../platform.h" -#include "../selectable.h" -#include "../util.h" +#include "platform.h" +#include "selectable.h" +#include "util.h" struct pn_selector_t { struct pollfd *fds; @@ -45,7 +45,7 @@ void pn_selector_initialize(void *obj) selector->fds = NULL; selector->deadlines = NULL; selector->capacity = 0; - selector->selectables = pn_list(0, 0); + selector->selectables = pn_list(PN_WEAKREF, 0); selector->deadline = 0; selector->current = 0; selector->awoken = 0; @@ -68,7 +68,7 @@ void pn_selector_finalize(void *obj) pn_selector_t *pni_selector(void) { static const pn_class_t clazz = PN_CLASS(pn_selector); - pn_selector_t *selector = (pn_selector_t *) pn_new(sizeof(pn_selector_t), &clazz); + pn_selector_t *selector = (pn_selector_t *) pn_class_new(&clazz, sizeof(pn_selector_t)); return selector; } http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/92b8098c/proton-c/src/proton.c ---------------------------------------------------------------------- diff --git a/proton-c/src/proton.c b/proton-c/src/proton.c index 2b7d313..495659a 100644 --- a/proton-c/src/proton.c +++ b/proton-c/src/proton.c @@ -29,16 +29,18 @@ #include "pncompat/misc_funcs.inc" #include <stdio.h> +#include <stdlib.h> #include <string.h> -#include <proton/driver.h> -#include <proton/message.h> -#include <proton/util.h> + +#include "proton/buffer.h" +#include "proton/codec.h" +#include "proton/driver.h" +#include "proton/engine.h" +#include "proton/message.h" +#include "proton/version.h" #include "util.h" -#include <proton/version.h> -#include <proton/codec.h> -#include <proton/buffer.h> -#include <proton/parser.h> #include "platform_fmt.h" + #include "protocol.h" void error_exit(const char* fmt, ...) http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/92b8098c/proton-c/src/sasl/sasl.c ---------------------------------------------------------------------- diff --git a/proton-c/src/sasl/sasl.c b/proton-c/src/sasl/sasl.c index 9c7ba1e..f926b1b 100644 --- a/proton-c/src/sasl/sasl.c +++ b/proton-c/src/sasl/sasl.c @@ -25,13 +25,13 @@ #include <string.h> #include <proton/buffer.h> #include <proton/framing.h> -#include <proton/engine.h> // XXX: just needed for PN_EOS +#include <proton/error.h> #include <proton/sasl.h> #include "protocol.h" #include "dispatch_actions.h" -#include "../dispatcher/dispatcher.h" -#include "../engine/engine-internal.h" -#include "../util.h" +#include "engine/engine-internal.h" +#include "dispatcher/dispatcher.h" +#include "util.h" struct pn_sasl_t { http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/92b8098c/proton-c/src/selectable.c ---------------------------------------------------------------------- diff --git a/proton-c/src/selectable.c b/proton-c/src/selectable.c index 1f39a38..d3adee4 100644 --- a/proton-c/src/selectable.c +++ b/proton-c/src/selectable.c @@ -91,7 +91,7 @@ pn_selectable_t *pni_selectable(ssize_t (*capacity)(pn_selectable_t *), void (*finalize)(pn_selectable_t *)) { static const pn_class_t clazz = PN_CLASS(pn_selectable); - pn_selectable_t *selectable = (pn_selectable_t *) pn_new(sizeof(pn_selectable_t), &clazz); + pn_selectable_t *selectable = (pn_selectable_t *) pn_class_new(&clazz, sizeof(pn_selectable_t)); selectable->capacity = capacity; selectable->pending = pending; selectable->readable = readable; http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/92b8098c/proton-c/src/ssl/openssl.c ---------------------------------------------------------------------- diff --git a/proton-c/src/ssl/openssl.c b/proton-c/src/ssl/openssl.c index db3af4c..62556fa 100644 --- a/proton-c/src/ssl/openssl.c +++ b/proton-c/src/ssl/openssl.c @@ -20,11 +20,10 @@ */ #include <proton/ssl.h> -#include "./ssl-internal.h" #include <proton/engine.h> -#include "../engine/engine-internal.h" -#include "../platform.h" -#include "../util.h" +#include "engine/engine-internal.h" +#include "platform.h" +#include "util.h" #include <openssl/ssl.h> #include <openssl/dh.h> @@ -197,7 +196,7 @@ static int ssl_failed(pn_ssl_t *ssl) ERR_error_string_n( ssl_err, buf, sizeof(buf) ); } _log_ssl_error(NULL); // spit out any remaining errors to the log file - ssl->transport->tail_closed = true; + pni_close_tail(ssl->transport); pn_do_error(ssl->transport, "amqp:connection:framing-error", "SSL Failure: %s", buf); return PN_EOS; } http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/92b8098c/proton-c/src/ssl/ssl_stub.c ---------------------------------------------------------------------- diff --git a/proton-c/src/ssl/ssl_stub.c b/proton-c/src/ssl/ssl_stub.c index 435f1e4..300215a 100644 --- a/proton-c/src/ssl/ssl_stub.c +++ b/proton-c/src/ssl/ssl_stub.c @@ -20,6 +20,8 @@ */ #include <proton/ssl.h> +#include <proton/error.h> +#include <proton/transport.h> /** @file http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/92b8098c/proton-c/src/tests/object.c ---------------------------------------------------------------------- diff --git a/proton-c/src/tests/object.c b/proton-c/src/tests/object.c index f6d11cf..ad83006 100644 --- a/proton-c/src/tests/object.c +++ b/proton-c/src/tests/object.c @@ -30,12 +30,12 @@ static char mem; static void *END = &mem; -static pn_list_t *build_list(size_t capacity, int options, ...) +static pn_list_t *build_list(size_t capacity, ...) { - pn_list_t *result = pn_list(capacity, options); + pn_list_t *result = pn_list(PN_OBJECT, capacity); va_list ap; - va_start(ap, options); + va_start(ap, capacity); while (true) { void *arg = va_arg(ap, void *); if (arg == END) { @@ -43,23 +43,21 @@ static pn_list_t *build_list(size_t capacity, int options, ...) } pn_list_add(result, arg); - if (PN_REFCOUNT & options) { - pn_decref(arg); - } + pn_class_decref(PN_OBJECT, arg); } va_end(ap); return result; } -static pn_map_t *build_map(size_t capacity, float load_factor, int options, ...) +static pn_map_t *build_map(size_t capacity, float load_factor, ...) { - pn_map_t *result = pn_map(capacity, load_factor, options); + pn_map_t *result = pn_map(PN_OBJECT, PN_OBJECT, capacity, load_factor); va_list ap; void *prev = NULL; - va_start(ap, options); + va_start(ap, load_factor); int count = 0; while (true) { void *arg = va_arg(ap, void *); @@ -70,10 +68,8 @@ static pn_map_t *build_map(size_t capacity, float load_factor, int options, ...) if (count % 2) { pn_map_put(result, prev, arg); - if (PN_REFCOUNT & options) { - pn_decref(prev); - pn_decref(arg); - } + pn_class_decref(PN_OBJECT, prev); + pn_class_decref(PN_OBJECT, arg); } else { prev = arg; } @@ -93,15 +89,51 @@ static void noop(void *o) {} static uintptr_t zero(void *o) { return 0; } static intptr_t delta(void *a, void *b) { return (uintptr_t) b - (uintptr_t) a; } -static pn_class_t null_class = {0}; +#define CID_noop CID_pn_object +#define noop_initialize noop +#define noop_finalize noop +#define noop_hashcode zero +#define noop_compare delta +#define noop_inspect NULL -static pn_class_t noop_class = {NULL, noop, noop, zero, delta}; +static const pn_class_t noop_class = PN_CLASS(noop); -static void test_new(size_t size, pn_class_t *clazz) +static void test_class(const pn_class_t *clazz, size_t size) { - void *obj = pn_new(size, clazz); + void *a = pn_class_new(clazz, size); + void *b = pn_class_new(clazz, size); + + assert(!pn_class_equals(clazz, a, b)); + assert(pn_class_equals(clazz, a, a)); + assert(pn_class_equals(clazz, b, b)); + assert(!pn_class_equals(clazz, a, NULL)); + assert(!pn_class_equals(clazz, NULL, a)); + + int rca = pn_class_refcount(clazz, a); + int rcb = pn_class_refcount(clazz, b); + + assert(rca == -1 || rca == 1); + assert(rcb == -1 || rcb == 1); + + pn_class_incref(clazz, a); + + rca = pn_class_refcount(clazz, a); + assert(rca == -1 || rca == 2); + + pn_class_decref(clazz, a); + + rca = pn_class_refcount(clazz, a); + assert(rca == -1 || rca == 1); + + pn_class_free(clazz, a); + pn_class_free(clazz, b); +} + +static void test_new(size_t size, const pn_class_t *clazz) +{ + void *obj = pn_class_new(clazz, size); assert(obj); - assert(pn_refcount(obj) == 1); + assert(pn_class_refcount(PN_OBJECT, obj) == 1); assert(pn_class(obj) == clazz); char *bytes = (char *) obj; for (size_t i = 0; i < size; i++) { @@ -117,11 +149,18 @@ static void finalizer(void *object) (**called)++; } +#define CID_finalizer CID_pn_object +#define finalizer_initialize NULL +#define finalizer_finalize finalizer +#define finalizer_hashcode NULL +#define finalizer_compare NULL +#define finalizer_inspect NULL + static void test_finalize(void) { - static pn_class_t clazz = {NULL, NULL, finalizer}; + static pn_class_t clazz = PN_CLASS(finalizer); - int **obj = (int **) pn_new(sizeof(int **), &clazz); + int **obj = (int **) pn_class_new(&clazz, sizeof(int **)); assert(obj); int called = 0; @@ -139,23 +178,37 @@ static void test_free(void) static uintptr_t hashcode(void *obj) { return (uintptr_t) obj; } +#define CID_hashcode CID_pn_object +#define hashcode_initialize NULL +#define hashcode_finalize NULL +#define hashcode_compare NULL +#define hashcode_hashcode hashcode +#define hashcode_inspect NULL + static void test_hashcode(void) { - static pn_class_t clazz = {NULL, NULL, NULL, hashcode}; - void *obj = pn_new(0, &clazz); + static pn_class_t clazz = PN_CLASS(hashcode); + void *obj = pn_class_new(&clazz, 0); assert(obj); assert(pn_hashcode(obj) == (uintptr_t) obj); assert(pn_hashcode(NULL) == 0); pn_free(obj); } +#define CID_compare CID_pn_object +#define compare_initialize NULL +#define compare_finalize NULL +#define compare_compare delta +#define compare_hashcode NULL +#define compare_inspect NULL + static void test_compare(void) { - static pn_class_t clazz = {NULL, NULL, NULL, NULL, delta}; + static pn_class_t clazz = PN_CLASS(compare); - void *a = pn_new(0, &clazz); + void *a = pn_class_new(&clazz, 0); assert(a); - void *b = pn_new(0, &clazz); + void *b = pn_class_new(&clazz, 0); assert(b); assert(pn_compare(a, b)); @@ -181,7 +234,7 @@ static void test_compare(void) static void test_refcounting(int refs) { - void *obj = pn_new(0, NULL); + void *obj = pn_class_new(PN_OBJECT, 0); assert(pn_refcount(obj) == 1); @@ -204,7 +257,7 @@ static void test_refcounting(int refs) static void test_list(size_t capacity) { - pn_list_t *list = pn_list(0, 0); + pn_list_t *list = pn_list(PN_WEAKREF, 0); assert(pn_list_size(list) == 0); assert(!pn_list_add(list, (void *) 0)); assert(!pn_list_add(list, (void *) 1)); @@ -224,12 +277,12 @@ static void test_list(size_t capacity) static void test_list_refcount(size_t capacity) { - void *one = pn_new(0, NULL); - void *two = pn_new(0, NULL); - void *three = pn_new(0, NULL); - void *four = pn_new(0, NULL); + void *one = pn_class_new(PN_OBJECT, 0); + void *two = pn_class_new(PN_OBJECT, 0); + void *three = pn_class_new(PN_OBJECT, 0); + void *four = pn_class_new(PN_OBJECT, 0); - pn_list_t *list = pn_list(0, PN_REFCOUNT); + pn_list_t *list = pn_list(PN_OBJECT, 0); assert(!pn_list_add(list, one)); assert(!pn_list_add(list, two)); assert(!pn_list_add(list, three)); @@ -281,7 +334,7 @@ static void check_list_index(pn_list_t *list, void *value, ssize_t idx) static void test_list_index(void) { - pn_list_t *l = pn_list(0, 0); + pn_list_t *l = pn_list(PN_WEAKREF, 0); void *one = pn_string("one"); void *two = pn_string("two"); void *three = pn_string("three"); @@ -324,7 +377,7 @@ static bool pn_strequals(const char *a, const char *b) static void test_build_list(void) { - pn_list_t *l = build_list(0, PN_REFCOUNT, + pn_list_t *l = build_list(0, pn_string("one"), pn_string("two"), pn_string("three"), @@ -344,7 +397,7 @@ static void test_build_list(void) static void test_build_map(void) { - pn_map_t *m = build_map(0, 0.75, PN_REFCOUNT, + pn_map_t *m = build_map(0, 0.75, pn_string("key"), pn_string("value"), pn_string("key2"), @@ -368,7 +421,7 @@ static void test_build_map(void) static void test_build_map_odd(void) { - pn_map_t *m = build_map(0, 0.75, PN_REFCOUNT, + pn_map_t *m = build_map(0, 0.75, pn_string("key"), pn_string("value"), pn_string("key2"), @@ -395,11 +448,11 @@ static void test_build_map_odd(void) static void test_map(void) { - void *one = pn_new(0, NULL); - void *two = pn_new(0, NULL); - void *three = pn_new(0, NULL); + void *one = pn_class_new(PN_OBJECT, 0); + void *two = pn_class_new(PN_OBJECT, 0); + void *three = pn_class_new(PN_OBJECT, 0); - pn_map_t *map = pn_map(4, 0.75, PN_REFCOUNT); + pn_map_t *map = pn_map(PN_OBJECT, PN_OBJECT, 4, 0.75); assert(pn_map_size(map) == 0); pn_string_t *key = pn_string("key"); @@ -458,11 +511,11 @@ static void test_map(void) static void test_hash(void) { - void *one = pn_new(0, NULL); - void *two = pn_new(0, NULL); - void *three = pn_new(0, NULL); + void *one = pn_class_new(PN_OBJECT, 0); + void *two = pn_class_new(PN_OBJECT, 0); + void *three = pn_class_new(PN_OBJECT, 0); - pn_hash_t *hash = pn_hash(4, 0.75, PN_REFCOUNT); + pn_hash_t *hash = pn_hash(PN_OBJECT, 4, 0.75); pn_hash_put(hash, 0, NULL); pn_hash_put(hash, 1, one); pn_hash_put(hash, 2, two); @@ -512,6 +565,7 @@ static uintptr_t collider_hashcode(void *obj) return 23; } +#define CID_collider CID_pn_object #define collider_initialize NULL #define collider_finalize NULL #define collider_inspect NULL @@ -521,12 +575,12 @@ static void test_map_links(void) const pn_class_t collider_clazz = PN_CLASS(collider); void *keys[3]; for (int i = 0; i < 3; i++) - keys[i] = pn_new(0, &collider_clazz); + keys[i] = pn_class_new(&collider_clazz, 0); // test deleting a head, middle link, tail for (int delete_idx=0; delete_idx < 3; delete_idx++) { - pn_map_t *map = pn_map(0, 0.75, 0); + pn_map_t *map = pn_map(PN_WEAKREF, PN_WEAKREF, 0, 0.75); // create a chain of entries that have same head (from identical key hashcode) for (int i = 0; i < 3; i++) { pn_map_put(map, keys[i], keys[i]); @@ -637,17 +691,17 @@ static void test_string_addf(void) static void test_map_iteration(int n) { - pn_list_t *pairs = pn_list(2*n, PN_REFCOUNT); + pn_list_t *pairs = pn_list(PN_OBJECT, 2*n); for (int i = 0; i < n; i++) { - void *key = pn_new(0, NULL); - void *value = pn_new(0, NULL); + void *key = pn_class_new(PN_OBJECT, 0); + void *value = pn_class_new(PN_OBJECT, 0); pn_list_add(pairs, key); pn_list_add(pairs, value); pn_decref(key); pn_decref(value); } - pn_map_t *map = pn_map(0, 0.75, PN_REFCOUNT); + pn_map_t *map = pn_map(PN_OBJECT, PN_OBJECT, 0, 0.75); assert(pn_map_head(map) == 0); @@ -684,22 +738,22 @@ void test_inspect(void *o, const char *expected) void test_list_inspect(void) { - pn_list_t *l = build_list(0, PN_REFCOUNT, END); + pn_list_t *l = build_list(0, END); test_inspect(l, "[]"); pn_free(l); - l = build_list(0, PN_REFCOUNT, pn_string("one"), END); + l = build_list(0, pn_string("one"), END); test_inspect(l, "[\"one\"]"); pn_free(l); - l = build_list(0, PN_REFCOUNT, + l = build_list(0, pn_string("one"), pn_string("two"), END); test_inspect(l, "[\"one\", \"two\"]"); pn_free(l); - l = build_list(0, PN_REFCOUNT, + l = build_list(0, pn_string("one"), pn_string("two"), pn_string("three"), @@ -713,24 +767,24 @@ void test_map_inspect(void) // note that when there is more than one entry in a map, the order // of the entries is dependent on the hashes involved, it will be // deterministic though - pn_map_t *m = build_map(0, 0.75, PN_REFCOUNT, END); + pn_map_t *m = build_map(0, 0.75, END); test_inspect(m, "{}"); pn_free(m); - m = build_map(0, 0.75, PN_REFCOUNT, + m = build_map(0, 0.75, pn_string("key"), pn_string("value"), END); test_inspect(m, "{\"key\": \"value\"}"); pn_free(m); - m = build_map(0, 0.75, PN_REFCOUNT, + m = build_map(0, 0.75, pn_string("k1"), pn_string("v1"), pn_string("k2"), pn_string("v2"), END); test_inspect(m, "{\"k1\": \"v1\", \"k2\": \"v2\"}"); pn_free(m); - m = build_map(0, 0.75, PN_REFCOUNT, + m = build_map(0, 0.75, pn_string("k1"), pn_string("v1"), pn_string("k2"), pn_string("v2"), pn_string("k3"), pn_string("v3"), @@ -741,14 +795,14 @@ void test_map_inspect(void) void test_list_compare(void) { - pn_list_t *a = pn_list(0, PN_REFCOUNT); - pn_list_t *b = pn_list(0, PN_REFCOUNT); + pn_list_t *a = pn_list(PN_OBJECT, 0); + pn_list_t *b = pn_list(PN_OBJECT, 0); assert(pn_equals(a, b)); - void *one = pn_new(0, NULL); - void *two = pn_new(0, NULL); - void *three = pn_new(0, NULL); + void *one = pn_class_new(PN_OBJECT, 0); + void *two = pn_class_new(PN_OBJECT, 0); + void *three = pn_class_new(PN_OBJECT, 0); pn_list_add(a, one); assert(!pn_equals(a, b)); @@ -785,7 +839,7 @@ static void *pn_it_next(void *state) { void test_iterator(void) { - pn_list_t *list = build_list(0, PN_REFCOUNT, + pn_list_t *list = build_list(0, pn_string("one"), pn_string("two"), pn_string("three"), @@ -811,8 +865,13 @@ void test_iterator(void) int main(int argc, char **argv) { for (size_t i = 0; i < 128; i++) { - test_new(i, NULL); - test_new(i, &null_class); + test_class(PN_OBJECT, i); + test_class(PN_VOID, i); + test_class(&noop_class, i); + } + + for (size_t i = 0; i < 128; i++) { + test_new(i, PN_OBJECT); test_new(i, &noop_class); } http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/92b8098c/proton-c/src/tests/parse-url.c ---------------------------------------------------------------------- diff --git a/proton-c/src/tests/parse-url.c b/proton-c/src/tests/parse-url.c index f57e739..829e9ab 100644 --- a/proton-c/src/tests/parse-url.c +++ b/proton-c/src/tests/parse-url.c @@ -20,7 +20,6 @@ */ #include <stdarg.h> -#include <proton/type_compat.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -29,8 +28,9 @@ #undef NDEBUG #include <assert.h> -#include <proton/error.h> -#include <proton/util.h> +#include "proton/type_compat.h" +#include "proton/error.h" +#include "util.h" static inline bool equalStrP(const char* s1, const char* s2) { http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/92b8098c/proton-c/src/transport/transport.c ---------------------------------------------------------------------- diff --git a/proton-c/src/transport/transport.c b/proton-c/src/transport/transport.c index 1ac2876..b4435ab 100644 --- a/proton-c/src/transport/transport.c +++ b/proton-c/src/transport/transport.c @@ -19,7 +19,7 @@ * */ -#include "../engine/engine-internal.h" +#include "engine/engine-internal.h" #include <stdlib.h> #include <string.h> #include <proton/framing.h> @@ -30,12 +30,10 @@ #include <stdarg.h> #include <stdio.h> -#include "../engine/event.h" - -#include "../sasl/sasl-internal.h" -#include "../ssl/ssl-internal.h" -#include "../platform.h" -#include "../platform_fmt.h" +#include "sasl/sasl-internal.h" +#include "ssl/ssl-internal.h" +#include "platform.h" +#include "platform_fmt.h" static ssize_t transport_consume(pn_transport_t *transport); @@ -43,7 +41,7 @@ static ssize_t transport_consume(pn_transport_t *transport); void pn_delivery_map_init(pn_delivery_map_t *db, pn_sequence_t next) { - db->deliveries = pn_hash(0, 0.75, PN_REFCOUNT); + db->deliveries = pn_hash(PN_OBJECT, 0, 0.75); db->next = next; } @@ -91,6 +89,7 @@ void pn_delivery_map_clear(pn_delivery_map_t *dm) pn_delivery_t *dlv = (pn_delivery_t *) pn_hash_value(hash, entry); pn_delivery_map_del(dm, dlv); } + dm->next = 0; } static ssize_t pn_input_read_amqp_header(pn_io_layer_t *io_layer, const char *bytes, size_t available); @@ -164,9 +163,10 @@ static void pn_transport_initialize(void *object) transport->remote_properties = pn_data(0); transport->disp_data = pn_data(0); pn_condition_init(&transport->remote_condition); + pn_condition_init(&transport->condition); - transport->local_channels = pn_hash(0, 0.75, PN_REFCOUNT); - transport->remote_channels = pn_hash(0, 0.75, PN_REFCOUNT); + transport->local_channels = pn_hash(PN_OBJECT, 0, 0.75); + transport->remote_channels = pn_hash(PN_OBJECT, 0, 0.75); transport->bytes_input = 0; transport->bytes_output = 0; @@ -175,6 +175,9 @@ static void pn_transport_initialize(void *object) transport->output_pending = 0; transport->done_processing = false; + + transport->posted_head_closed = false; + transport->posted_tail_closed = false; } pn_session_t *pn_channel_state(pn_transport_t *transport, uint16_t channel) @@ -189,12 +192,12 @@ static void pni_map_remote_channel(pn_session_t *session, uint16_t channel) session->state.remote_channel = channel; } -void pni_transport_unbind_handles(pn_hash_t *handles); +void pni_transport_unbind_handles(pn_hash_t *handles, bool reset_state); static void pni_unmap_remote_channel(pn_session_t *ssn) { // XXX: should really update link state also - pni_transport_unbind_handles(ssn->state.remote_handles); + pni_transport_unbind_handles(ssn->state.remote_handles, false); pn_transport_t *transport = ssn->connection->transport; uint16_t channel = ssn->state.remote_channel; ssn->state.remote_channel = -2; @@ -211,8 +214,8 @@ static void pn_transport_finalize(void *object); pn_transport_t *pn_transport() { static const pn_class_t clazz = PN_CLASS(pn_transport); - pn_transport_t *transport = (pn_transport_t *) pn_new(sizeof(pn_transport_t), - &clazz); + pn_transport_t *transport = + (pn_transport_t *) pn_class_new(&clazz, sizeof(pn_transport_t)); if (!transport) return NULL; transport->output_buf = (char *) malloc(transport->output_size); @@ -254,6 +257,7 @@ static void pn_transport_finalize(void *object) pn_free(transport->remote_properties); pn_free(transport->disp_data); pn_condition_tini(&transport->remote_condition); + pn_condition_tini(&transport->condition); pn_free(transport->local_channels); pn_free(transport->remote_channels); if (transport->input_buf) free(transport->input_buf); @@ -263,25 +267,36 @@ static void pn_transport_finalize(void *object) int pn_transport_bind(pn_transport_t *transport, pn_connection_t *connection) { - if (!transport) return PN_ARG_ERR; + assert(transport); + assert(connection); + if (transport->connection) return PN_STATE_ERR; if (connection->transport) return PN_STATE_ERR; + transport->connection = connection; connection->transport = transport; - pn_incref2(connection, transport); + + pn_collector_put(connection->collector, PN_OBJECT, connection, PN_CONNECTION_BOUND); + + pn_incref(connection); if (transport->open_rcvd) { PN_SET_REMOTE(connection->endpoint.state, PN_REMOTE_ACTIVE); - pn_collector_put(connection->collector, PN_CONNECTION_REMOTE_OPEN, connection); + pn_collector_put(connection->collector, PN_OBJECT, connection, PN_CONNECTION_REMOTE_OPEN); transport->disp->halt = false; transport_consume(transport); // blech - testBindAfterOpen } + return 0; } -void pni_transport_unbind_handles(pn_hash_t *handles) +void pni_transport_unbind_handles(pn_hash_t *handles, bool reset_state) { for (pn_handle_t h = pn_hash_head(handles); h; h = pn_hash_next(handles, h)) { uintptr_t key = pn_hash_key(handles, h); + if (reset_state) { + pn_link_t *link = (pn_link_t *) pn_hash_value(handles, h); + pn_link_unbound(link); + } pn_hash_del(handles, key); } } @@ -291,8 +306,9 @@ void pni_transport_unbind_channels(pn_hash_t *channels) for (pn_handle_t h = pn_hash_head(channels); h; h = pn_hash_next(channels, h)) { uintptr_t key = pn_hash_key(channels, h); pn_session_t *ssn = (pn_session_t *) pn_hash_value(channels, h); - pni_transport_unbind_handles(ssn->state.local_handles); - pni_transport_unbind_handles(ssn->state.remote_handles); + pni_transport_unbind_handles(ssn->state.local_handles, true); + pni_transport_unbind_handles(ssn->state.remote_handles, true); + pn_session_unbound(ssn); pn_hash_del(channels, key); } } @@ -302,9 +318,12 @@ int pn_transport_unbind(pn_transport_t *transport) assert(transport); if (!transport->connection) return 0; + pn_connection_t *conn = transport->connection; transport->connection = NULL; + pn_collector_put(conn->collector, PN_OBJECT, conn, PN_CONNECTION_UNBOUND); + // XXX: what happens if the endpoints are freed before we get here? pn_session_t *ssn = pn_session_head(conn, 0); while (ssn) { @@ -324,7 +343,7 @@ int pn_transport_unbind(pn_transport_t *transport) pni_transport_unbind_channels(transport->remote_channels); pn_connection_unbound(conn); - pn_decref2(conn, transport); + pn_decref(conn); return 0; } @@ -333,6 +352,12 @@ pn_error_t *pn_transport_error(pn_transport_t *transport) return NULL; } +pn_condition_t *pn_transport_condition(pn_transport_t *transport) +{ + assert(transport); + return &transport->condition; +} + static void pni_map_remote_handle(pn_link_t *link, uint32_t handle) { link->state.remote_handle = handle; @@ -413,6 +438,15 @@ int pn_post_close(pn_transport_t *transport, const char *condition, const char * (bool) condition, ERROR, condition, description, info); } +static pn_collector_t *pni_transport_collector(pn_transport_t *transport) +{ + if (transport->connection && transport->connection->collector) { + return transport->connection->collector; + } else { + return NULL; + } +} + int pn_do_error(pn_transport_t *transport, const char *condition, const char *fmt, ...) { va_list ap; @@ -430,6 +464,10 @@ int pn_do_error(pn_transport_t *transport, const char *condition, const char *fm transport->close_sent = true; } transport->disp->halt = true; + pn_condition_set_name(&transport->condition, condition); + pn_condition_set_description(&transport->condition, buf); + pn_collector_t *collector = pni_transport_collector(transport); + pn_collector_put(collector, PN_OBJECT, transport, PN_TRANSPORT_ERROR); pn_transport_logf(transport, "ERROR %s %s", condition, buf); return PN_ERR; } @@ -479,7 +517,7 @@ int pn_do_open(pn_dispatcher_t *disp) if (conn) { PN_SET_REMOTE(conn->endpoint.state, PN_REMOTE_ACTIVE); - pn_collector_put(conn->collector, PN_CONNECTION_REMOTE_OPEN, conn); + pn_collector_put(conn->collector, PN_OBJECT, conn, PN_CONNECTION_REMOTE_OPEN); } else { transport->disp->halt = true; } @@ -508,7 +546,7 @@ int pn_do_begin(pn_dispatcher_t *disp) ssn->state.incoming_transfer_count = next; pni_map_remote_channel(ssn, disp->channel); PN_SET_REMOTE(ssn->endpoint.state, PN_REMOTE_ACTIVE); - pn_collector_put(transport->connection->collector, PN_SESSION_REMOTE_OPEN, ssn); + pn_collector_put(transport->connection->collector, PN_OBJECT, ssn, PN_SESSION_REMOTE_OPEN); return 0; } @@ -682,7 +720,7 @@ int pn_do_attach(pn_dispatcher_t *disp) link->state.delivery_count = idc; } - pn_collector_put(transport->connection->collector, PN_LINK_REMOTE_OPEN, link); + pn_collector_put(transport->connection->collector, PN_OBJECT, link, PN_LINK_REMOTE_OPEN); return 0; } @@ -763,7 +801,7 @@ int pn_do_transfer(pn_dispatcher_t *disp) pn_post_flow(transport, ssn, link); } - pn_collector_put(transport->connection->collector, PN_DELIVERY, delivery); + pn_collector_put(transport->connection->collector, PN_OBJECT, delivery, PN_DELIVERY); return 0; } @@ -813,7 +851,7 @@ int pn_do_flow(pn_dispatcher_t *disp) } } - pn_collector_put(transport->connection->collector, PN_LINK_FLOW, link); + pn_collector_put(transport->connection->collector, PN_OBJECT, link, PN_LINK_FLOW); } return 0; @@ -908,7 +946,7 @@ int pn_do_disposition(pn_dispatcher_t *disp) delivery->updated = true; pn_work_update(transport->connection, delivery); - pn_collector_put(transport->connection->collector, PN_DELIVERY, delivery); + pn_collector_put(transport->connection->collector, PN_OBJECT, delivery, PN_DELIVERY); } } @@ -938,9 +976,9 @@ int pn_do_detach(pn_dispatcher_t *disp) if (closed) { PN_SET_REMOTE(link->endpoint.state, PN_REMOTE_CLOSED); - pn_collector_put(transport->connection->collector, PN_LINK_REMOTE_CLOSE, link); + pn_collector_put(transport->connection->collector, PN_OBJECT, link, PN_LINK_REMOTE_CLOSE); } else { - // TODO: implement + pn_collector_put(transport->connection->collector, PN_OBJECT, link, PN_LINK_REMOTE_DETACH); } pni_unmap_remote_handle(link); @@ -954,7 +992,7 @@ int pn_do_end(pn_dispatcher_t *disp) int err = pn_scan_error(disp->args, &ssn->endpoint.remote_condition, SCAN_ERROR_DEFAULT); if (err) return err; PN_SET_REMOTE(ssn->endpoint.state, PN_REMOTE_CLOSED); - pn_collector_put(transport->connection->collector, PN_SESSION_REMOTE_CLOSE, ssn); + pn_collector_put(transport->connection->collector, PN_OBJECT, ssn, PN_SESSION_REMOTE_CLOSE); pni_unmap_remote_channel(ssn); return 0; } @@ -967,7 +1005,7 @@ int pn_do_close(pn_dispatcher_t *disp) if (err) return err; transport->close_rcvd = true; PN_SET_REMOTE(conn->endpoint.state, PN_REMOTE_CLOSED); - pn_collector_put(transport->connection->collector, PN_CONNECTION_REMOTE_CLOSE, conn); + pn_collector_put(transport->connection->collector, PN_OBJECT, conn, PN_CONNECTION_REMOTE_CLOSE); return 0; } @@ -997,6 +1035,14 @@ ssize_t pn_transport_input(pn_transport_t *transport, const char *bytes, size_t return original - available; } +static void pni_maybe_post_closed(pn_transport_t *transport) +{ + pn_collector_t *collector = pni_transport_collector(transport); + if (transport->posted_head_closed && transport->posted_tail_closed) { + pn_collector_put(collector, PN_OBJECT, transport, PN_TRANSPORT_CLOSED); + } +} + // process pending input until none remaining or EOS static ssize_t transport_consume(pn_transport_t *transport) { @@ -1018,6 +1064,12 @@ static ssize_t transport_consume(pn_transport_t *transport) if (transport->disp->trace & (PN_TRACE_RAW | PN_TRACE_FRM)) pn_transport_log(transport, " <- EOS"); transport->input_pending = 0; // XXX ??? + if (!transport->posted_tail_closed) { + pn_collector_t *collector = pni_transport_collector(transport); + pn_collector_put(collector, PN_OBJECT, transport, PN_TRANSPORT_TAIL_CLOSED); + transport->posted_tail_closed = true; + pni_maybe_post_closed(transport); + } return n; } } @@ -1445,7 +1497,7 @@ int pn_process_tpwork_sender(pn_transport_t *transport, pn_delivery_t *delivery, link->session->outgoing_deliveries--; } - pn_collector_put(transport->connection->collector, PN_LINK_FLOW, link); + pn_collector_put(transport->connection->collector, PN_OBJECT, link, PN_LINK_FLOW); } } @@ -1571,7 +1623,7 @@ int pn_process_link_teardown(pn_transport_t *transport, pn_endpoint_t *endpoint) pn_session_t *session = link->session; pn_session_state_t *ssn_state = &session->state; pn_link_state_t *state = &link->state; - if (endpoint->state & PN_LOCAL_CLOSED && (int32_t) state->local_handle >= 0 && + if (((endpoint->state & PN_LOCAL_CLOSED) || link->detached) && (int32_t) state->local_handle >= 0 && (int16_t) ssn_state->local_channel >= 0 && !transport->close_sent) { if (pn_link_is_sender(link) && pn_link_queued(link) && (int32_t) state->remote_handle != -2 && @@ -1588,8 +1640,10 @@ int pn_process_link_teardown(pn_transport_t *transport, pn_endpoint_t *endpoint) info = pn_condition_info(&endpoint->condition); } - int err = pn_post_frame(transport->disp, ssn_state->local_channel, "DL[Io?DL[sSC]]", DETACH, - state->local_handle, true, (bool) name, ERROR, name, description, info); + int err = + pn_post_frame(transport->disp, ssn_state->local_channel, + "DL[Io?DL[sSC]]", DETACH, state->local_handle, !link->detached, + (bool)name, ERROR, name, description, info); if (err) return err; pni_unmap_local_handle(link); } @@ -1625,7 +1679,7 @@ bool pn_pointful_buffering(pn_transport_t *transport, pn_session_t *session) static void pni_unmap_local_channel(pn_session_t *ssn) { // XXX: should really update link state also - pni_transport_unbind_handles(ssn->state.local_handles); + pni_transport_unbind_handles(ssn->state.local_handles, false); pn_transport_t *transport = ssn->connection->transport; pn_session_state_t *state = &ssn->state; uintptr_t channel = state->local_channel; @@ -2039,6 +2093,13 @@ ssize_t pn_transport_push(pn_transport_t *transport, const char *src, size_t siz } } +void pni_close_tail(pn_transport_t *transport) +{ + if (!transport->tail_closed) { + transport->tail_closed = true; + } +} + int pn_transport_process(pn_transport_t *transport, size_t size) { assert(transport); @@ -2048,7 +2109,7 @@ int pn_transport_process(pn_transport_t *transport, size_t size) ssize_t n = transport_consume( transport ); if (n == PN_EOS) { - transport->tail_closed = true; + pni_close_tail(transport); } if (n < 0 && n != PN_EOS) return n; @@ -2058,7 +2119,7 @@ int pn_transport_process(pn_transport_t *transport, size_t size) // input stream has closed int pn_transport_close_tail(pn_transport_t *transport) { - transport->tail_closed = true; + pni_close_tail(transport); transport_consume( transport ); return 0; // XXX: what if not all input processed at this point? do we care??? @@ -2110,6 +2171,14 @@ void pn_transport_pop(pn_transport_t *transport, size_t size) memmove( transport->output_buf, &transport->output_buf[size], transport->output_pending ); } + + if (!transport->output_pending && pn_transport_pending(transport) < 0 && + !transport->posted_head_closed) { + pn_collector_t *collector = pni_transport_collector(transport); + pn_collector_put(collector, PN_OBJECT, transport, PN_TRANSPORT_HEAD_CLOSED); + transport->posted_head_closed = true; + pni_maybe_post_closed(transport); + } } } @@ -2143,3 +2212,9 @@ bool pn_transport_closed(pn_transport_t *transport) ssize_t pending = pn_transport_pending(transport); return capacity < 0 && pending < 0; } + +pn_connection_t *pn_transport_connection(pn_transport_t *transport) +{ + assert(transport); + return transport->connection; +} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/92b8098c/proton-c/src/url.c ---------------------------------------------------------------------- diff --git a/proton-c/src/url.c b/proton-c/src/url.c new file mode 100644 index 0000000..12d6f9d --- /dev/null +++ b/proton-c/src/url.c @@ -0,0 +1,168 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include "proton/url.h" +#include "proton/object.h" +#include "util.h" +#include "platform.h" + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +static char* copy(const char* str) { + if (str == NULL) return NULL; + char *str2 = (char*)malloc(strlen(str)+1); + if (str2) strcpy(str2, str); + return str2; +} + +struct pn_url_t { + char *scheme; + char *username; + char *password; + char *host; + char *port; + char *path; + pn_string_t *str; +}; + +/** Internal use only, returns the pn_string_t. Public function is pn_url_str() */ +static pn_string_t *pn_url_string(pn_url_t* url) +{ + pn_url_str(url); /* Make sure str is up to date */ + return url->str; +} + +static void pn_url_finalize(void *object) +{ + pn_url_t *url = (pn_url_t *) object; + pn_url_clear(url); + pn_free(url->str); +} + +static uintptr_t pn_url_hashcode(void *object) +{ + pn_url_t *url = (pn_url_t *) object; + return pn_hashcode(pn_url_string(url)); +} + +static intptr_t pn_url_compare(void *oa, void *ob) +{ + pn_url_t *a = (pn_url_t *) oa; + pn_url_t *b = (pn_url_t *) ob; + return pn_compare(pn_url_string(a), pn_url_string(b)); +} + + +static int pn_url_inspect(void *obj, pn_string_t *dst) +{ + pn_url_t *url = (pn_url_t *) obj; + int err = 0; + err = pn_string_addf(dst, "Url("); if (err) return err; + err = pn_inspect(pn_url_string(url), dst); if (err) return err; + return pn_string_addf(dst, ")"); +} + +#define pn_url_initialize NULL + + +PN_EXTERN pn_url_t *pn_url() { + static const pn_class_t clazz = PN_CLASS(pn_url); + pn_url_t *url = (pn_url_t*) pn_class_new(&clazz, sizeof(pn_url_t)); + if (!url) return NULL; + memset(url, 0, sizeof(*url)); + url->str = pn_string(NULL); + return url; +} + +/** Parse a string URL as a pn_url_t. + *@param[in] url A URL string. + *@return The parsed pn_url_t or NULL if url is not a valid URL string. + */ +PN_EXTERN pn_url_t *pn_url_parse(const char *str) { + if (!str || !*str) /* Empty string or NULL is illegal. */ + return NULL; + + pn_url_t *url = pn_url(); + char *str2 = copy(str); + pni_parse_url(str2, &url->scheme, &url->username, &url->password, &url->host, &url->port, &url->path); + url->scheme = copy(url->scheme); + url->username = copy(url->username); + url->password = copy(url->password); + url->host = (url->host && !*url->host) ? NULL : copy(url->host); + url->port = copy(url->port); + url->path = copy(url->path); + + free(str2); + return url; +} + +/** Free a URL */ +PN_EXTERN void pn_url_free(pn_url_t *url) { pn_free(url); } + +/** Clear the contents of the URL. */ +PN_EXTERN void pn_url_clear(pn_url_t *url) { + pn_url_set_scheme(url, NULL); + pn_url_set_username(url, NULL); + pn_url_set_password(url, NULL); + pn_url_set_host(url, NULL); + pn_url_set_port(url, NULL); + pn_url_set_path(url, NULL); + pn_string_clear(url->str); +} + +static inline int len(const char *str) { return str ? strlen(str) : 0; } + +/** Return the string form of a URL. */ +PN_EXTERN const char *pn_url_str(pn_url_t *url) { + if (pn_string_get(url->str) == NULL) { + pn_string_set(url->str, ""); + if (url->scheme) pn_string_addf(url->str, "%s://", url->scheme); + if (url->username) pn_string_addf(url->str, "%s", url->username); + if (url->password) pn_string_addf(url->str, ":%s", url->password); + if (url->username || url->password) pn_string_addf(url->str, "@"); + if (url->host) { + if (strchr(url->host, ':')) pn_string_addf(url->str, "[%s]", url->host); + else pn_string_addf(url->str, "%s", url->host); + } + if (url->port) pn_string_addf(url->str, ":%s", url->port); + if (url->path) pn_string_addf(url->str, "/%s", url->path); + } + return pn_string_get(url->str); +} + +PN_EXTERN const char *pn_url_get_scheme(pn_url_t *url) { return url->scheme; } +PN_EXTERN const char *pn_url_get_username(pn_url_t *url) { return url->username; } +PN_EXTERN const char *pn_url_get_password(pn_url_t *url) { return url->password; } +PN_EXTERN const char *pn_url_get_host(pn_url_t *url) { return url->host; } +PN_EXTERN const char *pn_url_get_port(pn_url_t *url) { return url->port; } +PN_EXTERN const char *pn_url_get_path(pn_url_t *url) { return url->path; } + +#define SET(part) free(url->part); url->part = copy(part); pn_string_clear(url->str) +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char *scheme) { SET(scheme); } +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char *username) { SET(username); } +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char *password) { SET(password); } +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char *host) { SET(host); } +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char *port) { SET(port); } +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char *path) { SET(path); } + + http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/92b8098c/proton-c/src/util.c ---------------------------------------------------------------------- diff --git a/proton-c/src/util.c b/proton-c/src/util.c index 16e3685..84d594b 100644 --- a/proton-c/src/util.c +++ b/proton-c/src/util.c @@ -27,7 +27,6 @@ #include <ctype.h> #include <string.h> #include <proton/error.h> -#include <proton/util.h> #include <proton/types.h> #include "util.h" @@ -200,17 +199,17 @@ void pni_parse_url(char *url, char **scheme, char **user, char **pass, char **ho if (*pass) pni_urldecode(*pass, *pass); } -void pn_vfatal(const char *fmt, va_list ap) +void pni_vfatal(const char *fmt, va_list ap) { vfprintf(stderr, fmt, ap); abort(); } -void pn_fatal(const char *fmt, ...) +void pni_fatal(const char *fmt, ...) { va_list ap; va_start(ap, fmt); - pn_vfatal(fmt, ap); + pni_vfatal(fmt, ap); va_end(ap); } http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/92b8098c/proton-c/src/util.h ---------------------------------------------------------------------- diff --git a/proton-c/src/util.h b/proton-c/src/util.h index 322f4ef..ad299b9 100644 --- a/proton-c/src/util.h +++ b/proton-c/src/util.h @@ -33,6 +33,9 @@ #include <proton/types.h> #include <proton/object.h> +PN_EXTERN void pni_parse_url(char *url, char **scheme, char **user, char **pass, char **host, char **port, char **path); +void pni_fatal(const char *fmt, ...); +void pni_vfatal(const char *fmt, va_list ap); PN_EXTERN ssize_t pn_quote_data(char *dst, size_t capacity, const char *src, size_t size); int pn_quote(pn_string_t *dst, const char *src, size_t size); PN_EXTERN void pn_fprint_data(FILE *stream, const char *bytes, size_t size); --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
