]> git.saurik.com Git - apple/syslog.git/blobdiff - aslcommon/asl_memory.c
syslog-322.tar.gz
[apple/syslog.git] / aslcommon / asl_memory.c
index 66d8703a2afdd0abcc70b679ae78e947073a4b72..1dcfab1579a2e7819923598cf4300b5c67886d48 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007-2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2007-2010 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,8 +21,6 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 
-#include <asl_core.h>
-#include <asl_memory.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <sys/types.h>
 #include <time.h>
+#include <asl_core.h>
+#include <asl_msg.h>
+#include <asl_msg_list.h>
 #include <asl_private.h>
+#include "asl_memory.h"
 
 #define DEFAULT_MAX_RECORDS 2000
-#define MEM_STRING_HEADER_SIZE 8
+#define DEFAULT_MAX_STRING_MEMORY 4096000
 
 #define forever for(;;)
-extern time_t asl_parse_time(const char *str);
-extern int asl_msg_cmp(asl_msg_t *a, asl_msg_t *b);
 
 uint32_t
-asl_memory_statistics(asl_memory_t *s, aslmsg *msg)
+asl_memory_statistics(asl_memory_t *s, asl_msg_t **msg)
 {
-       aslmsg out;
+       asl_msg_t * out;
        uint32_t i, n;
        uint64_t size;
        char str[256];
@@ -50,7 +50,7 @@ asl_memory_statistics(asl_memory_t *s, aslmsg *msg)
        if (s == NULL) return ASL_STATUS_INVALID_STORE;
        if (msg == NULL) return ASL_STATUS_INVALID_ARG;
 
-       out = (aslmsg)calloc(1, sizeof(asl_msg_t));
+       out = asl_msg_new(ASL_TYPE_MSG);
        if (out == NULL) return ASL_STATUS_NO_MEMORY;
 
        size = sizeof(asl_memory_t);
@@ -58,21 +58,30 @@ asl_memory_statistics(asl_memory_t *s, aslmsg *msg)
 
        for (i = 0; i < s->string_count; i++)
        {
-               size += MEM_STRING_HEADER_SIZE;
-               if (((mem_string_t *)s->string_cache[i])->str != NULL) size += (strlen(((mem_string_t *)s->string_cache[i])->str) + 1);
+               size += sizeof(mem_string_t);
+               if (s->string_cache[i]->str != NULL) size += (strlen(s->string_cache[i]->str) + 1);
        }
 
        snprintf(str, sizeof(str), "%llu", size);
-       asl_set(out, "Size", str);
+       asl_msg_set_key_val(out, "Size", str);
 
        n = 0;
        for (i = 0; i < s->record_count; i++) if (s->record[i]->mid != 0) n++;
 
+       snprintf(str, sizeof(str), "%u", s->record_count);
+       asl_msg_set_key_val(out, "MaxRecords", str);
+
        snprintf(str, sizeof(str), "%u", n);
-       asl_set(out, "RecordCount", str);
+       asl_msg_set_key_val(out, "RecordCount", str);
 
        snprintf(str, sizeof(str), "%u", s->string_count);
-       asl_set(out, "StringCount", str);
+       asl_msg_set_key_val(out, "StringCount", str);
+
+       snprintf(str, sizeof(str), "%lu", s->curr_string_mem);
+       asl_msg_set_key_val(out, "StringMemory", str);
+
+       snprintf(str, sizeof(str), "%lu", s->max_string_mem);
+       asl_msg_set_key_val(out, "MaxStringMemory", str);
 
        *msg = out;
        return ASL_STATUS_OK;
@@ -81,35 +90,45 @@ asl_memory_statistics(asl_memory_t *s, aslmsg *msg)
 uint32_t
 asl_memory_close(asl_memory_t *s)
 {
-       uint32_t i;
-
        if (s == NULL) return ASL_STATUS_OK;
+       
+       dispatch_sync(s->queue, ^{
+               uint32_t i;
 
-       if (s->record != NULL)
-       {
-               for (i = 0; i < s->record_count; i++)
+               if (s->record != NULL)
                {
-                       if (s->record[i] != NULL) free(s->record[i]);
-                       s->record[i] = NULL;
-               }
+                       for (i = 0; i < s->record_count; i++)
+                       {
+                               free(s->record[i]);
+                               s->record[i] = NULL;
+                       }
 
-               free(s->record);
-               s->record = NULL;
-       }
+                       free(s->record);
+                       s->record = NULL;
+               }
 
-       if (s->buffer_record != NULL) free(s->buffer_record);
+               free(s->buffer_record);
+               s->buffer_record = NULL;
 
-       if (s->string_cache != NULL)
-       {
-               for (i = 0; i < s->string_count; i++)
+               if (s->string_cache != NULL)
                {
-                       if (s->string_cache[i] != NULL) free(s->string_cache[i]);
-                       s->string_cache[i] = NULL;
+                       for (i = 0; i < s->string_count; i++)
+                       {
+                               if (s->string_cache[i] != NULL)
+                               {
+                                       free(s->string_cache[i]->str);
+                                       free(s->string_cache[i]);
+                               }
+
+                               s->string_cache[i] = NULL;
+                       }
+
+                       free(s->string_cache);
+                       s->string_cache = NULL;
                }
+       });
 
-               free(s->string_cache);
-               s->string_cache = NULL;
-       }
+       dispatch_release(s->queue);
 
        free(s);
 
@@ -117,7 +136,7 @@ asl_memory_close(asl_memory_t *s)
 }
 
 uint32_t
-asl_memory_open(uint32_t max_records, asl_memory_t **s)
+asl_memory_open(uint32_t max_records, size_t max_str_mem, asl_memory_t **s)
 {
        asl_memory_t *out;
        uint32_t i;
@@ -125,14 +144,25 @@ asl_memory_open(uint32_t max_records, asl_memory_t **s)
        if (s == NULL) return ASL_STATUS_INVALID_ARG;
 
        if (max_records == 0) max_records = DEFAULT_MAX_RECORDS;
+       if (max_str_mem == 0) max_str_mem = DEFAULT_MAX_STRING_MEMORY;
 
        out = calloc(1, sizeof(asl_memory_t));
        if (out == NULL) return ASL_STATUS_NO_MEMORY;
 
+       out->queue = dispatch_queue_create("ASL Memory Queue", NULL);
+       if (out->queue == NULL)
+       {
+               free(out);
+               return ASL_STATUS_NO_MEMORY;
+       }
+
+       out->max_string_mem = max_str_mem;
+
        out->record_count = max_records;
        out->record = (mem_record_t **)calloc(max_records, sizeof(mem_record_t *));
        if (out->record == NULL)
        {
+               dispatch_release(out->queue);
                free(out);
                return ASL_STATUS_NO_MEMORY;
        }
@@ -158,28 +188,67 @@ asl_memory_open(uint32_t max_records, asl_memory_t **s)
        return ASL_STATUS_OK;
 }
 
+static void
+asl_memory_reset(asl_memory_t *s)
+{
+       uint32_t i;
+       if (s == NULL) return;
+
+       /* clear all message records */
+       for (i = 0; i < s->record_count; i++)
+       {
+               memset(s->record[i], 0, sizeof(mem_record_t));
+       }
+
+       /* reset the string cache */
+       if (s->string_cache != NULL)
+       {
+               for (i = 0; i < s->string_count; i++)
+               {
+                       if (s->string_cache[i] != NULL)
+                       {
+                               free(s->string_cache[i]->str);
+                               free(s->string_cache[i]);
+                       }
+                       
+                       s->string_cache[i] = NULL;
+               }
+               
+               free(s->string_cache);
+               s->string_cache = NULL;
+       }
+       
+       s->string_count = 0;
+}
+
 static mem_string_t *
-mem_string_new(const char *str, uint32_t len, uint32_t hash)
+asl_memory_string_new(const char *str, uint32_t len, uint32_t hash)
 {
        mem_string_t *out;
-       size_t ss;
 
        if (str == NULL) return NULL;
 
-       ss = MEM_STRING_HEADER_SIZE + len + 1;
-       out = (mem_string_t *)calloc(1, ss);
+       out = (mem_string_t *)calloc(1, sizeof(mem_string_t));
        if (out == NULL) return NULL;
 
        out->hash = hash;
        out->refcount = 1;
+       out->str = malloc(len + 1);
+       if (out->str == NULL)
+       {
+               free(out);
+               return NULL;
+       }
+       
        memcpy(out->str, str, len);
+       out->str[len] = 0;
 
        return out;
 }
 
 /*
  * Find the first hash greater than or equal to a given hash in the string cache.
- * Return s->string_count if hash is greater that or equal to last hash in the string cache.
+ * Return s->string_count if hash is greater than last hash in the string cache.
  * Caller must check if the hashes match or not.
  *
  * This routine is used both to find strings in the cache and to determine where to insert
@@ -194,25 +263,24 @@ asl_memory_string_cache_search_hash(asl_memory_t *s, uint32_t hash)
        if (s->string_count == 0) return 0;
        if (s->string_count == 1)
        {
-               ms = (mem_string_t *)s->string_cache[0];
+               ms = s->string_cache[0];
                if (hash < ms->hash) return 0;
                return 1;
        }
 
-       top = s->string_count - 1;
+       range = top = s->string_count - 1;
        bot = 0;
        mid = top / 2;
 
-       range = top - bot;
        while (range > 1)
        {
-               ms = (mem_string_t *)s->string_cache[mid];
+               ms = s->string_cache[mid];
 
                if (hash == ms->hash)
                {
                        while (mid > 0)
                        {
-                               ms = (mem_string_t *)s->string_cache[mid - 1];
+                               ms = s->string_cache[mid - 1];
                                if (hash != ms->hash) break;
                                mid--;
                        }
@@ -221,7 +289,7 @@ asl_memory_string_cache_search_hash(asl_memory_t *s, uint32_t hash)
                }
                else
                {
-                       ms = (mem_string_t *)s->string_cache[mid];
+                       ms = s->string_cache[mid];
                        if (hash < ms->hash) top = mid;
                        else bot = mid;
                }
@@ -230,10 +298,10 @@ asl_memory_string_cache_search_hash(asl_memory_t *s, uint32_t hash)
                mid = bot + (range / 2);
        }
 
-       ms = (mem_string_t *)s->string_cache[bot];
+       ms = s->string_cache[bot];
        if (hash <= ms->hash) return bot;
 
-       ms = (mem_string_t *)s->string_cache[top];
+       ms = s->string_cache[top];
        if (hash <= ms->hash) return top;
 
        return s->string_count;
@@ -249,6 +317,7 @@ static mem_string_t *
 asl_memory_string_retain(asl_memory_t *s, const char *str, int create)
 {
        uint32_t i, where, hash, len;
+       mem_string_t *new;
 
        if (s == NULL) return NULL;
        if (str == NULL) return NULL;
@@ -261,11 +330,11 @@ asl_memory_string_retain(asl_memory_t *s, const char *str, int create)
        /* asl_memory_string_cache_search_hash just tells us where to look */
        if (where < s->string_count)
        {
-               while (((mem_string_t *)(s->string_cache[where]))->hash == hash)
+               while (s->string_cache[where]->hash == hash)
                {
-                       if (!strcmp(str, ((mem_string_t *)(s->string_cache[where]))->str))
+                       if (!strcmp(str, s->string_cache[where]->str))
                        {
-                               ((mem_string_t *)(s->string_cache[where]))->refcount++;
+                               s->string_cache[where]->refcount++;
                                return s->string_cache[where];
                        }
 
@@ -277,24 +346,22 @@ asl_memory_string_retain(asl_memory_t *s, const char *str, int create)
        if (create == 0) return NULL;
 
        /* create a new mem_string_t and insert into the cache at index 'where' */
-       if (s->string_count == 0)
-       {
-               s->string_cache = (void **)calloc(1, sizeof(void *));
-       }
-       else
-       {
-               s->string_cache = (void **)reallocf(s->string_cache, (s->string_count + 1) * sizeof(void *));
-               for (i = s->string_count; i > where; i--) s->string_cache[i] = s->string_cache[i - 1];
-       }
-
+       new = asl_memory_string_new(str, len, hash);
+       if (new == NULL) return NULL;
+       
+       s->string_cache = (mem_string_t **)reallocf(s->string_cache, (s->string_count + 1) * sizeof(void *));
        if (s->string_cache == NULL)
        {
                s->string_count = 0;
+               free(new);
                return NULL;
        }
 
+       for (i = s->string_count; i > where; i--) s->string_cache[i] = s->string_cache[i - 1];
+
+       s->curr_string_mem += (sizeof(mem_string_t) + len + 1);
+       s->string_cache[where] = new;
        s->string_count++;
-       s->string_cache[where] = mem_string_new(str, len, hash);
 
        return s->string_cache[where];
 }
@@ -311,11 +378,11 @@ asl_memory_string_release(asl_memory_t *s, mem_string_t *m)
        if (m->refcount > 0) return ASL_STATUS_OK;
 
        where = asl_memory_string_cache_search_hash(s, m->hash);
-       if (((mem_string_t *)(s->string_cache[where]))->hash != m->hash) return ASL_STATUS_OK;
+       if (s->string_cache[where]->hash != m->hash) return ASL_STATUS_OK;
 
        while (s->string_cache[where] != m)
        {
-               if (((mem_string_t *)(s->string_cache[where]))->hash != m->hash) return ASL_STATUS_OK;
+               if (s->string_cache[where]->hash != m->hash) return ASL_STATUS_OK;
 
                where++;
                if (where >= s->string_count) return ASL_STATUS_OK;
@@ -323,7 +390,12 @@ asl_memory_string_release(asl_memory_t *s, mem_string_t *m)
 
        for (i = where + 1; i < s->string_count; i++) s->string_cache[i - 1] = s->string_cache[i];
 
+       if (m->str == NULL) s->curr_string_mem -= sizeof(mem_string_t);
+       else s->curr_string_mem -= (sizeof(mem_string_t) + strlen(m->str) + 1);
+
+       free(m->str);
        free(m);
+
        s->string_count--;
 
        if (s->string_count == 0)
@@ -333,7 +405,7 @@ asl_memory_string_release(asl_memory_t *s, mem_string_t *m)
                return ASL_STATUS_OK;
        }
 
-       s->string_cache = (void **)reallocf(s->string_cache, s->string_count * sizeof(void *));
+       s->string_cache = (mem_string_t **)reallocf(s->string_cache, s->string_count * sizeof(void *));
        if (s->string_cache == NULL)
        {
                s->string_count = 0;
@@ -356,6 +428,7 @@ asl_memory_record_clear(asl_memory_t *s, mem_record_t *r)
 
        asl_memory_string_release(s, r->host);
        asl_memory_string_release(s, r->sender);
+       asl_memory_string_release(s, r->sender_mach_uuid);
        asl_memory_string_release(s, r->facility);
        asl_memory_string_release(s, r->message);
        asl_memory_string_release(s, r->refproc);
@@ -375,18 +448,22 @@ asl_memory_record_free(asl_memory_t *s, mem_record_t *r)
 }
 
 /*
- * Encode an aslmsg as a record structure.
+ * Encode an asl_msg_t as a record structure.
  * Creates and caches strings.
  */
 static uint32_t
-asl_memory_message_encode(asl_memory_t *s, asl_msg_t *msg, mem_record_t *r)
+asl_memory_message_encode(asl_memory_t *s, asl_msg_t *msg)
 {
-       uint32_t i;
+       uint32_t x;
        mem_string_t *k, *v;
+       mem_record_t *r;
+       const char *key, *val;
 
        if (s == NULL) return ASL_STATUS_INVALID_STORE;
+       if (s->buffer_record == NULL) return ASL_STATUS_INVALID_STORE;
        if (msg == NULL) return ASL_STATUS_INVALID_MESSAGE;
-       if (r == NULL) return ASL_STATUS_INVALID_ARG;
+
+       r = s->buffer_record;
 
        memset(r, 0, sizeof(mem_record_t));
 
@@ -400,100 +477,103 @@ asl_memory_message_encode(asl_memory_t *s, asl_msg_t *msg, mem_record_t *r)
        r->time = (uint64_t)-1;
        r->nano = (uint32_t)-1;
 
-       for (i = 0; i < msg->count; i++)
+       key = NULL;
+       val = NULL;
+
+       for (x = asl_msg_fetch((asl_msg_t *)msg, 0, &key, &val, NULL); x != IndexNull; x = asl_msg_fetch((asl_msg_t *)msg, x, &key, &val, NULL))
        {
-               if (msg->key[i] == NULL) continue;
+               if (key == NULL) continue;
 
-               else if (!strcmp(msg->key[i], ASL_KEY_TIME))
+               else if (!strcmp(key, ASL_KEY_TIME))
                {
-                       if (msg->val[i] != NULL) r->time = asl_parse_time(msg->val[i]);
+                       if (val != NULL) r->time = asl_core_parse_time(val, NULL);
                }
-               else if (!strcmp(msg->key[i], ASL_KEY_TIME_NSEC))
+               else if (!strcmp(key, ASL_KEY_TIME_NSEC))
                {
-                       if (msg->val[i] != NULL) r->nano = atoi(msg->val[i]);
+                       if (val != NULL) r->nano = atoi(val);
                }
-               else if (!strcmp(msg->key[i], ASL_KEY_HOST))
+               else if (!strcmp(key, ASL_KEY_HOST))
                {
-                       if (msg->val[i] != NULL) r->host = asl_memory_string_retain(s, msg->val[i], 1);
+                       if (val != NULL) r->host = asl_memory_string_retain(s, val, 1);
                }
-               else if (!strcmp(msg->key[i], ASL_KEY_SENDER))
+               else if (!strcmp(key, ASL_KEY_SENDER))
                {
-                       if (msg->val[i] != NULL) r->sender = asl_memory_string_retain(s, msg->val[i], 1);
+                       if (val != NULL) r->sender = asl_memory_string_retain(s, val, 1);
                }
-               else if (!strcmp(msg->key[i], ASL_KEY_PID))
+               else if (!strcmp(key, ASL_KEY_PID))
                {
-                       if (msg->val[i] != NULL) r->pid = atoi(msg->val[i]);
+                       if (val != NULL) r->pid = atoi(val);
                }
-               else if (!strcmp(msg->key[i], ASL_KEY_REF_PID))
+               else if (!strcmp(key, ASL_KEY_REF_PID))
                {
-                       if (msg->val[i] != NULL) r->refpid = atoi(msg->val[i]);
+                       if (val != NULL) r->refpid = atoi(val);
                }
-               else if (!strcmp(msg->key[i], ASL_KEY_UID))
+               else if (!strcmp(key, ASL_KEY_UID))
                {
-                       if (msg->val[i] != NULL) r->uid = atoi(msg->val[i]);
+                       if (val != NULL) r->uid = atoi(val);
                }
-               else if (!strcmp(msg->key[i], ASL_KEY_GID))
+               else if (!strcmp(key, ASL_KEY_GID))
                {
-                       if (msg->val[i] != NULL) r->gid = atoi(msg->val[i]);
+                       if (val != NULL) r->gid = atoi(val);
                }
-               else if (!strcmp(msg->key[i], ASL_KEY_LEVEL))
+               else if (!strcmp(key, ASL_KEY_LEVEL))
                {
-                       if (msg->val[i] != NULL) r->level = atoi(msg->val[i]);
+                       if (val != NULL) r->level = atoi(val);
                }
-               else if (!strcmp(msg->key[i], ASL_KEY_MSG))
+               else if (!strcmp(key, ASL_KEY_MSG))
                {
-                       if (msg->val[i] != NULL) r->message = asl_memory_string_retain(s, msg->val[i], 1);
+                       if (val != NULL) r->message = asl_memory_string_retain(s, val, 1);
                }
-               else if (!strcmp(msg->key[i], ASL_KEY_FACILITY))
+               else if (!strcmp(key, ASL_KEY_SENDER_MACH_UUID))
                {
-                       if (msg->val[i] != NULL) r->facility = asl_memory_string_retain(s, msg->val[i], 1);
+                       if (val != NULL) r->sender_mach_uuid = asl_memory_string_retain(s, val, 1);
                }
-               else if (!strcmp(msg->key[i], ASL_KEY_REF_PROC))
+               else if (!strcmp(key, ASL_KEY_FACILITY))
                {
-                       if (msg->val[i] != NULL) r->refproc = asl_memory_string_retain(s, msg->val[i], 1);
+                       if (val != NULL) r->facility = asl_memory_string_retain(s, val, 1);
                }
-               else if (!strcmp(msg->key[i], ASL_KEY_SESSION))
+               else if (!strcmp(key, ASL_KEY_REF_PROC))
                {
-                       if (msg->val[i] != NULL) r->session = asl_memory_string_retain(s, msg->val[i], 1);
+                       if (val != NULL) r->refproc = asl_memory_string_retain(s, val, 1);
                }
-               else if (!strcmp(msg->key[i], ASL_KEY_READ_UID))
+               else if (!strcmp(key, ASL_KEY_SESSION))
                {
-                       if (((r->flags & ASL_MSG_FLAG_READ_UID_SET) == 0) && (msg->val[i] != NULL))
+                       if (val != NULL) r->session = asl_memory_string_retain(s, val, 1);
+               }
+               else if (!strcmp(key, ASL_KEY_READ_UID))
+               {
+                       if (((r->flags & ASL_MSG_FLAG_READ_UID_SET) == 0) && (val != NULL))
                        {
-                               r->ruid = atoi(msg->val[i]);
+                               r->ruid = atoi(val);
                                r->flags |= ASL_MSG_FLAG_READ_UID_SET;
                        }
                }
-               else if (!strcmp(msg->key[i], ASL_KEY_READ_GID))
+               else if (!strcmp(key, ASL_KEY_READ_GID))
                {
-                       if (((r->flags & ASL_MSG_FLAG_READ_GID_SET) == 0) && (msg->val[i] != NULL))
+                       if (((r->flags & ASL_MSG_FLAG_READ_GID_SET) == 0) && (val != NULL))
                        {
-                               r->rgid = atoi(msg->val[i]);
+                               r->rgid = atoi(val);
                                r->flags |= ASL_MSG_FLAG_READ_GID_SET;
                        }
                }
-               else if (!strcmp(msg->key[i], ASL_KEY_MSG_ID))
+               else if (!strcmp(key, ASL_KEY_OS_ACTIVITY_ID))
+               {
+                       if (val != NULL) r->os_activity_id = atoll(val);
+               }
+               else if (!strcmp(key, ASL_KEY_MSG_ID))
                {
                        /* Ignore */
                        continue;
                }
                else
                {
-                       k = asl_memory_string_retain(s, msg->key[i], 1);
+                       k = asl_memory_string_retain(s, key, 1);
                        if (k == NULL) continue;
 
                        v = NULL;
-                       if (msg->val[i] != NULL) v = asl_memory_string_retain(s, msg->val[i], 1);
-
-                       if (r->kvcount == 0)
-                       {
-                               r->kvlist = (mem_string_t **)calloc(2, sizeof(mem_string_t *));
-                       }
-                       else
-                       {
-                               r->kvlist = (mem_string_t **)realloc(r->kvlist, (r->kvcount + 2) * sizeof(mem_string_t *));
-                       }
+                       if (val != NULL) v = asl_memory_string_retain(s, val, 1);
 
+                       r->kvlist = (mem_string_t **)reallocf(r->kvlist, (r->kvcount + 2) * sizeof(mem_string_t *));
                        if (r->kvlist == NULL)
                        {
                                asl_memory_record_clear(s, r);
@@ -509,39 +589,60 @@ asl_memory_message_encode(asl_memory_t *s, asl_msg_t *msg, mem_record_t *r)
 }
 
 uint32_t
-asl_memory_save(asl_memory_t *s, aslmsg msg, uint64_t *mid)
+asl_memory_save(asl_memory_t *s, asl_msg_t *msg, uint64_t *mid)
 {
-       uint32_t status;
-       mem_record_t *t;
+       __block uint32_t status;
 
        if (s == NULL) return ASL_STATUS_INVALID_STORE;
        if (s->buffer_record == NULL) return ASL_STATUS_INVALID_STORE;
 
-       /* asl_memory_message_encode creates and caches strings */
-       status = asl_memory_message_encode(s, msg, s->buffer_record);
-       if (status != ASL_STATUS_OK) return status;
-
-       if (*mid != 0)
-       {
-               s->buffer_record->mid = *mid;
-       }
-       else
-       {
-               s->buffer_record->mid = asl_core_new_msg_id(0);
-               *mid = s->buffer_record->mid;
-       }
-
-       /* clear the first record */
-       t = s->record[s->record_first];
-       asl_memory_record_clear(s, t);
-
-       /* add the new record to the record list (swap in the buffer record) */
-       s->record[s->record_first] = s->buffer_record;
-       s->buffer_record = t;
+       dispatch_sync(s->queue, ^{
+               mem_record_t *t;
 
-       /* record list is a circular queue */
-       s->record_first++;
-       if (s->record_first >= s->record_count) s->record_first = 0;
+               /* asl_memory_message_encode creates and caches strings */
+               status = asl_memory_message_encode(s, msg);
+               if (status == ASL_STATUS_OK)
+               {
+                       uint32_t loop_start_index = s->record_first;
+       
+                       if (*mid != 0)
+                       {
+                               s->buffer_record->mid = *mid;
+                       }
+                       else
+                       {
+                               s->buffer_record->mid = asl_core_new_msg_id(0);
+                               *mid = s->buffer_record->mid;
+                       }
+                       
+                       /* clear the first record */
+                       t = s->record[s->record_first];
+                       asl_memory_record_clear(s, t);
+                       
+                       /* add the new record to the record list (swap in the buffer record) */
+                       s->record[s->record_first] = s->buffer_record;
+                       s->buffer_record = t;
+                       
+                       /* record list is a circular queue */
+                       s->record_first++;
+                       if (s->record_first >= s->record_count) s->record_first = 0;
+                       
+                       /* delete records if too much memory is in use */
+                       while (s->curr_string_mem > s->max_string_mem)
+                       {
+                               asl_memory_record_clear(s, s->record[s->record_first]);
+                               s->record_first++;
+                               if (s->record_first >= s->record_count) s->record_first = 0;
+                               if (s->record_first == loop_start_index)
+                               {
+                                       /* The entire ring has been cleared.  This should never happen. */
+                                       asl_memory_reset(s);
+                                       status = ASL_STATUS_FAILED;
+                                       break;
+                               }
+                       }
+               }
+       });
 
        return status;
 }
@@ -552,8 +653,10 @@ asl_memory_save(asl_memory_t *s, aslmsg msg, uint64_t *mid)
 static uint32_t
 asl_memory_message_decode(asl_memory_t *s, mem_record_t *r, asl_msg_t **out)
 {
-       uint32_t i, n;
+       uint32_t i;
        asl_msg_t *msg;
+       char tmp[64];
+       const char *key, *val;
 
        if (s == NULL) return ASL_STATUS_INVALID_STORE;
        if (r == NULL) return ASL_STATUS_INVALID_ARG;
@@ -561,321 +664,133 @@ asl_memory_message_decode(asl_memory_t *s, mem_record_t *r, asl_msg_t **out)
 
        *out = NULL;
 
-       msg = (asl_msg_t *)calloc(1, sizeof(asl_msg_t));
+       msg = asl_msg_new(ASL_TYPE_MSG);
        if (msg == NULL) return ASL_STATUS_NO_MEMORY;
 
-       msg->type = ASL_TYPE_MSG;
-       /* Level and Message ID are always set */
-       msg->count = 2;
-       if (r->time != (uint64_t)-1) msg->count++;
-       if (r->nano != (uint32_t)-1) msg->count++;
-       if (r->host != NULL) msg->count++;
-       if (r->sender != NULL) msg->count++;
-       if (r->facility != NULL) msg->count++;
-       if (r->refproc != NULL) msg->count++;
-       if (r->session != NULL) msg->count++;
-       if (r->pid != -1) msg->count++;
-       if (r->refpid != 0) msg->count++;
-       if (r->uid != -2) msg->count++;
-       if (r->gid != -2) msg->count++;
-       if (r->message != NULL) msg->count++;
-       if (r->flags & ASL_MSG_FLAG_READ_UID_SET) msg->count++;
-       if (r->flags & ASL_MSG_FLAG_READ_GID_SET) msg->count++;
-
-       msg->count += (r->kvcount / 2);
-
-       msg->key = (char **)calloc(msg->count, sizeof(char *));
-       if (msg->key == NULL)
-       {
-               free(msg);
-               return ASL_STATUS_NO_MEMORY;
-       }
-
-       msg->val = (char **)calloc(msg->count, sizeof(char *));
-       if (msg->val == NULL)
-       {
-               free(msg->key);
-               free(msg);
-               return ASL_STATUS_NO_MEMORY;
-       }
-
-       n = 0;
-
        /* Message ID */
-       msg->key[n] = strdup(ASL_KEY_MSG_ID);
-       if (msg->key[n] == NULL)
-       {
-               asl_free(msg);
-               return ASL_STATUS_NO_MEMORY;
-       }
-
-       asprintf(&(msg->val[n]), "%llu", r->mid);
-       if (msg->val[n] == NULL)
-       {
-               asl_free(msg);
-               return ASL_STATUS_NO_MEMORY;
-       }
-       n++;
+       snprintf(tmp, sizeof(tmp), "%llu", r->mid);
+       asl_msg_set_key_val(msg, ASL_KEY_MSG_ID, tmp);
 
        /* Level */
-       msg->key[n] = strdup(ASL_KEY_LEVEL);
-       if (msg->key[n] == NULL)
-       {
-               asl_free(msg);
-               return ASL_STATUS_NO_MEMORY;
-       }
-
-       asprintf(&(msg->val[n]), "%u", r->level);
-       if (msg->val[n] == NULL)
-       {
-               asl_free(msg);
-               return ASL_STATUS_NO_MEMORY;
-       }
-       n++;
+       snprintf(tmp, sizeof(tmp), "%u", r->level);
+       asl_msg_set_key_val(msg, ASL_KEY_LEVEL, tmp);
 
        /* Time */
        if (r->time != (uint64_t)-1)
        {
-               msg->key[n] = strdup(ASL_KEY_TIME);
-               if (msg->key[n] == NULL)
-               {
-                       asl_free(msg);
-                       return ASL_STATUS_NO_MEMORY;
-               }
-
-               asprintf(&(msg->val[n]), "%llu", r->time);
-               if (msg->val[n] == NULL)
-               {
-                       asl_free(msg);
-                       return ASL_STATUS_NO_MEMORY;
-               }
-               n++;
+               snprintf(tmp, sizeof(tmp), "%llu", r->time);
+               asl_msg_set_key_val(msg, ASL_KEY_TIME, tmp);
        }
 
        /* Nanoseconds */
        if (r->nano != (uint32_t)-1)
        {
-               msg->key[n] = strdup(ASL_KEY_TIME_NSEC);
-               if (msg->key[n] == NULL)
-               {
-                       asl_free(msg);
-                       return ASL_STATUS_NO_MEMORY;
-               }
-
-               asprintf(&(msg->val[n]), "%lu", r->nano);
-               if (msg->val[n] == NULL)
-               {
-                       asl_free(msg);
-                       return ASL_STATUS_NO_MEMORY;
-               }
-               n++;
+               snprintf(tmp, sizeof(tmp), "%u", r->nano);
+               asl_msg_set_key_val(msg, ASL_KEY_TIME_NSEC, tmp);
        }
 
        /* Host */
        if (r->host != NULL)
        {
-               msg->key[n] = strdup(ASL_KEY_HOST);
-               if (msg->key[n] == NULL)
-               {
-                       asl_free(msg);
-                       return ASL_STATUS_NO_MEMORY;
-               }
-
-               msg->val[n] = strdup(r->host->str);
-               n++;
+               asl_msg_set_key_val(msg, ASL_KEY_HOST, r->host->str);
        }
 
        /* Sender */
        if (r->sender != NULL)
        {
-               msg->key[n] = strdup(ASL_KEY_SENDER);
-               if (msg->key[n] == NULL)
-               {
-                       asl_free(msg);
-                       return ASL_STATUS_NO_MEMORY;
-               }
+               asl_msg_set_key_val(msg, ASL_KEY_SENDER, r->sender->str);
+       }
 
-               msg->val[n] = strdup(r->sender->str);
-               n++;
+       /* Sender mach UUID */
+       if (r->sender_mach_uuid != NULL)
+       {
+               asl_msg_set_key_val(msg, ASL_KEY_SENDER_MACH_UUID, r->sender_mach_uuid->str);
        }
 
        /* Facility */
        if (r->facility != NULL)
        {
-               msg->key[n] = strdup(ASL_KEY_FACILITY);
-               if (msg->key[n] == NULL)
-               {
-                       asl_free(msg);
-                       return ASL_STATUS_NO_MEMORY;
-               }
-
-               msg->val[n] = strdup(r->facility->str);
-               n++;
+               asl_msg_set_key_val(msg, ASL_KEY_FACILITY, r->facility->str);
        }
 
        /* Ref Proc */
        if (r->refproc != NULL)
        {
-               msg->key[n] = strdup(ASL_KEY_REF_PROC);
-               if (msg->key[n] == NULL)
-               {
-                       asl_free(msg);
-                       return ASL_STATUS_NO_MEMORY;
-               }
-
-               msg->val[n] = strdup(r->refproc->str);
-               n++;
+               asl_msg_set_key_val(msg, ASL_KEY_REF_PROC, r->refproc->str);
        }
 
        /* Session */
        if (r->session != NULL)
        {
-               msg->key[n] = strdup(ASL_KEY_SESSION);
-               if (msg->key[n] == NULL)
-               {
-                       asl_free(msg);
-                       return ASL_STATUS_NO_MEMORY;
-               }
-
-               msg->val[n] = strdup(r->session->str);
-               n++;
+               asl_msg_set_key_val(msg, ASL_KEY_SESSION, r->session->str);
        }
 
        /* PID */
        if (r->pid != -1)
        {
-               msg->key[n] = strdup(ASL_KEY_PID);
-               if (msg->key[n] == NULL)
-               {
-                       asl_free(msg);
-                       return ASL_STATUS_NO_MEMORY;
-               }
-
-               asprintf(&(msg->val[n]), "%d", r->pid);
-               if (msg->val[n] == NULL)
-               {
-                       asl_free(msg);
-                       return ASL_STATUS_NO_MEMORY;
-               }
-               n++;
+               snprintf(tmp, sizeof(tmp), "%d", r->pid);
+               asl_msg_set_key_val(msg, ASL_KEY_PID, tmp);
        }
 
        /* REF PID */
        if (r->refpid != 0)
        {
-               msg->key[n] = strdup(ASL_KEY_REF_PID);
-               if (msg->key[n] == NULL)
-               {
-                       asl_free(msg);
-                       return ASL_STATUS_NO_MEMORY;
-               }
-
-               asprintf(&(msg->val[n]), "%d", r->refpid);
-               if (msg->val[n] == NULL)
-               {
-                       asl_free(msg);
-                       return ASL_STATUS_NO_MEMORY;
-               }
-               n++;
+               snprintf(tmp, sizeof(tmp), "%d", r->refpid);
+               asl_msg_set_key_val(msg, ASL_KEY_REF_PID, tmp);
        }
 
        /* UID */
        if (r->uid != -2)
        {
-               msg->key[n] = strdup(ASL_KEY_UID);
-               if (msg->key[n] == NULL)
-               {
-                       asl_free(msg);
-                       return ASL_STATUS_NO_MEMORY;
-               }
-
-               asprintf(&(msg->val[n]), "%d", r->uid);
-               if (msg->val[n] == NULL)
-               {
-                       asl_free(msg);
-                       return ASL_STATUS_NO_MEMORY;
-               }
-               n++;
+               snprintf(tmp, sizeof(tmp), "%d", r->uid);
+               asl_msg_set_key_val(msg, ASL_KEY_UID, tmp);
        }
 
        /* GID */
        if (r->gid != -2)
        {
-               msg->key[n] = strdup(ASL_KEY_GID);
-               if (msg->key[n] == NULL)
-               {
-                       asl_free(msg);
-                       return ASL_STATUS_NO_MEMORY;
-               }
-
-               asprintf(&(msg->val[n]), "%d", r->gid);
-               if (msg->val[n] == NULL)
-               {
-                       asl_free(msg);
-                       return ASL_STATUS_NO_MEMORY;
-               }
-               n++;
+               snprintf(tmp, sizeof(tmp), "%d", r->gid);
+               asl_msg_set_key_val(msg, ASL_KEY_GID, tmp);
        }
 
        /* Message */
        if (r->message != NULL)
        {
-               msg->key[n] = strdup(ASL_KEY_MSG);
-               if (msg->key[n] == NULL)
-               {
-                       asl_free(msg);
-                       return ASL_STATUS_NO_MEMORY;
-               }
-
-               msg->val[n] = strdup(r->message->str);
-               n++;
+               asl_msg_set_key_val(msg, ASL_KEY_MSG, r->message->str);
        }
 
        /* ReadUID */
        if (r->flags & ASL_MSG_FLAG_READ_UID_SET)
        {
-               msg->key[n] = strdup(ASL_KEY_READ_UID);
-               if (msg->key[n] == NULL)
-               {
-                       asl_free(msg);
-                       return ASL_STATUS_NO_MEMORY;
-               }
-
-               asprintf(&(msg->val[n]), "%d", r->ruid);
-               if (msg->val[n] == NULL)
-               {
-                       asl_free(msg);
-                       return ASL_STATUS_NO_MEMORY;
-               }
-               n++;
+               snprintf(tmp, sizeof(tmp), "%d", r->ruid);
+               asl_msg_set_key_val(msg, ASL_KEY_READ_UID, tmp);
        }
 
        /* ReadGID */
        if (r->flags & ASL_MSG_FLAG_READ_GID_SET)
        {
-               msg->key[n] = strdup(ASL_KEY_READ_GID);
-               if (msg->key[n] == NULL)
-               {
-                       asl_free(msg);
-                       return ASL_STATUS_NO_MEMORY;
-               }
+               snprintf(tmp, sizeof(tmp), "%d", r->rgid);
+               asl_msg_set_key_val(msg, ASL_KEY_READ_GID, tmp);
+       }
 
-               asprintf(&(msg->val[n]), "%d", r->rgid);
-               if (msg->val[n] == NULL)
-               {
-                       asl_free(msg);
-                       return ASL_STATUS_NO_MEMORY;
-               }
-               n++;
+       /* OSActivityID */
+       if (r->os_activity_id != 0)
+       {
+               snprintf(tmp, sizeof(tmp), "%llu", r->os_activity_id);
+               asl_msg_set_key_val(msg, ASL_KEY_OS_ACTIVITY_ID, tmp);
        }
 
        /* Key - Value List */
        for (i = 0; i < r->kvcount; i++)
        {
-               if ((r->kvlist[i] != NULL) && (r->kvlist[i]->str != NULL)) msg->key[n] = strdup(r->kvlist[i]->str);
+               key = NULL;
+               val = NULL;
+
+               if (r->kvlist[i] != NULL) key = r->kvlist[i]->str;
                i++;
-               if ((r->kvlist[i] != NULL) && (r->kvlist[i]->str != NULL)) msg->val[n] = strdup(r->kvlist[i]->str);
-               n++;
+               if (r->kvlist[i] != NULL) val = r->kvlist[i]->str;
+
+               if (key != NULL) asl_msg_set_key_val(msg, key, val);
        }
 
        *out = msg;
@@ -883,34 +798,44 @@ asl_memory_message_decode(asl_memory_t *s, mem_record_t *r, asl_msg_t **out)
 }
 
 uint32_t
-asl_memory_fetch(asl_memory_t *s, uint64_t mid, aslmsg *msg, int32_t ruid, int32_t rgid)
+asl_memory_fetch(asl_memory_t *s, uint64_t mid, asl_msg_t **msg, int32_t ruid, int32_t rgid)
 {
-       uint32_t i, status;
+       __block uint32_t status;
 
        if (s == NULL) return ASL_STATUS_INVALID_STORE;
        if (msg == NULL) return ASL_STATUS_INVALID_ARG;
 
-       for (i = 0; i < s->record_count; i++)
-       {
-               if (s->record[i]->mid == 0) break;
+       status = ASL_STATUS_INVALID_ID;
+
+       dispatch_sync(s->queue, ^{
+               uint32_t i;
 
-               if (s->record[i]->mid == mid)
+               for (i = 0; i < s->record_count; i++)
                {
-                       status = asl_core_check_access(s->record[i]->ruid, s->record[i]->rgid, ruid, rgid, s->record[i]->flags);
-                       if (status != ASL_STATUS_OK) return status;
-                       return asl_memory_message_decode(s, s->record[i], msg);
+                       if (s->record[i]->mid == 0) break;
+
+                       if (s->record[i]->mid == mid)
+                       {
+                               status = asl_core_check_access(s->record[i]->ruid, s->record[i]->rgid, ruid, rgid, s->record[i]->flags);
+                               if (status != ASL_STATUS_OK) break;
+
+                               status = asl_memory_message_decode(s, s->record[i], msg);
+                               break;
+                       }
                }
-       }
+       });
 
-       return ASL_STATUS_INVALID_ID;
+       return status;
 }
 
 static mem_record_t *
 asl_memory_query_to_record(asl_memory_t *s, asl_msg_t *q, uint32_t *type)
 {
        mem_record_t *out;
-       uint32_t i, j;
-       mem_string_t *key, *val;
+       uint32_t i, x;
+       uint16_t op;
+       mem_string_t *mkey, *mval;
+       const char *key, *val;
 
        if (type == NULL) return NULL;
 
@@ -923,14 +848,15 @@ asl_memory_query_to_record(asl_memory_t *s, asl_msg_t *q, uint32_t *type)
        /* NULL query matches anything */
        *type = ASL_QUERY_MATCH_TRUE;
        if (q == NULL) return NULL;
-       if (q->count == 0) return NULL;
+       if (asl_msg_count((asl_msg_t *)q) == 0) return NULL;
 
 
        /* we can only do fast match on equality tests */
        *type = ASL_QUERY_MATCH_SLOW;
-       if (q->op != NULL)
+
+       for (x = asl_msg_fetch((asl_msg_t *)q, 0, NULL, NULL, &op); x != IndexNull; x = asl_msg_fetch((asl_msg_t *)q, x, NULL, NULL, &op))
        {
-               for (i = 0; i < q->count; i++) if (q->op[i] != ASL_QUERY_OP_EQUAL) return NULL;
+               if (op != ASL_QUERY_OP_EQUAL) return NULL;
        }
 
        out = (mem_record_t *)calloc(1, sizeof(mem_record_t));
@@ -940,13 +866,13 @@ asl_memory_query_to_record(asl_memory_t *s, asl_msg_t *q, uint32_t *type)
                return NULL;
        }
 
-       for (i = 0; i < q->count; i++)
+       for (x = asl_msg_fetch((asl_msg_t *)q, 0, &key, &val, &op); x != IndexNull; x = asl_msg_fetch((asl_msg_t *)q, x, &key, &val, &op))
        {
-               if (q->key[i] == NULL) continue;
+               if (key == NULL) continue;
 
-               else if (!strcmp(q->key[i], ASL_KEY_MSG_ID))
+               else if (!strcmp(key, ASL_KEY_MSG_ID))
                {
-                       if (q->val[i] == NULL) continue;
+                       if (val == NULL) continue;
 
                        if (*type & ASL_QUERY_MATCH_MSG_ID)
                        {
@@ -956,11 +882,11 @@ asl_memory_query_to_record(asl_memory_t *s, asl_msg_t *q, uint32_t *type)
                        }
 
                        *type |= ASL_QUERY_MATCH_MSG_ID;
-                       out->mid = atoll(q->val[i]);
+                       out->mid = atoll(val);
                }
-               else if (!strcmp(q->key[i], ASL_KEY_TIME))
+               else if (!strcmp(key, ASL_KEY_TIME))
                {
-                       if (q->val[i] == NULL) continue;
+                       if (val == NULL) continue;
 
                        if (*type & ASL_QUERY_MATCH_TIME)
                        {
@@ -970,11 +896,11 @@ asl_memory_query_to_record(asl_memory_t *s, asl_msg_t *q, uint32_t *type)
                        }
 
                        *type |= ASL_QUERY_MATCH_TIME;
-                       out->time = asl_parse_time(q->val[i]);
+                       out->time = asl_core_parse_time(val, NULL);
                }
-               else if (!strcmp(q->key[i], ASL_KEY_TIME_NSEC))
+               else if (!strcmp(key, ASL_KEY_TIME_NSEC))
                {
-                       if (q->val[i] == NULL) continue;
+                       if (val == NULL) continue;
 
                        if (*type & ASL_QUERY_MATCH_NANO)
                        {
@@ -984,11 +910,11 @@ asl_memory_query_to_record(asl_memory_t *s, asl_msg_t *q, uint32_t *type)
                        }
 
                        *type |= ASL_QUERY_MATCH_NANO;
-                       out->nano = atoll(q->val[i]);
+                       out->nano = atoll(val);
                }
-               else if (!strcmp(q->key[i], ASL_KEY_LEVEL))
+               else if (!strcmp(key, ASL_KEY_LEVEL))
                {
-                       if (q->val[i] == NULL) continue;
+                       if (val == NULL) continue;
 
                        if (*type & ASL_QUERY_MATCH_LEVEL)
                        {
@@ -998,11 +924,11 @@ asl_memory_query_to_record(asl_memory_t *s, asl_msg_t *q, uint32_t *type)
                        }
 
                        *type |= ASL_QUERY_MATCH_LEVEL;
-                       out->level = atoi(q->val[i]);
+                       out->level = atoi(val);
                }
-               else if (!strcmp(q->key[i], ASL_KEY_PID))
+               else if (!strcmp(key, ASL_KEY_PID))
                {
-                       if (q->val[i] == NULL) continue;
+                       if (val == NULL) continue;
 
                        if (*type & ASL_QUERY_MATCH_PID)
                        {
@@ -1012,11 +938,11 @@ asl_memory_query_to_record(asl_memory_t *s, asl_msg_t *q, uint32_t *type)
                        }
 
                        *type |= ASL_QUERY_MATCH_PID;
-                       out->pid = atoi(q->val[i]);
+                       out->pid = atoi(val);
                }
-               else if (!strcmp(q->key[i], ASL_KEY_UID))
+               else if (!strcmp(key, ASL_KEY_UID))
                {
-                       if (q->val[i] == NULL) continue;
+                       if (val == NULL) continue;
 
                        if (*type & ASL_QUERY_MATCH_UID)
                        {
@@ -1026,11 +952,11 @@ asl_memory_query_to_record(asl_memory_t *s, asl_msg_t *q, uint32_t *type)
                        }
 
                        *type |= ASL_QUERY_MATCH_UID;
-                       out->uid = atoi(q->val[i]);
+                       out->uid = atoi(val);
                }
-               else if (!strcmp(q->key[i], ASL_KEY_GID))
+               else if (!strcmp(key, ASL_KEY_GID))
                {
-                       if (q->val[i] == NULL) continue;
+                       if (val == NULL) continue;
 
                        if (*type & ASL_QUERY_MATCH_GID)
                        {
@@ -1040,11 +966,11 @@ asl_memory_query_to_record(asl_memory_t *s, asl_msg_t *q, uint32_t *type)
                        }
 
                        *type |= ASL_QUERY_MATCH_GID;
-                       out->gid = atoi(q->val[i]);
+                       out->gid = atoi(val);
                }
-               else if (!strcmp(q->key[i], ASL_KEY_READ_UID))
+               else if (!strcmp(key, ASL_KEY_READ_UID))
                {
-                       if (q->val[i] == NULL) continue;
+                       if (val == NULL) continue;
 
                        if (*type & ASL_QUERY_MATCH_RUID)
                        {
@@ -1054,11 +980,11 @@ asl_memory_query_to_record(asl_memory_t *s, asl_msg_t *q, uint32_t *type)
                        }
 
                        *type |= ASL_QUERY_MATCH_RUID;
-                       out->ruid = atoi(q->val[i]);
+                       out->ruid = atoi(val);
                }
-               else if (!strcmp(q->key[i], ASL_KEY_READ_GID))
+               else if (!strcmp(key, ASL_KEY_READ_GID))
                {
-                       if (q->val[i] == NULL) continue;
+                       if (val == NULL) continue;
 
                        if (*type & ASL_QUERY_MATCH_RGID)
                        {
@@ -1068,11 +994,11 @@ asl_memory_query_to_record(asl_memory_t *s, asl_msg_t *q, uint32_t *type)
                        }
 
                        *type |= ASL_QUERY_MATCH_RGID;
-                       out->rgid = atoi(q->val[i]);
+                       out->rgid = atoi(val);
                }
-               else if (!strcmp(q->key[i], ASL_KEY_REF_PID))
+               else if (!strcmp(key, ASL_KEY_REF_PID))
                {
-                       if (q->val[i] == NULL) continue;
+                       if (val == NULL) continue;
 
                        if (*type & ASL_QUERY_MATCH_REF_PID)
                        {
@@ -1082,11 +1008,11 @@ asl_memory_query_to_record(asl_memory_t *s, asl_msg_t *q, uint32_t *type)
                        }
 
                        *type |= ASL_QUERY_MATCH_REF_PID;
-                       out->refpid = atoi(q->val[i]);
+                       out->refpid = atoi(val);
                }
-               else if (!strcmp(q->key[i], ASL_KEY_HOST))
+               else if (!strcmp(key, ASL_KEY_HOST))
                {
-                       if (q->val[i] == NULL) continue;
+                       if (val == NULL) continue;
 
                        if (*type & ASL_QUERY_MATCH_HOST)
                        {
@@ -1096,7 +1022,7 @@ asl_memory_query_to_record(asl_memory_t *s, asl_msg_t *q, uint32_t *type)
                        }
 
                        *type |= ASL_QUERY_MATCH_HOST;
-                       out->host = asl_memory_string_retain(s, q->val[i], 0);
+                       out->host = asl_memory_string_retain(s, val, 0);
                        if (out->host == NULL)
                        {
                                asl_memory_record_free(s, out);
@@ -1104,9 +1030,9 @@ asl_memory_query_to_record(asl_memory_t *s, asl_msg_t *q, uint32_t *type)
                                return NULL;
                        }
                }
-               else if (!strcmp(q->key[i], ASL_KEY_SENDER))
+               else if (!strcmp(key, ASL_KEY_SENDER))
                {
-                       if (q->val[i] == NULL) continue;
+                       if (val == NULL) continue;
 
                        if (*type & ASL_QUERY_MATCH_SENDER)
                        {
@@ -1116,7 +1042,7 @@ asl_memory_query_to_record(asl_memory_t *s, asl_msg_t *q, uint32_t *type)
                        }
 
                        *type |= ASL_QUERY_MATCH_SENDER;
-                       out->sender = asl_memory_string_retain(s, q->val[i], 0);
+                       out->sender = asl_memory_string_retain(s, val, 0);
                        if (out->sender == NULL)
                        {
                                asl_memory_record_free(s, out);
@@ -1124,9 +1050,29 @@ asl_memory_query_to_record(asl_memory_t *s, asl_msg_t *q, uint32_t *type)
                                return NULL;
                        }
                }
-               else if (!strcmp(q->key[i], ASL_KEY_FACILITY))
+               else if (!strcmp(key, ASL_KEY_SENDER_MACH_UUID))
+               {
+                       if (val == NULL) continue;
+
+                       if (*type & ASL_QUERY_MATCH_SMUUID)
+                       {
+                               asl_memory_record_free(s, out);
+                               *type = ASL_QUERY_MATCH_SLOW;
+                               return NULL;
+                       }
+
+                       *type |= ASL_QUERY_MATCH_SMUUID;
+                       out->sender = asl_memory_string_retain(s, val, 0);
+                       if (out->sender_mach_uuid == NULL)
+                       {
+                               asl_memory_record_free(s, out);
+                               *type = ASL_QUERY_MATCH_FALSE;
+                               return NULL;
+                       }
+               }
+               else if (!strcmp(key, ASL_KEY_FACILITY))
                {
-                       if (q->val[i] == NULL) continue;
+                       if (val == NULL) continue;
 
                        if (*type & ASL_QUERY_MATCH_FACILITY)
                        {
@@ -1136,7 +1082,7 @@ asl_memory_query_to_record(asl_memory_t *s, asl_msg_t *q, uint32_t *type)
                        }
 
                        *type |= ASL_QUERY_MATCH_FACILITY;
-                       out->facility = asl_memory_string_retain(s, q->val[i], 0);
+                       out->facility = asl_memory_string_retain(s, val, 0);
                        if (out->facility == NULL)
                        {
                                asl_memory_record_free(s, out);
@@ -1144,9 +1090,9 @@ asl_memory_query_to_record(asl_memory_t *s, asl_msg_t *q, uint32_t *type)
                                return NULL;
                        }
                }
-               else if (!strcmp(q->key[i], ASL_KEY_MSG))
+               else if (!strcmp(key, ASL_KEY_MSG))
                {
-                       if (q->val[i] == NULL) continue;
+                       if (val == NULL) continue;
 
                        if (*type & ASL_QUERY_MATCH_MESSAGE)
                        {
@@ -1156,7 +1102,7 @@ asl_memory_query_to_record(asl_memory_t *s, asl_msg_t *q, uint32_t *type)
                        }
 
                        *type |= ASL_QUERY_MATCH_MESSAGE;
-                       out->message = asl_memory_string_retain(s, q->val[i], 0);
+                       out->message = asl_memory_string_retain(s, val, 0);
                        if (out->message == NULL)
                        {
                                asl_memory_record_free(s, out);
@@ -1164,9 +1110,9 @@ asl_memory_query_to_record(asl_memory_t *s, asl_msg_t *q, uint32_t *type)
                                return NULL;
                        }
                }
-               else if (!strcmp(q->key[i], ASL_KEY_REF_PROC))
+               else if (!strcmp(key, ASL_KEY_REF_PROC))
                {
-                       if (q->val[i] == NULL) continue;
+                       if (val == NULL) continue;
 
                        if (*type & ASL_QUERY_MATCH_REF_PROC)
                        {
@@ -1176,7 +1122,7 @@ asl_memory_query_to_record(asl_memory_t *s, asl_msg_t *q, uint32_t *type)
                        }
 
                        *type |= ASL_QUERY_MATCH_REF_PROC;
-                       out->refproc = asl_memory_string_retain(s, q->val[i], 0);
+                       out->refproc = asl_memory_string_retain(s, val, 0);
                        if (out->refproc == NULL)
                        {
                                asl_memory_record_free(s, out);
@@ -1184,9 +1130,9 @@ asl_memory_query_to_record(asl_memory_t *s, asl_msg_t *q, uint32_t *type)
                                return NULL;
                        }
                }
-               else if (!strcmp(q->key[i], ASL_KEY_SESSION))
+               else if (!strcmp(key, ASL_KEY_SESSION))
                {
-                       if (q->val[i] == NULL) continue;
+                       if (val == NULL) continue;
 
                        if (*type & ASL_QUERY_MATCH_SESSION)
                        {
@@ -1196,7 +1142,7 @@ asl_memory_query_to_record(asl_memory_t *s, asl_msg_t *q, uint32_t *type)
                        }
 
                        *type |= ASL_QUERY_MATCH_SESSION;
-                       out->session = asl_memory_string_retain(s, q->val[i], 0);
+                       out->session = asl_memory_string_retain(s, val, 0);
                        if (out->session == NULL)
                        {
                                asl_memory_record_free(s, out);
@@ -1206,17 +1152,17 @@ asl_memory_query_to_record(asl_memory_t *s, asl_msg_t *q, uint32_t *type)
                }
                else
                {
-                       key = asl_memory_string_retain(s, q->key[i], 0);
-                       if (key == NULL)
+                       mkey = asl_memory_string_retain(s, key, 0);
+                       if (mkey == NULL)
                        {
                                asl_memory_record_free(s, out);
                                *type = ASL_QUERY_MATCH_FALSE;
                                return NULL;
                        }
 
-                       for (j = 0; j < out->kvcount; j += 2)
+                       for (i = 0; i < out->kvcount; i += 2)
                        {
-                               if (out->kvlist[j] == key)
+                               if (out->kvlist[i] == mkey)
                                {
                                        asl_memory_record_free(s, out);
                                        *type = ASL_QUERY_MATCH_SLOW;
@@ -1224,7 +1170,7 @@ asl_memory_query_to_record(asl_memory_t *s, asl_msg_t *q, uint32_t *type)
                                }
                        }
 
-                       val = asl_memory_string_retain(s, q->val[i], 0);
+                       mval = asl_memory_string_retain(s, val, 0);
 
                        if (out->kvcount == 0)
                        {
@@ -1232,7 +1178,7 @@ asl_memory_query_to_record(asl_memory_t *s, asl_msg_t *q, uint32_t *type)
                        }
                        else
                        {
-                               out->kvlist = (mem_string_t **)realloc(out->kvlist, (out->kvcount + 2) * sizeof(mem_string_t *));
+                               out->kvlist = (mem_string_t **)reallocf(out->kvlist, (out->kvcount + 2) * sizeof(mem_string_t *));
                        }
 
                        if (out->kvlist == NULL)
@@ -1242,8 +1188,8 @@ asl_memory_query_to_record(asl_memory_t *s, asl_msg_t *q, uint32_t *type)
                                return NULL;
                        }
 
-                       out->kvlist[out->kvcount++] = key;
-                       out->kvlist[out->kvcount++] = val;
+                       out->kvlist[out->kvcount++] = mkey;
+                       out->kvlist[out->kvcount++] = mval;
                }
        }
 
@@ -1271,6 +1217,7 @@ asl_memory_fast_match(asl_memory_t *s, mem_record_t *r, uint32_t qtype, mem_reco
        if ((qtype & ASL_QUERY_MATCH_REF_PID) && (q->refpid != r->refpid)) return 0;
        if ((qtype & ASL_QUERY_MATCH_HOST) && (q->host != r->host)) return 0;
        if ((qtype & ASL_QUERY_MATCH_SENDER) && (q->sender != r->sender)) return 0;
+       if ((qtype & ASL_QUERY_MATCH_SMUUID) && (q->sender_mach_uuid != r->sender_mach_uuid)) return 0;
        if ((qtype & ASL_QUERY_MATCH_FACILITY) && (q->facility != r->facility)) return 0;
        if ((qtype & ASL_QUERY_MATCH_MESSAGE) && (q->message != r->message)) return 0;
        if ((qtype & ASL_QUERY_MATCH_REF_PROC) && (q->refproc != r->refproc)) return 0;
@@ -1294,7 +1241,7 @@ asl_memory_fast_match(asl_memory_t *s, mem_record_t *r, uint32_t qtype, mem_reco
 }
 
 static uint32_t
-asl_memory_slow_match(asl_memory_t *s, mem_record_t *r, mem_record_t *q, asl_msg_t *rawq)
+asl_memory_slow_match(asl_memory_t *s, mem_record_t *r, asl_msg_t *rawq)
 {
        asl_msg_t *rawm;
        uint32_t status;
@@ -1304,36 +1251,35 @@ asl_memory_slow_match(asl_memory_t *s, mem_record_t *r, mem_record_t *q, asl_msg
        if (status != ASL_STATUS_OK) return 0;
 
        status = 0;
-       if (asl_msg_cmp(rawq, rawm) != 0) status = 1;
-       asl_free(rawm);
+       if (asl_msg_cmp((asl_msg_t *)rawq, (asl_msg_t *)rawm) != 0) status = 1;
+       asl_msg_release(rawm);
        return status;
 }
 
-uint32_t
-asl_memory_match(asl_memory_t *s, aslresponse query, aslresponse *res, uint64_t *last_id, uint64_t start_id, uint32_t count, int32_t direction, int32_t ruid, int32_t rgid)
+static uint32_t
+asl_memory_match_restricted_uuid_internal(asl_memory_t *s, asl_msg_list_t *query, asl_msg_list_t **res, uint64_t *last_id, uint64_t start_id, uint32_t count, uint32_t duration, int32_t direction, int32_t ruid, int32_t rgid, const char *uuid_str)
 {
        uint32_t status, i, where, start, j, do_match, did_match, rescount, *qtype;
        mem_record_t **qp;
        asl_msg_t *m;
+       size_t qcount;
+       struct timeval now, finish;
 
-       if (s == NULL) return ASL_STATUS_INVALID_STORE;
-       if (res == NULL) return ASL_STATUS_INVALID_ARG;
-
-       do_match = 1;
        qp = NULL;
        qtype = NULL;
        rescount = 0;
+       qcount = asl_msg_list_count(query);
 
-       if ((query == NULL) || ((query != NULL) && (query->count == 0)))
+       if (qcount == 0)
        {
                do_match = 0;
        }
        else
        {
-               qp = (mem_record_t **)calloc(query->count, sizeof(mem_record_t *));
+               qp = (mem_record_t **)calloc(qcount, sizeof(mem_record_t *));
                if (qp == NULL) return ASL_STATUS_NO_MEMORY;
 
-               qtype = (uint32_t *)calloc(query->count, sizeof(uint32_t));
+               qtype = (uint32_t *)calloc(qcount, sizeof(uint32_t));
                if (qtype == NULL)
                {
                        free(qp);
@@ -1341,9 +1287,9 @@ asl_memory_match(asl_memory_t *s, aslresponse query, aslresponse *res, uint64_t
                }
 
                do_match = 0;
-               for (i = 0; i < query->count; i++)
+               for (i = 0; i < qcount; i++)
                {
-                       qp[i] = asl_memory_query_to_record(s, query->msg[i], &(qtype[i]));
+                       qp[i] = asl_memory_query_to_record(s, asl_msg_list_get_index(query, i), &(qtype[i]));
                        if (qtype[i] == ASL_QUERY_MATCH_ERROR)
                        {
                                for (j = 0; j < i; j++) asl_memory_record_free(s, qp[j]);
@@ -1376,7 +1322,7 @@ asl_memory_match(asl_memory_t *s, aslresponse query, aslresponse *res, uint64_t
        {
                if (qp != NULL)
                {
-                       for (i = 0; i < query->count; i++) asl_memory_record_free(s, qp[i]);
+                       for (i = 0; i < qcount; i++) asl_memory_record_free(s, qp[i]);
                        free(qp);
                        free(qtype);
                }
@@ -1384,6 +1330,27 @@ asl_memory_match(asl_memory_t *s, aslresponse query, aslresponse *res, uint64_t
                return ASL_STATUS_OK;
        }
 
+       /* start the timer if a duration was specified */
+       memset(&finish, 0, sizeof(struct timeval));
+       if (duration != 0)
+       {
+               if (gettimeofday(&finish, NULL) == 0)
+               {
+                       finish.tv_sec += (duration / USEC_PER_SEC);
+                       finish.tv_usec += (duration % USEC_PER_SEC);
+                       if (finish.tv_usec > USEC_PER_SEC)
+                       {
+                               finish.tv_usec -= USEC_PER_SEC;
+                               finish.tv_sec += 1;
+                       }
+               }
+               else
+               {
+                       /* shouldn't happen, but if gettimeofday failed we just run without a timeout */
+                       memset(&finish, 0, sizeof(struct timeval));
+               }
+       }
+
        start = where;
 
        /* 
@@ -1393,6 +1360,13 @@ asl_memory_match(asl_memory_t *s, aslresponse query, aslresponse *res, uint64_t
        {
                status = ASL_STATUS_INVALID_ID;
                if (s->record[where]->mid != 0) status = asl_core_check_access(s->record[where]->ruid, s->record[where]->rgid, ruid, rgid, s->record[where]->flags);
+
+               if ((status == ASL_STATUS_OK) && (uuid_str != NULL))
+               {
+                       if (s->record[where]->sender_mach_uuid == NULL) status = ASL_STATUS_INVALID_ID;
+                       else if (strcmp(s->record[where]->sender_mach_uuid->str, uuid_str) != 0) status = ASL_STATUS_INVALID_ID;
+               }
+
                if (status != ASL_STATUS_OK)
                {
                        if (direction >= 0)
@@ -1418,15 +1392,19 @@ asl_memory_match(asl_memory_t *s, aslresponse query, aslresponse *res, uint64_t
                {
                        did_match = 0;
 
-                       for (j = 0; (j < query->count) && (did_match == 0); j++)
+                       for (j = 0; (j < qcount) && (did_match == 0); j++)
                        {
                                if (qtype[j] == ASL_QUERY_MATCH_TRUE)
                                {
                                        did_match = 1;
                                }
+                               else if (qtype[j] == ASL_QUERY_MATCH_FALSE)
+                               {
+                                       did_match = 0;
+                               }
                                else if (qtype[j] == ASL_QUERY_MATCH_SLOW)
                                {
-                                       did_match = asl_memory_slow_match(s, s->record[where], qp[j], query->msg[j]);
+                                       did_match = asl_memory_slow_match(s, s->record[where], asl_msg_list_get_index(query, j));
                                }
                                else
                                {
@@ -1442,6 +1420,12 @@ asl_memory_match(asl_memory_t *s, aslresponse query, aslresponse *res, uint64_t
                        if ((count != 0) && (rescount >= count)) break;
                }
 
+               /* check the timer */
+               if ((finish.tv_sec != 0) && (gettimeofday(&now, NULL) == 0))
+               {
+                       if ((now.tv_sec > finish.tv_sec) || ((now.tv_sec == finish.tv_sec) && (now.tv_usec > finish.tv_usec))) break;
+               }
+
                if (direction >= 0)
                {
                        where++;
@@ -1456,9 +1440,9 @@ asl_memory_match(asl_memory_t *s, aslresponse query, aslresponse *res, uint64_t
                if (where == s->record_first) break;
        }
 
-       if (query != NULL)
+       if (qp != NULL)
        {
-               for (i = 0; i < query->count; i++) asl_memory_record_free(s, qp[i]);
+               for (i = 0; i < qcount; i++) asl_memory_record_free(s, qp[i]);
                free(qp);
                free(qtype);
        }
@@ -1466,22 +1450,14 @@ asl_memory_match(asl_memory_t *s, aslresponse query, aslresponse *res, uint64_t
        *res = NULL;
        if (rescount == 0) return ASL_STATUS_OK;
 
-       *res = (asl_msg_list_t *)calloc(1, sizeof(asl_msg_list_t));
+       *res = asl_msg_list_new();
        if (*res == NULL) return ASL_STATUS_NO_MEMORY;
 
-       (*res)->count = rescount;
-
-       (*res)->msg = (asl_msg_t **)calloc(rescount, sizeof(asl_msg_t *));
-       if ((*res)->msg == NULL)
-       {
-               free(*res);
-               *res = NULL;
-               return ASL_STATUS_NO_MEMORY;
-       }
-
        where = start;
        forever
        {
+               int n = 0;
+
                if (s->record[where]->flags & ASL_MSG_FLAG_SEARCH_MATCH)
                {
                        s->record[where]->flags &= ASL_MSG_FLAG_SEARCH_CLEAR;
@@ -1489,13 +1465,15 @@ asl_memory_match(asl_memory_t *s, aslresponse query, aslresponse *res, uint64_t
                        status = asl_memory_message_decode(s, s->record[where], &m);
                        if (status != ASL_STATUS_OK)
                        {
-                               aslresponse_free(*res);
+                               asl_msg_list_release(*res);
                                *res = NULL;
                                return status;
                        }
 
-                       (*res)->msg[(*res)->curr++] = m;
-                       if ((*res)->curr == rescount) break;
+                       asl_msg_list_append(*res, m);
+                       asl_msg_release(m);
+                       n++;
+                       if (n == rescount) break;
                }
 
                if (direction >= 0)
@@ -1512,6 +1490,35 @@ asl_memory_match(asl_memory_t *s, aslresponse query, aslresponse *res, uint64_t
                if (where == s->record_first) break;
        }
 
-       (*res)->curr = 0;
        return ASL_STATUS_OK;
 }
+
+uint32_t
+asl_memory_match_restricted_uuid(asl_memory_t *s, asl_msg_list_t *query, asl_msg_list_t **res, uint64_t *last_id, uint64_t start_id, uint32_t count, uint32_t duration, int32_t direction, int32_t ruid, int32_t rgid, const char *uuid_str)
+{
+       __block uint32_t status;
+       if (s == NULL) return ASL_STATUS_INVALID_STORE;
+       if (res == NULL) return ASL_STATUS_INVALID_ARG;
+       
+       dispatch_sync(s->queue, ^{
+               status = asl_memory_match_restricted_uuid_internal(s, query, res, last_id, start_id, count, duration, direction, ruid, rgid, uuid_str);
+       });
+       
+       return status;
+}
+
+uint32_t
+asl_memory_match(asl_memory_t *s, asl_msg_list_t *query, asl_msg_list_t **res, uint64_t *last_id, uint64_t start_id, uint32_t count, int32_t direction, int32_t ruid, int32_t rgid)
+{
+       __block uint32_t status;
+       if (s == NULL) return ASL_STATUS_INVALID_STORE;
+       if (res == NULL) return ASL_STATUS_INVALID_ARG;
+       
+       dispatch_sync(s->queue, ^{
+               status = asl_memory_match_restricted_uuid_internal(s, query, res, last_id, start_id, count, 0, direction, ruid, rgid, NULL);
+       });
+
+       return status;
+}