Index: trunk/ippTools/src/pxtools.h
===================================================================
--- trunk/ippTools/src/pxtools.h	(revision 23487)
+++ trunk/ippTools/src/pxtools.h	(revision 23868)
@@ -478,3 +478,85 @@
 }
 
+
+/// Add a primary item to the mirror database
+///
+/// ITEM: Item to add (if it is of the correct type)
+/// NAME: Name for table, to match item name
+/// ROWTYPE: Type of the row (type returned by PARSEFUNC)
+/// PARSEFUNC: Function to parse ITEM and return a ROWTYPE
+/// IDENTIFIERS: Vector (of type U64) to store identifiers
+/// IDNAME: Element of the row with U64 identifier
+/// INSERTFUNC: Function to insert a row into the database
+/// DATABASE: Database handle
+/// CLEANUP: Operation(s) to perform to cleanup in case of an error
+#define PXMIRROR_PRIMARY(ITEM, NAME, ROWTYPE, PARSEFUNC, IDENTIFIERS, IDNAME, INSERTFUNC, DATABASE, CLEANUP) \
+    if (strcmp((ITEM)->name, NAME) == 0) { \
+        if ((ITEM)->type != PS_DATA_METADATA) { \
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Entry %s is not of type METADATA", (ITEM)->name); \
+            CLEANUP; \
+            return false; \
+        } \
+        ROWTYPE *row = PARSEFUNC((ITEM)->data.md); /* Row to insert */ \
+        if (!row) { \
+            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to generate %s row from metadata", (ITEM)->name); \
+            CLEANUP; \
+            return false; \
+        } \
+        if (!INSERTFUNC(DATABASE, row)) { \
+            psError(PS_ERR_UNKNOWN, false, "Unable to add %s %" PRIu64, (ITEM)->name, row->IDNAME); \
+            psFree(row); \
+            CLEANUP; \
+            return false; \
+        } \
+        psVectorAppend((IDENTIFIERS), row->IDNAME); \
+        psFree(row); \
+    }
+
+/// Add a dependent item to the mirror database
+///
+/// ITEM: Item to add (if it is of the correct type)
+/// NAME: Name for table, to match item name
+/// ROWTYPE: Type of the row (type returned by PARSEFUNC)
+/// PARSEFUNC: Function to parse ITEM and return a ROWTYPE
+/// IDENTIFIERS: Vector (of type U64) to check identifiers
+/// IDNAME: Element of the row with U64 identifier
+/// INSERTFUNC: Function to insert a row into the database
+/// DATABASE: Database handle
+/// CLEANUP: Operation(s) to perform to cleanup in case of an error
+#define PXMIRROR_OTHER(ITEM, NAME, ROWTYPE, PARSEFUNC, IDENTIFIERS, IDNAME, INSERTFUNC, DATABASE, CLEANUP) \
+    if (strcmp((ITEM)->name, NAME) == 0) { \
+        if ((ITEM)->type != PS_DATA_METADATA) { \
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Entry %s is not of type METADATA", (ITEM)->name); \
+            CLEANUP; \
+            return false; \
+        } \
+        ROWTYPE *row = PARSEFUNC(item->data.md); /* Row to insert */ \
+        if (!row) { \
+            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to generate %s row from metadata", (ITEM)->name); \
+            CLEANUP; \
+            return false; \
+        } \
+        bool found = false;         /* Found the identifier? */ \
+        for (int i = 0; i < (IDENTIFIERS)->n && !found; i++) { \
+            if (row->IDNAME == (IDENTIFIERS)->data.U64[i]) { \
+                found = true; \
+                break; \
+            } \
+        } \
+        if (!found) { \
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Identifier not found for %s %" PRIu64, \
+                    (ITEM)->name, row->IDNAME); \
+            psFree(row); \
+            CLEANUP; \
+            return false; \
+        } \
+        if (!INSERTFUNC(DATABASE, row)) { \
+            psError(PS_ERR_UNKNOWN, false, "Unable to add %s %" PRIu64, (ITEM)->name, row->IDNAME); \
+            psFree(row); \
+            CLEANUP; \
+            return false; \
+        } \
+        psFree(row); \
+    }
+
 #endif // PXTOOLS_H
