Index: /branches/eam_branch_20080430/psLib/src/types/psMetadata.c
===================================================================
--- /branches/eam_branch_20080430/psLib/src/types/psMetadata.c	(revision 17493)
+++ /branches/eam_branch_20080430/psLib/src/types/psMetadata.c	(revision 17494)
@@ -12,6 +12,6 @@
  *  @author Ross Harman, MHPCC
  *
- *  @version $Revision: 1.168 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2008-03-05 00:57:00 $
+ *  @version $Revision: 1.168.6.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-04-30 21:04:22 $
  *
  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -495,15 +495,50 @@
     bool result = true;
 
+    // we loop over the metadata container by item, not by name.  this pushes us directly into
+    // the elements of the MULTI items; we miss the containers.  We need to check the
+    // (possible) MULTI containers to see how to set the flags.  If we encounter a MULTI which
+    // is requesting REPLACE, then the first item on the input list from that MULTI should be
+    // added with the REPLACE flag turned on; the rest should have the REPLACE flag turned off.
+    // save a list of the MULTI entries which has REPLACE turned off?
+
+    psArray *multiItems = psArrayAlloc (128);
+
     psMetadataIterator *iter = psMetadataIteratorAlloc(in, PS_LIST_HEAD, NULL);
     psMetadataItem *inItem = NULL;
     while ((inItem = psMetadataGetAndIncrement(iter))) {
+
+	// it is not possible to have RESET && UPDATE
+	// is it possible to have !RESET && !UPDATE?
+	// are these mutually exclusive conditions?
+	// input MULTI & RESET  : replace an existing MULTI or ITEM of same name
+	// input MULTI & UPDATE : supplement an existing MULTI or ITEM of same name
+	// in both cases the name must exist in 'out' 
+
         // Need to look for MULTI, which won't be picked up using the iterator.
         psMetadataItem *multiCheckItem = psMetadataLookup(in, inItem->name);
-        unsigned int flag = PS_META_REPLACE | PS_META_REQUIRE_ENTRY | PS_META_REQUIRE_TYPE; // Flag to indicate MULTI; otherwise, replace
-        if (multiCheckItem->type == PS_DATA_METADATA_MULTI) {
-            psTrace("psLib.types", 10, "MULTI: %s (%s)\n", inItem->name, inItem->comment);
-            flag = PS_META_DUPLICATE_OK | PS_META_REQUIRE_ENTRY | PS_META_REQUIRE_TYPE;
+
+	// default operation for the new metadata item (replace existing entry, require existence & type)
+        unsigned int flag = PS_META_REPLACE | PS_META_REQUIRE_ENTRY | PS_META_REQUIRE_TYPE; 
+
+	// for MULTI items, the mode is carried on the multi container
+        if (PS_METADATA_ITEM_GET_TYPE(multiCheckItem) == PS_DATA_METADATA_MULTI) {
+	    psTrace("psLib.types", 10, "MULTI: %s (%s)\n", inItem->name, inItem->comment);
+	    if (multiCheckItem->type & PS_META_UPDATE_FOLDER) {
+		psTrace("psLib.types", 10, "supplement MULTI with new entries\n");
+		flag = PS_META_DUPLICATE_OK | PS_META_REQUIRE_ENTRY | PS_META_REQUIRE_TYPE;
+	    } else {
+		multiCheckItem->type |= PS_META_UPDATE_FOLDER;
+		// save this multi so we can reset their flags below
+		psArrayAdd (multiItems, 128, multiCheckItem); 
+	    }
         }
         psTrace("psLib.types", 5, "Copying %s (%s)...\n", inItem->name, inItem->comment);
+
+	// for METADATA folders, do something different?
+        if (PS_METADATA_ITEM_GET_TYPE(inItem) == PS_DATA_METADATA) {
+	    if (inItem->type & PS_META_UPDATE_FOLDER) {
+		flag = PS_META_UPDATE_FOLDER | PS_META_REQUIRE_ENTRY | PS_META_REQUIRE_TYPE;
+	    }
+	}
 
         // Copy the item and add it on.  report all errors so we get a listing
@@ -517,7 +552,15 @@
     psFree(iter);
 
+    // remove the UPDATE_FOLDER flag from the following MULTI items
+    for (int i = 0; i < multiItems->n; i++) {
+	psMetadataItem *item = multiItems->data[i];
+	item->type &= ~PS_META_UPDATE_FOLDER;
+    }
+    psFree (multiItems);
+
     if (!result) {
         psError(PS_ERR_UNKNOWN, false, "failed to update metadata\n");
     }
+
     return result;
 }
Index: /branches/eam_branch_20080430/psLib/src/types/psMetadata.h
===================================================================
--- /branches/eam_branch_20080430/psLib/src/types/psMetadata.h	(revision 17493)
+++ /branches/eam_branch_20080430/psLib/src/types/psMetadata.h	(revision 17494)
@@ -9,6 +9,6 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.103 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2007-08-09 01:40:08 $
+*  @version $Revision: 1.103.12.1 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2008-04-30 21:04:22 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -57,11 +57,12 @@
  */
 typedef enum {
-    PS_META_DEFAULT = 0,               ///< default behaviour (duplicate entry is an error)
-    PS_META_REPLACE = 0x1000000,       ///< allow entry to be replaced
-    PS_META_NO_REPLACE = 0x2000000,    ///< duplicate entry is silently skipped
-    PS_META_DUPLICATE_OK = 0x4000000,  ///< allow duplicate entries
-    PS_META_NULL = 0x8000000,           ///< psMetadataItem.data is a NULL value
-    PS_META_REQUIRE_ENTRY = 0x10000000,	///< require pre-existing entry with same name
-    PS_META_REQUIRE_TYPE = 0x20000000	///< require pre-existing entry to have same type
+    PS_META_DEFAULT       = 0,		///< default behaviour (duplicate entry is an error)
+    PS_META_REPLACE       = 0x01000000,	///< allow entry to be replaced
+    PS_META_NO_REPLACE    = 0x02000000,	///< duplicate entry is silently skipped
+    PS_META_DUPLICATE_OK  = 0x04000000,	///< allow duplicate entries
+    PS_META_UPDATE_FOLDER = 0x08000000,	///< for a metadata folder, merge contents with existing md
+    PS_META_NULL          = 0x10000000,	///< psMetadataItem.data is a NULL value
+    PS_META_REQUIRE_ENTRY = 0x20000000,	///< require pre-existing entry with same name
+    PS_META_REQUIRE_TYPE  = 0x40000000	///< require pre-existing entry to have same type
 } psMetadataFlags;
 
@@ -69,4 +70,5 @@
 #define PS_METADATA_TYPE_MASK 0x00FFFFFF
 
+#define PS_METADATA_ITEM_TYPE(ITEM) (MD->type & PS_METADATA_TYPE_MASK)
 
 /** Metadata data structure.
Index: /branches/eam_branch_20080430/psLib/src/types/psMetadataConfig.c
===================================================================
--- /branches/eam_branch_20080430/psLib/src/types/psMetadataConfig.c	(revision 17493)
+++ /branches/eam_branch_20080430/psLib/src/types/psMetadataConfig.c	(revision 17494)
@@ -11,6 +11,6 @@
 *  @author Joshua Hoblitt, University of Hawaii 2006-2007
 *
-*  @version $Revision: 1.142 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2007-11-08 04:24:01 $
+*  @version $Revision: 1.142.8.1 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2008-04-30 21:04:22 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -802,6 +802,54 @@
     }
 
-    // If type is not MULTI or META then get the value and comment
-    if((mdType != PS_DATA_METADATA_MULTI) && (mdType != PS_DATA_METADATA)) {
+    // If type is MULTI or META then check for the (optional) directives UPDATE or RESET;
+    // otherwise, get the value and comment.
+    if((mdType == PS_DATA_METADATA_MULTI) || (mdType == PS_DATA_METADATA)) {
+        // Get the metadata item value if there is one.
+        status = 0;
+        strValue = getToken (&linePtr, "#", &status, true);
+
+        if (status) {
+            psError(PS_ERR_IO, true, _("Failed to examine line for optional directive."));
+            psFree(strType);
+            psFree(strValue);
+            return false;
+        }
+
+        if (strValue) {
+	    // found a directive, what does it say?
+	    if (strcasecmp (strValue, "UPDATE") && strcasecmp (strValue, "UPDATE")) {
+		psError(PS_ERR_IO, true, _("Invalid directive %s for METADATA or MULTI.", strValue));
+		psFree(strType);
+		psFree(strValue);
+		return false;
+	    }
+
+	    // found a directive, what does it say?
+	    if (!strcasecmp (strValue, "UPDATE")) {
+		// this folder or group is merged with an existing one of the same name
+		flags |= PS_META_UPDATE_FOLDER;
+	    }
+	    if (!strcasecmp (strValue, "RESET")) {
+		// this folder or group replaces an existing one of the same name
+		flags |= PS_META_REPLACE;
+	    }
+        }
+	psFree(strValue);
+	strValue = NULL;
+
+        // Not all lines will have comments, so NULL is ok.
+        status = 0;
+
+        // XXX this is a very ugly way of finding from the current position to
+        // the end of the line
+        strComment = getToken(&linePtr, "", &status, true);
+
+        if (status) {
+            psError(PS_ERR_IO, true, _("Error reading a metadata comment"));
+            psFree(strType);
+            psFree(strComment);
+            return false;
+        }
+    } else {
         // Get the metadata item value if there is one.
         status = 0;
@@ -833,5 +881,5 @@
             return false;
         }
-    }
+    } 
 
 #define PARSE_ADD_CASE(NAME, TYPE, PARSEFUNC) \
