You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@etch.apache.org by jd...@apache.org on 2009/04/22 19:25:51 UTC

svn commit: r767594 [8/43] - in /incubator/etch/trunk/binding-c/runtime/c: ./ ext/ ext/hashtab/ ext/lib/ inc/ lib/ project/ project/$etchstop/ project/bin/ project/etch/ project/logcli/ project/logsrv/ project/notes/ project/test/ project/test/logcli/ ...

Added: incubator/etch/trunk/binding-c/runtime/c/project/notes/array.txt
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/project/notes/array.txt?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/project/notes/array.txt (added)
+++ incubator/etch/trunk/binding-c/runtime/c/project/notes/array.txt Wed Apr 22 17:25:43 2009
@@ -0,0 +1,173 @@
+
+- - - - - - - - - - - - - - - - - -
+arrayvalue - nativearray discussion
+- - - - - - - - - - - - - - - - - -
+
+1. when reading arrays off the wire (tagdata input) the binding creates arrayvalue objects.
+
+2. question whether we can substitute our nativearray across the board.
+   a. probably best not, since code up the line that is now mostly ported,
+      would instead have to be rewritten for nativearray.
+      
+3. should we however plan to always use 1-dim nativearray as the base of our arrayvalue, 
+   since if we need to be able to access elements, we can't simply reflect to an array as
+   does java, we need the subscripting and primitive object instantiation facilities of the 
+   nativearray.
+   
+   a. however the arrayvalue is an arraylist under the covers. perhaps we should let the
+      arrayvalue have either or both backing store types, arraylist or nativearray.
+   b. that could create inconsistencies of access, in that accessing nativearray always
+      returns a disposable, and accessing arrayvalue always returns a non-disposable.
+   c. however we could well want to not store an object for every array element, a large
+      byte array case in point. 
+   d. let's store only as arraylist for now, leaving the option open to store as
+      nativearray if we need it. 
+   e. another possibility is to "lazy-load" the arraylist from the natarray. 
+      in this way, we always return a non-disposable from arrayvalue.get().
+      when item[i] is requested, we look in the arraylist, lazy-allocating it if
+      needed. if arraylist[i] is null, we populate it from natarray[i]. in either
+      case we return the non-disposable arraylist[i].
+   
+4. our arrayvalue has *both* an arraylist *and* a nativearray member.
+   the natarray member currently is saved there when an arrayvalue was created *from* a nativearray.
+   the natarray can be owned by the arrayvalue or not.
+   a. arrayvalue has from() and to() nativearray methods
+   b. arrayvalue_to_nativearray is limited to three dimensions of course.  
+   
+5. java code freely references the native array or the array value and expects both to be available.
+   ArrayValue has getArray() which returns ArrayValue.array, the native array. TaggedData has
+   Object fromArrayValue(ArrayValue) which returns the native array representation of the ArrayValue.
+   So we really need to keep the 1-dim nativearray in the c arrayvalue. let's do it the lazy load way
+   descibed above. the arrayvalue then handles the multi-dimensional aspect. 
+   
+   
+- - - - - - - - - - - - - - - - - -
+serialization notes 1
+- - - - - - - - - - - - - - - - - -  
+let's walk through writing some arrays.
+first, a 2-dimensional array.
+int x[2][3] = { {1,2,3}, {4,5,6} };
+
+0. we start with a nativearray, and call writeValue(ARRAY, nativearray);
+
+1. writeValue always puts the supplied byte typecode to the buffer first.
+   so in this case, that is ARRAY. (1)
+   
+2. next, switch(typecode) to ARRAY. 
+   a. convert the nativearray to an arrayvalue, passing ownership of na to av: 
+        etch_arrayvalue* av = new_arrayvalue_from
+           (nativearray, typecode, customtype, size(?), 0, TRUE); 
+   b. call writeArray(av, vtor);  
+   
+3. writeArray calls startArray(arrayvalue);  
+   a. put the arrayvalue's content type byte. (2)
+   b. if content type is custom, put array's custom struct type. (3)
+   c. put intval arrayvalue's dimensions (4)
+   d. put intval arrayvalue's itemcount  (5)
+   
+4. writeArray calls writeValues(arrayvalue); 
+   a. elementVtor ev = av.eltvtor;
+   b. foreach entry val in ev
+      writeValue(ev, val);  
+
+5. writeValue writes each value in the arrayvalue.
+   this will be recursive for multidim arrays.
+   a. in our case, the first arravalue has dim 2 and has 2 entries, 
+      which are the two 3-integer dimensions of x
+      so writeValue(arravalue.value[i]); goes back to step 0. 
+   b. our inner recursion of writeValue (arravalue.value[i]) writes the int content (6)
+
+6. writeArray calls endArray(arrayvalue);   
+   a. endArray writes the EOD marker. (7)  
+   
+ARRAY INTEGER 2 2            (a1) (a2) (a4) (a5)
+   ARRAY INTEGER 1 3    (a6):(b1) (b2) (b4) (b5)
+   1                    (b6) 
+   2                    (b6)
+   3                    (b6)
+   EOD                  (b7)
+   ARRAY INTEGER 1 3    (a6):(b1) (b2) (b4) (b5)
+   4                    (b6) 
+   5                    (b6)
+   6                    (b6)
+   EOD                  (b7)
+EOD                     (a7)
+   
+- - - - - - - - - - - - - - - - - -
+deserialization notes 1
+- - - - - - - - - - - - - - - - - - 
+looking at the serialization, it seems as if we should do things a bit differently from the java version.
+when java creates an arrayvalue in which to read an array off the wire, it first allocates a java native
+array, and then wraps an arrayvalue around that. with the scanty information available, and without lookahead,
+we can't allocate our version of a nativearray, since (a) ours is top down, i.e. we need the entire byte blob
+first, and (b) we don't know the item count up front (we know the itemcount for the serialized *array*, in 
+our example above that would be 2, i.e. 2 arrays of type and length not yet read. all we know at the time
+of array container allocation is the number of dimensions, and the actual serialized item count for that
+dimension.
+
+if it turns out we need data not yet read, we could conceivably look ahead for it. however the better approach
+might be to read into arrayvalues, and when done, construct the nativearray. lets explore that avenue here.
+
+0. we start with a serialized arrayvalue of dim 2, type int, whose members are 2 arrayvalues of dim 1.
+
+1. readValue finds ARRAY (a1)
+   a. calls readArray()
+   
+2. readArray 
+   a. calls startArray() getting a new arrayvalue back. 
+   
+3. startArray()   
+   a. reads the content type byte = INTEGER (a2)
+   b. reads the dimensions count = 2  (a4) 
+   c. reads the item count = 2 (a5)  
+   d. allocates an arrayvalue (java code is lost)
+   e. returns the new arrayvalue.
+   
+4. readArray receives arrayvalue from startArray.
+   readArray calls readValues(arrayvalue, vtor)
+   
+5. readValues gets the element vtor for this dimension count
+   value = readValue(arrayvalue); (a6)
+   
+   until value is EOD
+      arrayvalue.add(value)
+      value = readValue() ;
+      
+6. readValue 
+   a. ARRAY (b1) 
+   
+7. readArray()
+   arrayvalb = startArray();
+   
+8. startArray()
+   a. reads the content type byte INTEGER (b2)
+   b. reads the dimensions count = 1 (b4) 
+   c. reads the item count = 3 (b5)
+   d. allocates an arrayvalue (java code is lost)
+   e. returns the new arrayvalb.   
+   
+   
+9. readArray()          
+   a. readValues(arrayvalb);  
+   
+10. readValues gets the element vtor for this dimension count
+    value = readValue(arrayvalb) = tiny 1; (b6)        
+    arrayvalb.add(value)
+    value = readValue(arrayvalb) = tiny 2; (b6)        
+    arrayvalb.add(value)
+    value = readValue(arrayvalb) = tiny 3; (b6)        
+    arrayvalb.add(value)             
+    value = readValue(arrayvalb) = EOD (b7)  
+    return; 
+    
+10. readArray() calls endArray which is a nop
+    and returns arrayvalb. 
+    
+11. readValues (a) gets back Object arrayvalb and puts it to arrayvalue[0] 
+    (repeat 5-10)
+     readValues (a) gets back Object arrayvalc and puts it to arrayvalue[1]         
+   
+   
+999. readValue processing ARRAY receives arrayvalue result of readArray(),
+   presumably an arrayvalue with 2 members, each member being an array dim1 with 3 members. 
+   and converts the arrayValue to nativearray.   
\ No newline at end of file

Added: incubator/etch/trunk/binding-c/runtime/c/project/notes/assignable.txt
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/project/notes/assignable.txt?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/project/notes/assignable.txt (added)
+++ incubator/etch/trunk/binding-c/runtime/c/project/notes/assignable.txt Wed Apr 22 17:25:43 2009
@@ -0,0 +1,420 @@
+
+/////////////////////////////
+// is assignable from 
+/////////////////////////////
+
+1. Available data
+   a. object class_id, obj_type
+   b. inherited from class_id, obj_type, hard-coded in constructor
+      0. does inheritor have to be same obj-type as parent? 
+         a. no - i can inherit from something and be a different thing
+      1. how do we go multi-level? hard-code it all? or read object data.
+      2. seems like a path to explore - constants describing inheritance
+      
+2. Rules
+   a. x.isAssignableFrom(y) means I can assign an object of class y to one of class x   
+   b. x.isAssignableFrom(y) if y inherits from x  
+   c. if y IS_A(x) then x.isAssignableFrom(y)
+   d. x.isAssignableFrom(y) means I can do: xobj = yobj;      
+   e. true:  Object.class.isAssignableFrom( Integer.class);    
+   f. false: int.class.isAssignableFrom( short.class));  
+      1. note above that isAssignableFrom does not imply isConvertibleFrom  
+   g. false: short.class.isAssignableFrom( int.class);
+   h. false: Integer.class.isAssignableFrom( Short.class);
+   i. false: Integer.class.isAssignableFrom( int.class);
+   j. false: Integer.class.isAssignableFrom( short.class);
+   k. false: Integer.class.isAssignableFrom( short.class);
+   l. false: Object.class.isAssignableFrom ( short.class);
+      1. note above that a class must derive from object to assign to object
+      2. however note that in c binding we never encounter such an assignment possibility,
+         since the right side would be wrapped, and the assignment therefore OK.
+   m. true:  Object.class.isAssignableFrom ( Short.class);
+   n. true:  Integer[].class.isAssignableFrom( Integer[].class)   
+   o. false: Object[].class.isAssignableFrom( Integer.class);    
+   p. true:  Object[].class.isAssignableFrom( Integer[].class);  
+   q. true:  Object.class.isAssignableFrom( Integer[].class);    
+   r. true:  short[].class.isAssignableFrom( short[].class)
+      true   Integer.class.isAssignableFrom( Integer.class)  
+      true   String.class.isAssignableFrom( String.class)   
+   s. Integer[] IntObj1 = new Integer[4];
+      Integer[] IntObj2 = new Integer[8];
+      IntObj1 = IntObj2;
+      Object[] x = IntObj1; 
+   t.  
+      1. consider using vtab to get at inheritance hierarchy
+         a. in this way we don't duplicate an inheritance list for all objects of same type
+         b. we would have to make a vtable another etch_object type, such that it could use 
+            the etch_object value* to point to an inheritance list. the vtable object could
+            have a short count field to indicate the length of the inheritance list, or
+            the first entry in the list could be the count, with a null list implying zero,
+            or we could just walk a linked list.
+            1. we would change all i_xxxx objects to conform. we must ensure that all
+               vtables conform to this naming convention also. they seem to do so.
+            2. we would grep all new_xxxx to find ctors and examine each such object for
+               inheritance.            
+         b. for objects which don't currently use the vtable we could allocate one to use
+            just for this purpose.
+         c. however this entails changing many constructors to allocate a vtable. this may be
+            worth it however since the list is infrequently accessed and so we don't want to 
+            use up an object slot. 
+         d. however if there is no inheritance we don't neeed a vtable, so this would save
+            some ctor work. this assumes that the final object parent is not explicit in the 
+            list, but rather exists implicitly for objects deriving from Object.
+ 
+            typedef struct etchparentinfo
+            {
+               union {
+               unsigned short  obj_type; 
+               unsigned short  list_size;    /* entry[0] in any inheritance list */
+               };
+               union {
+               unsigned short  class_id;   
+               unsigned short  parent_count; /* entry[0] in any inheritance list */ 
+               };
+               
+            } etchparentinfo;
+                                       
+            
+            /**
+             * vtabmask
+             * mask over any vtable 
+             */
+            struct vtabmask
+            {
+                unsigned int    hashkey;    
+                unsigned short  obj_type;          
+                unsigned short  class_id;   
+                objmask*        vtab;       
+                int  (*destroy)(void*);     
+                void*(*clone)  (void*);     
+                struct objmask* parent;     
+                etchresult*     result;     
+                unsigned int    refcount;       
+                unsigned int    length;     
+                unsigned char   is_null;   
+                unsigned char   is_copy;   
+                unsigned char   is_static;  
+                unsigned char   reserved;
+
+                etchparentinfo* inherits_from;  
+                
+                /* function pointers start here */              
+            };  
+             
+   u. true:  etch_id_name.class.isAssignableFrom( etch_field.class)
+      true:  etch_object.class.isAssignableFrom( etch_field.class)
+      1. In the first case we need a method of assigning a field to an id_name.
+         In the second case we would wrap the field in an object.
+      2. How do we assign extended object to base object, in general?
+         a. do we somehow manipulate the object header so it becomes a different type?
+         b. do we assume that content is ordered, and memcpy child to parent?
+         c. we need to formalize what is means to assign an object to another,
+            1. does each object now need an assign_from() method?
+               a. such a method would have to be able to cast the extended to the base,
+                  meaning the base portion of extended must be positionally the same.
+      3. Let's postpone implementation of assignment methods until we determine
+         apecifically what sort of assignments will be required by the compiler.         
+ 
+3. Representation of inheritance at run time  
+
+   a. Note that we need to interpret isAssignableFrom same as java, and implement the assignment.
+      1. problematic will be assignments such as int[] to int[], since we must re-construct a target array,
+         due to the fact that our native arrays are fixed size. 
+       
+   b. To solve this problem, begin by representing each of the objects in the examples above
+      by their etch-c internal type codes. 
+      1. Determine how the isAssignableFrom() logic would handle each such isAssignableFrom test
+      2. Determine how an assignemt would be made for each isAssignableFrom instance. 
+
+   e. Object.class.isAssignableFrom( Integer.class) 
+      (Note that assignments must implicitly destroy content of the target object)
+      
+      1. Object.class         
+         a. obj_type:     ETCHTYPEB_ETCHOBJECT
+         b. class_id:     CLASSID_OBJECT
+         c. byte typecode none           
+         d. value (if obj.is_value_object)
+            1. value obj_type
+            2. value class_id
+            
+      2. Integer.class                               
+         a. obj_type:     ETCHTYPEB_PRIMITIVE
+         b. class_id:     CLASSID_PRIMITIVE_INT32
+         
+      3. Determine if assignment is legal
+         a. if (is_etch_object(targetobj)) true
+         
+      4. Assignment
+         a. Prior to assignment, system must destroy target object content.
+            1. if (obj.value) if (obj.is_value_object) obj.value->destroy(); else etch_free(obj.value);  
+         b. obj.value = intobj;
+            obj.is_value_object = TRUE;
+            obj.is_value_owned  = TRUE; // assignment to object always implies object owns value                                   
+            
+   f. int.class.isAssignableFrom( short.class));
+      
+      1. int.class         
+         a. obj_type:     ETCHTYPEB_PRIMITIVE  
+         b. class_id:     CLASSID_PRIMITIVE_INT32
+            
+      2. short.class                               
+         a. obj_type:     ETCHTYPEB_PRIMITIVE
+         b. class_id:     CLASSID_PRIMITIVE_INT16
+         
+      3. Determine if assignment is legal
+         a. if (is_etch_primitive(targetobj)) false
+                       
+   h. Integer.class.isAssignableFrom( Short.class);
+      (note that in c binding, native primitives are never used where class comes into play;
+       therefore in the context of isAssignableFrom rules, int and Integer are the same.)
+      
+      1. int.class         
+         a. obj_type:     ETCHTYPEB_PRIMITIVE  
+         b. class_id:     CLASSID_PRIMITIVE_INT32
+            
+      2. short.class                               
+         a. obj_type:     ETCHTYPEB_PRIMITIVE
+         b. class_id:     CLASSID_PRIMITIVE_INT16
+         
+      3. Determine if assignment is legal
+         a. if (is_etch_primitive(targetobj)) false
+                  
+   l. Object.class.isAssignableFrom ( short.class);
+      ** Note again that in c binding we never encounter a situation of Object x = (short) n;
+         For java, this assignment is not legal. For c, the right hand side would always be
+         a wrapped short, and therefore the assignment is legal.
+      
+      1. Object.class         
+         a. obj_type:     ETCHTYPEB_ETCHOBJECT
+         b. class_id:     CLASSID_OBJECT
+            
+      2. short.class                               
+         a. obj_type:     ETCHTYPEB_PRIMITIVE
+         b. class_id:     CLASSID_PRIMITIVE_INT16
+         
+      3. Determine if assignment is legal
+         a. if (is_etch_object(targetobj)) true
+         
+      4. Assignment
+         a. if (obj.value) if (obj.is_value_object) obj.value->destroy(); else etch_free(obj.value);  
+         b. obj.value = intobj;
+            obj.is_value_object = TRUE;
+            obj.is_value_owned  = TRUE; // assignment to object always implies object owns value                                   
+   
+   n. Integer[].class.isAssignableFrom( Integer[].class
+      note that it would seem that an assignment to a etch nativearray array should necessitate 
+      creating a new target array, however since the nativearray is a wrapped object, we can
+      instead simply destroy the left side content and assign the right side content and counts.
+      
+      1. leftobj      
+         a. obj_type:     ETCHTYPEB_NATIVEARRAY  
+         b. class_id:     CLASSID_ARRAY_INT32
+         c. numdims       1
+         d. content_obj_type ETCHTYPEB_PRIMITIVE
+         e. content_class_id CLASSID_PRIMITIVE_INT32
+            
+      2. rightobj                               
+         a. obj_type:     ETCHTYPEB_NATIVEARRAY
+         b. class_id:     CLASSID_ARRAY_INT32
+         c. numdims       1
+         d. content_obj_type ETCHTYPEB_PRIMITIVE
+         e. content_class_id CLASSID_PRIMITIVE_INT32
+         
+      3. Determine if assignment is legal and do the assignment if so
+      
+         if (is_etch_nativearray(leftobj))
+             if  (is_etch_nativearray(rightobj))
+                  if ((leftobj.class_id == rightobj.class_id)
+                   || (leftobj.class_id == CLASSID_ARRAY_OBJECT))
+                       if  (leftobj.numdims == rightobj.numdims)
+                       {    destroy_nativearray_content(leftobj);  // do the assignment
+                            leftobj.values = rightobj.values;
+                            leftobj.bytecount = rightobj.bytecount; 
+                            leftobj.content_obj_type = rightobj.content_obj_type;  // in case assigning to object[]
+                            leftobj.content_class_id = rightobj.content_class_id;  // in case assigning to object[] 
+                            memcpy(leftobj.dimension, rightobj.dimension, sizeof(leftobj.dimension));
+                            memcpy(leftobj.dimsize,   rightobj.dimsize,   sizeof(leftobj.dimsize));
+                            memcpy(leftobj.counts,    rightobj.counts,    sizeof(leftobj.counts));
+                       )    
+                       else false; /* array dimensions not the same */
+                  else false; /* both sides not array of int32 */              
+             else false; /* both sides not nativearray */
+             
+   o. Object[].class.isAssignableFrom( Integer.class);  
+      ** assignment of a scalar object to an array object is not valid
+      
+      1. Object[].class         
+         a. obj_type:     ETCHTYPEB_ETCHOBJECT
+         b. class_id:     CLASSID_ARRAY_OBJECT
+         c. numdims       1
+         d. content_obj_type ETCHTYPEB_ETCHOBJECT
+         e. content_class_id CLASSID_OBJECT
+                            
+      2. Integer.class                               
+         a. obj_type:     ETCHTYPEB_PRIMITIVE
+         b. class_id:     CLASSID_PRIMITIVE_INT32
+         
+      3. Determine if assignment is legal
+         if (is_etch_nativearray(leftobj))
+             if  (is_etch_nativearray(rightobj)); else false
+ 
+   p. Object[].class.isAssignableFrom( Integer[].class); 
+      note that an array of any type can be assigned to an array of objects, assuming like dimensionality.
+      
+      1. leftobj      
+         a. obj_type:     ETCHTYPEB_NATIVEARRAY  
+         b. class_id:     CLASSID_ARRAY_OBJECT
+         c. numdims       1
+         d. content_obj_type ETCHTYPEB_PRIMITIVE
+         e. content_class_id CLASSID_PRIMITIVE_INT32
+            
+      2. rightobj                               
+         a. obj_type:     ETCHTYPEB_NATIVEARRAY
+         b. class_id:     CLASSID_ARRAY_INT32
+         c. numdims       1
+         d. content_obj_type ETCHTYPEB_PRIMITIVE
+         e. content_class_id CLASSID_PRIMITIVE_INT32
+         
+      3. Determine if assignment is legal and do the assignment if so
+      
+         if (is_etch_nativearray(leftobj))
+             if  (is_etch_nativearray(rightobj))
+                  if ((leftobj.class_id == rightobj.class_id)
+                   || (leftobj.class_id == CLASSID_ARRAY_OBJECT))
+                       if  (leftobj.numdims == rightobj.numdims)
+                       {    destroy_nativearray_content(leftobj);   // do the assignment
+                            leftobj.values = rightobj.values;
+                            leftobj.bytecount = rightobj.bytecount;  
+                            leftobj.content_obj_type = rightobj.content_obj_type;  // in case assigning to object[]
+                            leftobj.content_class_id = rightobj.content_class_id;  // in case assigning to object[]
+                            memcpy(leftobj.dimension, rightobj.dimension, sizeof(leftobj.dimension));
+                            memcpy(leftobj.dimsize,   rightobj.dimsize,   sizeof(leftobj.dimsize));
+                            memcpy(leftobj.counts,    rightobj.counts,    sizeof(leftobj.counts));
+                       )    
+                       else false; /* array dimensions not the same */
+                  else false; /* both sides not array of int32 */  
+             else false;  /* both sides not nativearray */
+                              
+   q. Object.class.isAssignableFrom( Integer[].class);  
+      in this case the object content becomes the nativearray object
+      
+      1. leftobj      
+         a. obj_type:     ETCHTYPEB_OBJECT  
+         b. class_id:     CLASSID_OBJECT
+            
+      2. rightobj                               
+         a. obj_type:     ETCHTYPEB_NATIVEARRAY
+         b. class_id:     CLASSID_ARRAY_INT32
+         c. numdims       1
+         d. content_obj_type ETCHTYPEB_PRIMITIVE
+         e. content_class_id CLASSID_PRIMITIVE_INT32
+         
+      3. Determine if assignment is legal and do the assignment if so
+      
+         if (is_etch_object(leftobj))
+             if  (is_etch_object(rightobj))
+             {    destroy_etch_object_value(leftobj.value);  /* not relevant to this example */
+                  leftobj.value = rightobj.value;
+                  leftobj.is_value_object = rightobj.is_value_object;
+                  leftobj.is_value_owned  = rightobj.is_value_owned;
+             }
+             else /* this example: assigning a non-wrapper object to a wrapper object */
+             {    destroy_etch_object_value(leftobj.value);
+                  leftobj->value = rightobj; // wrap right side inside left side
+                  leftobj->is_value_object = TRUE;
+                  leftobj->is_value_owned  = TRUE;
+             }
+             
+                 
+     u. etch_id_name.class.isAssignableFrom(etch_field.class)
+     
+      1. leftobj      
+         a. obj_type:     ETCHTYPEB_ID_NAME  
+         b. class_id:     CLASSID_ID_NAME
+         c. inherits_from = etch_id_name, Object
+            
+      2. rightobj                               
+         a. obj_type:     ETCHTYPEB_ID_NAME
+         b. class_id:     ETCHTYPEB_ID_FIELD
+         
+      3. Determine if assignment is legal and do the assignment if so
+      
+         if (is_etch_object(leftobj))  { ... }
+         else
+         if (is_etch_object(rightobj)) { ... }
+         else
+         if (is_assignable_from(leftobj, rightobj) // true
+         {
+             // now what do we do with the string? 
+             // it would seem we need a clone_content virtual method on the object 
+             // or possibly clone the object, copy it and delete the object frame but not its owned content
+             // here's how: copy content but mark it not owned:
+                          
+             memcpy(leftobj, rightobj, sizeof(leftobj)); 
+             leftobj->is_copy = TRUE;  // now the dtor will not destroy the name            
+         }
+         
+         a. how to specify static object content
+            1. we don't have a means of specifying that an object's content should not be destroyed with the object.
+               a. when content is objmask-based, the objmask destructor handles this, 
+                  however when content is anonymous pointer, it gets etch_freed with the object,
+                  except in cases where we have added an extra owned flag, such as for nativearray content.
+            2. we can rename the is_copy flag which we do not enforce, and have used only once.
+            3. possible names
+               a. is_cloned_content
+               b. is_static_content
+               c. is_foreign_content
+               d. is_copy
+               e. can we avoid current problems by re-purposing the is_static and is_copy flags
+                  to mean is_static_shell and is_static_content?
+                  1. would we miss the is_copy meaning in that case? i.e. does is_static_content
+                     have the same effect as is_copy?
+                     a. maybe we need to know that an object is a copy of another, in addition
+                        to whether or not content is not owned
+                  2. possible names:
+                     a. is_statcon, is_statobj
+                     b. is_owned derivatives are not good because default should be owned
+                        and we don't want to have to explicitly flag default conditions.
+                     c. is_static_cont, is_static_shell
+                  3. can we instead use the is_static flag as quad-state? e.g., 1 indicates shell, 
+                     2 content, and 3 both. i like this idea. it buys us all needed functionality
+                     without sacrificing meaning. we could rename is_static to not appear boolean.
+               
+         b. how to copy one object to another, 
+             1. need to handle memory for the abandoned left side content 
+             2. need to ensure that new left side content becomes imuutable
+             3. if we enforce content inheritance order (base class first, child 1 next, etc.)
+                we should be able to memcpy right side to left side, and then mark left side 
+                content immutable with the is_copy flag.
+             4. how do we destroy left side content. we almost certainly want to use the destructor
+                since it already handles content, however it would need to know to not destroy the
+                object shell.
+             5. how to invoke destructor without destroying shell
+                a. another byte flag? if we had reserved one byte for bitflags we could do internal
+                   stuff like this much more easily. check the objects which have used this flag
+                   and determine if we can put the flag somewhere else.
+                b. use an unused but existing field in the object.
+             5. HOW DO WE HANDLE REFCOUNTED OBJECTS ON EITHER SIDE?
+                a. if an obj is refcounted it means that it is "owned" by multiple code paths.
+                b. example 1: objB recounted 2 copied to objA not refcounted.
+                   1. the refcounts should remain the same on both sides, i.e. after copy,
+                      objA refcount is set to zero.
+                c. example 2: objB not refcounted copied to objA refcounted 2.
+                   1. again, objA recfount should not change.
+                d. so the rule is, the target object retains its refcount.
+             6. is the etchresult* considered to be a part of the content?
+                 a. i.e. if I copy an object, can the object include a result? if so, the
+                    result is part of the content.
+                 b. however if I return an object with a result, that object might include
+                    static content, but the result must still be destroyed.
+                 c. so the rule must be that if we copy an object, the result does not
+                    go with it, i.e. we null out the result address after copy.
+              7. so then, what is the required housekeeping before and after a copy
+                 a. before copy, save left side refcount
+                 b. destroy left side content  
+                    1. mark left side static shell and invoke its destructor
+                 c. memcpy right side to left side
+                 d. set left side refcount to saved refcount
+                 e. set left side result to null
+         
+   
\ No newline at end of file

Added: incubator/etch/trunk/binding-c/runtime/c/project/notes/clientsession.txt
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/project/notes/clientsession.txt?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/project/notes/clientsession.txt (added)
+++ incubator/etch/trunk/binding-c/runtime/c/project/notes/clientsession.txt Wed Apr 22 17:25:43 2009
@@ -0,0 +1,40 @@
+
+Q. where is client session created?
+A. in etch_transport.tcpxfact_session_accepted(), called from etch_tcpsvr_acceptproc(),
+   then new_etch_session()
+
+   the delivery service is populated there, the remote client, server impl, and stub
+   are populated in new_helper_accepted_server(), which instantiates them. 
+
+Q. where is client session blocking receive loop?
+A. etch_tcpserver.etch_tcpserver_listenerproc()
+
+Q. where is delivery service created?
+A. etch_transport.tcpxfact_session_accepted, and then etch_transport.new_etch_transport(), 
+	and then etch_transport.new_tcp_delivery_service()
+
+Q. where is delivery service torn down? (prior to code mods for session support)
+A. etch_transport.destroy_etch_listener(). 
+   this is the destructor for the main listener instantiated in [main].
+   obviously it is wrong to destroy the delivery service there, as well as remote client and stub.
+
+Q. where should delivery service be torn down now?
+A. etch_tcpserver_listenerproc() exit, then transport.destroy_etch_clientsession()
+
+   a. actual teardown must be in code that can see transport.h. 
+      and has an i_sessionlistener* reference.
+
+   b. end of session state is first known in etch_tcpserver.etch_tcpserver_listenerproc(),
+      when the receive loop exits. this returns to etch_apr_threadproc.
+      Q. where is threadproc etch_tcpserver_listenerproc() started from?
+      A. etch_tcpserver.etch_tcpsvr_acceptproc().
+         this method calls back into transport via tcpserver->on_session_accepted(),
+         which is etch_transport.tcpxfact_session_accepted(). 
+         THIS METHOD COULD RETURN AN OBJMASK SESSION OBJECT
+
+   c. ideally teardown would be on main thread, however we don't have an easy way to do that,
+      since the thread exit return is generic.
+
+   d. we'll try calling the session object destructor at exit of etch_tcpserver.etch_tcpserver_listenerproc().
+      a. the connection cx.session is an objmask* reference to the etch_session* object.
+      

Added: incubator/etch/trunk/binding-c/runtime/c/project/notes/hashmods.txt
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/project/notes/hashmods.txt?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/project/notes/hashmods.txt (added)
+++ incubator/etch/trunk/binding-c/runtime/c/project/notes/hashmods.txt Wed Apr 22 17:25:43 2009
@@ -0,0 +1,78 @@
+
+1. we probably do not need the hashkey uint at the head of object,
+   a. it is there in order to tell jenkins that an object is length 4 and to hash those 4 bytes.
+   b. if we can supply the hash code to jenkins, rather than it doing the hash based on address and length,
+      then we can lose this item.
+   
+2. however we will need to replace the hashkey uint with a hashkey *function*.
+   a. we want to be able to ask an object to give us its hashkey.
+      1. or alternatively it could give us its hashable address and length.
+      2. however it is probably cleaner to simply return a 4 byte hashkey.
+   b. this is the way c# objects work, by supplying the actual key. they have a default, however
+      types tpo be used as keys are supposed to override the default.
+   c. we could add methods to jenkins to accept a hash function callback pointer.
+      1. if our objects supply address and length we would not need to change jenkins to not hash.
+      2. if our objects instead supply the hashkey value, we would need to add fuctions to jenkins to accept
+         a precalculated hashcode rather than do the hash calculation itself.
+   d. each object would need to have a unique vector of at least 4 bytes to hash.
+      0. jenkins will copy the key to its own memory
+      1. objects not likely to be hashed could simply supply their memory address.
+      2. objects with names obviously use their name.
+      3. objects with unique numeric keys use either the stringed key or the numeric key.
+      4. we could establish an object id if we need it.
+      5. for an object to do hash lookup rather than sequential search, the most common lookup key
+         should be that used for hash.
+             a. therefore hashing on object id is not very useful.
+
+3. if an object hashkey function returns its key address and length:
+   a. we make new versions of all jenkins functions accepting key and length.
+   b. these new functions accept a callback instead of key and length.
+   c. the new functions continue to compute their key as usual.
+   d. we should optionally return a comparator function with the hashkey return.
+   e. how will we return two parameters?
+      1. jenkins passes pointer to struct hashkeyinfo, which is info it wants back:
+         a. char* key
+         b. uint  keylen;
+         c. etch_comparator* compare;
+         d. uint optional_hashkey; /* if non-zero, jenkins uses precalc key */
+   f. so the callback looks like this
+      int (*get_hashkey) (&my_hashkeyinfo, const int option);
+ 
+     
+
+4. plan for objects with no current search key
+   a. the objects are responsible for themselves. anonymous Object keys need to plan for a key.
+  
+5. we should find_by the actual object, rather than by the actual key. 
+   a. for example, type lookup, keyed by field.
+   b. 
+      result = jenkins_find(mytype->get_hashkey, &optional_out); 
+      or ...
+      result = etchmap_find(mytype, &optional_out); 
+ 
+
+6. however when we *put* an object, jenkins expects the address we give it to be both the key object,
+   *and* the hash start. 
+   a. we could add a function to jenkins to accept different addresses for object and hashkey.
+
+7. the way jenkins works it expects the key object and the hashable info to exist at the same
+   address. and the way etch works is that this address must point at the key object. 
+   a. possibly we can change jenkins to assume that the supplied address points at a hashinfo callback.
+
+
+
+X. test plan
+   a. don't change object layout yet, but *assume* hashkey header is the callback
+   b. write test program which defines new custom object types with varying keys
+      
+
+
+
+
+
+
+
+
+
+
+

Added: incubator/etch/trunk/binding-c/runtime/c/project/notes/packet.txt
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/project/notes/packet.txt?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/project/notes/packet.txt (added)
+++ incubator/etch/trunk/binding-c/runtime/c/project/notes/packet.txt Wed Apr 22 17:25:43 2009
@@ -0,0 +1,105 @@
+
+Session interface
+=================
+Object sessionQuery(Object query)
+void   sessionControl(Object control, Object value)
+void   sessionNotify(Object event)
+
+Transport interface
+===================
+Object transportQuery(Object query)
+void   transportControl(Object control, Object value)
+void   transportNotify(Object event)
+
+Source interface
+================
+Source<H extends SourceHandler> extends Transport
+H*   getHandler();
+void setHandler(H*);
+
+SourceHandler interface
+=======================
+SourceHandler<S extends Source> extends Session
+S*   getSource();
+void setSource(S*);
+
+PacketHandler interface
+=======================
+extends SourceHandler<PacketSource>
+void packet(Who, flexbuf);
+
+PacketSource interface
+=======================
+extends Source<PacketHandler>
+int  headerSize();
+void packet(Who, flexbuf);
+
+SesssionMessage interface
+=========================
+extends Session
+// delivers data to the session from the transport
+// returns true if message consumed
+boolean sessionMessage(Who from, Message)
+
+TransportMessage interface
+==========================
+extends Transport<SessionMessage>
+// delivers data to the transport (from the session?)
+void transportMessage(Who to, Message)
+
+
+
+- - - - - - - - - - - - - -
+    message
+- - - - - - - - - - - - - -
+
+MessageSource interface
+=======================
+void messagex(Who, Message);
+
+MessageHandler interface   // to deliver messages from msgizer  
+<S extends Source> extends SourceHandler<S>
+
+MessagizerMessageSource interface
+=================================
+extends MessageSource, Source<MessageHandler<MessagizerMessageSource>>
+
+
+- - - - - - - - - - - - - -
+    messagizer
+- - - - - - - - - - - - - -
+
+implements SessionPacket, TransportMessage
+TransportPacket* transport;
+TDI, TDO.
+FlexBuffer*  msgbuf;
+
+void TransportMessage(Who to, Message);
+void SessionPacket(Who from, packetbuffer);
+
+
+
+notes on how to destroy an object which *implements* an interface,
+but where the problem code does not have a pointer to the implementing
+object, but rather to the interface itself?
+the use case is where we implement an object fooimpl wrapping an i_foo,
+but the problem code does not save a fooimpl*, but rather saves and passes 
+around an i_foo*, and the i_foo contains a void* fooimpl*
+
+=============================================================
+
+1. problem code does ifoo->destroy()
+
+2. destroy_ifoo() uses its fooimpl* to do fooimpl->destroy()
+
+3. destroy_fooimpl() does destroy_ifoo()
+
+----------------------------------------------------------------
+
+how to handle situation where interfaces are created separately (i.e. not in implementor ctor)?
+
+a. problem code creates i_foo.
+
+b. fooimpl constructor is passed i_foo*  
+
+c. code proceeds as in prior example.
\ No newline at end of file

Added: incubator/etch/trunk/binding-c/runtime/c/project/notes/run.txt
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/project/notes/run.txt?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/project/notes/run.txt (added)
+++ incubator/etch/trunk/binding-c/runtime/c/project/notes/run.txt Wed Apr 22 17:25:43 2009
@@ -0,0 +1,205 @@
+GENERAL NOTES
+
+=====================================================================
+FAQ
+=====================================================================    
+1.   Q: where is the server accept loop, and what causes the loop to exit?
+     A. the accept loop is etch_tcpsvr_acceptproc().
+        destroy_etch_listener() forces the main listener thread down  
+        via etch_tcpsvr_close(svr); in destroy_etch_listener.
+        
+2.   Q. how do we message the accept?
+     A. i_sessionlistener->transport_control.
+     
+3.   a. the specific transport's (tcpserver's) "session" interface is the i_sessionlistener.  
+     b. the i_sessionlistener.thisx is be the etch_tcpserver. 
+     c. and the i_sessionlistener.transport is how we message the main listener. 
+     d. session.mainlistener is the i_sessionlistener.
+     
+4.   Q: where is server shutdown recognized? 
+     A: etch_tcpserver_listenerproc(), is_shutdown_request = TRUE; svr->is_started = FALSE; 
+        and BREAK out of receive loop.
+        
+5.   Q. where do we catch server's main listener exit?    
+     A. xxxx_helper: xxxx_listener_start(); etchlog ("main listener exited\n");
+     A. etch_tcpserver: etch_tcpserver_listenerproc(); catch result of transport_control(STOP 
+     
+6.   Q. where is server's receive thread recognized?
+     A. etch_tcpsvr_acceptproc() 
+     
+7.   Q. how is the server receive thread object accessed in the generic transport context?
+     A. params.session[i].cx.thread     
+     
+8.   Q. how could we programmatically stop the server main listener from the server's main thread?
+     A. listener->transport_control (listener->thisx, STOP_WAITDOWN, ms); 
+     
+9.   Q. where is the receive loop (data from other side)?
+     A. tcpserver: at etch_tcpserver_listenerproc; line: etch_tcpclient_receive(); 
+        tcpconxn:  at etch_tcpclient_receivex; line: apr_socket_recv()
+        
+10.  Q. how is data received off the socket routed?
+     A. etcpconxn: at etch_tcpclient_receivex; line: cx->on_data (tcpx, 0, datalen, buf);  
+     
+11. Q. where are the tcp connection, packetizer, messagizer, mailbox manager, 
+       and delivery service instantiated?
+    A. etch_transport: new_tcp_delivery_service()
+    
+12. Q. how is the inter-layer messaging chain constructed?
+    A. a) each layer implements both a session interface and a transport interface, and hosts 
+          a session and a transport interface owned by another layer, its session owned by the 
+          adjacent higher layer, its transport owned by the adjacent lower layer.
+       b) each layer's constructor is passed the transport implementation of the next lower layer,
+          and sets its own transport to the passed transport interface.
+       c) each layer implements its own session interface, and its constructor sets the session 
+          of the next lower layer, to its own session interface implementation. 
+       d) the thisx pointers of the hosted session and transport interfaces, are the layer objects
+          which implemented those interfaces. for example, packetizer.session is the session
+          interface implemented by messagizer, and so messagizer.session.thisx is the messagizer.   
+    
+13. Q. what is the messaging stack hierarchy?
+    A. as follows, transport messaging traveling down towards zero, session messaging traveling up:
+       1. tcp connection       
+       2. packetizer
+       3. messagizer
+       4. mailbox manager
+       5. delivery service
+       6. stub
+       7. stub user interface 
+       
+14. Q. where is the client receive thread constructed, and what is the receive procedure?       
+    A. etch_tcp_client* new_tcp_client (etch_tcp_connection*), called from etch_tcpclient_start_listener(); 
+       the receive proc is etch_tcpclient_listenerproc()
+    
+15. Q. where is the tcp client receive listener stopped? 
+    A. etch_tcpclient_stop_listener(), called from etch_tcpconx_transport_control(), case CLASSID_CONTROL_STOP.  
+
+ 
+============================================================
+debugger breakpoints to catch significant events on SERVER
+============================================================   
+
+###  MODULE                 FUNCTION                       LINE
+---  ---------------------- ------------------------------ -------------------------------------------------------------
+1.   etch_transport         new_etch_listener              i_sessionlistener* l = new_sessionlistener_interface 
+  
+2.   xxxx_listener_main     _tmain                         xxxx_listener_start (listener, waitupms);   
+
+3.   xxxx_helper            xxxx_listener_start            listener->transport_control (START_WAITUP)
+
+4.   etch_tcpserver         etch_tcpsvr_acceptproc         apr_socket_accept (&newsock, ... 
+
+5.   xxxx_helper            xxxx_listener_start            listener->wait_exit (listener);  
+
+6.   NOW BLOCKING WAITING FOR CONNECTION - SEND CONNECT AND DATA
+
+7.   etch_tcpserver         etch_tcpsvr_acceptproc         newx = new_accepted_tcp_connection (hostname, ...
+
+8.   etch_tcpserver         etch_tcpsvr_acceptproc         tcpserver->on_session_accepted (...
+
+9.   etch_transport         tcpxfact_session_accepted      delivery_service = new_etch_transport_a (
+
+10.  etch_transport         tcpxfact_session_accepted      delivery_service->itm->transport_control (START 
+
+11.  etch_tcpserver         etch_tcpsvr_acceptproc         thread = svr->threadpool->run(etch_tcpserver_listenerproc
+
+12a. etch_tcpserver         etch_tcpserver_listenerproc    mainlistener->transport_control (STOP_WAITDOWN
+12b. etch_tcpserver         etch_tcpserver_listenerproc    ETCHOBJ_DESTROY(cx->session);  
+
+13.  etch_tcpserver         etch_tcpsvr_acceptproc         return
+
+14.  xxxx_helper            xxxx_listener_start            etchlog ("main listener exited\n");
+                      
+15.  etch_tcpserver         etch_tcpserver_listenerproc    catch result of transport_control(STOP_WAITDOWN
+
+16.  xxxx_listener_main     _tmain                         ETCHOBJ_DESTROY(listener);    
+
+17.  SERVER EXE EXITS
+
+
+=====================================================================
+debugger breakpoints to catch the most siginificant events on CLIENT
+=====================================================================      
+
+###  MODULE                 FUNCTION                       LINE
+---  ---------------------- ------------------------------ -------------------------------------------------------------
+1.   xxxx_helper            start_perf_client              remote = new_remote_server ()
+  
+2.   xxxx_helper            new_remote_server              remote_server = new_xxxx_remote_server ()
+
+3.   xxxx_remote_server     new_xxxx_remote_server         rs->server_base = new_xxxx_remote_server_base ()
+
+4.   xxxx_helper            new_remote_server              myclient = p->new_client (remote_server);
+
+5.   xxxx_client_implx      init_xxxx_client_impl          pc->xxxx_client_base = new_xxxx_client_base (pc);  
+
+6.   xxxx_helper            new_remote_server              client_stub = new_perf_client_stub ()
+             
+7.   etch_stub              new_stubimpl_init              newstub->stub_base = new_stub ()
+
+8.   xxxx_helper            new_remote_server              return
+
+9.   etch_remote            etchremote_start_waitup        return thisx->transport_control(START_WAITUP) 
+
+10.  etch_transport         tcpdelsvc_transport_control    dstransport->transport_control()
+
+11.  etch_tcpconxn          etch_tcpconx_start             return etch_tcpconx_open ()
+
+12 . xxxx_helper            start_xxxx_client              remote->destroy(remote);
+
+13.  xxxx_remote_server     destroy_perf_remote_server     ETCHOBJ_DESTROY(thisx->remote_base);
+
+14.  xxxx_remote_server     destroy_perf_remote_server     ETCHOBJ_DESTROY(thisx->server_base);
+
+15.  xxxx_remote_server     destroy_perf_remote_server     ETCHOBJ_DESTROY(thisx->client_factory);
+
+14.  etch_transport         destroy_etch_client_factory    ETCHOBJ_DESTROY(((objmask*)thisx->iclient)); 
+
+14.  etch_transport         destroy_etch_client_factory    ETCHOBJ_DESTROY(((objmask*)thisx->stub)); 
+
+14.  etch_transport         destroy_etch_client_factory    ETCHOBJ_DESTROY(((objmask*)thisx->dsvc)); 
+                      
+15.  xxxx_client_main       _tmain                         if (NULL == remote) break;
+
+17.  CLIENT EXE EXITS
+
+
+=====================================================================
+Notes on message functionality thread execution
+=====================================================================
+
+1. The stub's session i/f becomes the delivery's session in the stub base ctor. 
+
+2. The delivery's session is typed to SessionMessage. The setSession sets the
+   entire session object, which in this case is a SessionMessage. So setting
+   the delivery's session also sets its SessionMessage method.
+   a. This means we need to override set_session on all objects whose session
+      i/f augments i_session.
+  
+3. Therefore, calling session_message on the transport (delivery) invokes the
+   stub's session_message.
+
+4. The stub's session_message expects as a parameter, a message to be "executed", 
+   either on a pool thread or inline.
+
+5. stubbase.session_message : inline execute mode
+   a. type.stub_helper().run (delivery*, _obj, whofrom, msg)
+          this translates to:
+          result = stubhelper(stub, delivery, obj, sender, msg);
+   b. stubhelper's are implemented in the xxxx_server_stub, e.g. perf_server_stub.
+
+   c. the perf_server_stub stubhelper for the type for perf.add() is as follows:
+    
+      static int run (stub, delivery, i_perf_server* perf, whofrom, msg)
+      {
+          etch_message* rmsg = message_get_in_reply_to(msg);
+          etch_int32* x = message_get msg, perfv._mf_x);
+          etch_int32* y = .... 
+          etch_int32* addresult = perf->add (perf, x, y);
+          etch_field* key = builtins._mf_result; /* todo: get from perfvf instead, where to get vf? */
+          result = message_put (rsmg, key, key, addresult);
+
+          // if result bad, transport an exception
+
+          result = delivery->itm->transport_message (delivery, whofrom, rmsg);
+      }	
+ 

Added: incubator/etch/trunk/binding-c/runtime/c/project/notes/servexe.txt
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/project/notes/servexe.txt?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/project/notes/servexe.txt (added)
+++ incubator/etch/trunk/binding-c/runtime/c/project/notes/servexe.txt Wed Apr 22 17:25:43 2009
@@ -0,0 +1,279 @@
+
+=====================================================================
+Notes on generated files and their interfaces with the etch runtime
+=====================================================================
+
+Each service XXXX will include the following generated and/or user-created (i.e. not runtime) files:
+
+base_XXXX_client		default stub functions for all client implementations
+base_XXXX_server		default stub functions for all server implementations
+impl_XXXX_client  		user's implementation of base_XXXX_client functions
+impl_XXXX_server		user's implementation of base_XXXX_server functions
+main_XXXX_client		executable entry point for client
+main_XXXX_listener		executable entry point for server
+XXXX			        class representation of user IDL for service XXXX
+XXXX_client		        interface defining client-directed functions to be implemented
+XXXX_server		        interface defining server functions to be implemented
+XXXX_helper		        static methods, interfaces and constants for creation of server and client instances	
+remote_XXXX		        send(), begin_call(), end_call(), transport control (start , stop, etc), plus async wrapper
+remote_XXXX_client		client extension of remote_XXXX			
+remote_XXXX_server		server extension of remote_XXXX; async service method implementations
+stub_XXXX		        base stub for service XXXX
+stub_XXXX_client		client stub
+stub_XXXX_server		server stub; thread procs for each message type, calling service impl methods.
+value_factory_XXXX		type declarations, type map, class to type map, type serializers, validators, extends default vf
+
+
+--------------------------------------------------------
+java binding's instantiation of a listener 
+--------------------------------------------------------
+  1. XXXXHelper.newListener(uri, rex, funcNewXXXXServer)
+  2. transportFactory.getListener(uri, resx, funcNewServer)
+  3. TransportFactory f = tcpfactory.
+  4. tcpfactory.newListener(funcNewServer): 
+  5. define onAccepted, which will create the delivery service
+  6. tcpfactory.newListener() will return the Transport interface,  
+         which is a TcpListener implementing a Transport<SessionListener>  
+         
+  1. JAVA MAIN calls transport = helper.newListener(main_new_perf_server)  
+
+  2. HELPER.newListener (main_new_perf_server)
+     a. init resources, create perfVF and put to resx
+     b. transport = TransportFactory.getListener (helper_new_server)   
+     c. return transport
+
+  3. TransportFactory.getListener (helper_new_server)
+       a. return TcpTransportFactory.newListener(resx, helper_new_server);
+
+  4. TcpTransportFactory.newListener(resx, helper_new_server);
+     a. new SessionListener()
+     b. new TcpListener(resx);
+     c. TcpListener.setSession(SessionListener);
+     d. return TcpListener
+
+     -  TcpListener.OnSessionAccepted(clientsocket)   
+        a. deliverysvc = newTransport()
+        b. CALLBACK to helper_new_server(delivery);
+        c. delivery.TransportControl(START);
+
+  5. HELPER_new_server(delivery)
+     a. new RemotePerfClient(...
+     b. PerfServer server = CALLBACK to MAIN_new_perf_server(remoteclient);
+     c. new StubPerfServer(delivery, server);              
+
+
+
+
+main ()  // pseudocode for server executable
+{
+    // see above comments for flow. we pass around the accepted handler which will construct the specific server side components
+
+    i_sessionlistener* lxr = XXXX_helper.new_listener (uri, NULL, funcptr(new_XXXX_server)); 
+    
+    result = lxr->transport_control (lxr, START_WAITUP, nseconds);   
+}
+
+
+etch_transport* new_listener (uri, resources, funcptr(new_XXXX_server) )   // from PerfHelper.newListener
+{   
+    etch_resources* resx = init_resx(resx);
+    valuefactory_XXXX = new_valuefactory_XXXX();	
+
+    i_server_factory* iserverfact = new_server_factory_interface 
+        (thisx, sessionobj, isession, funcptr_new_server); // PASSING func below
+
+    i_sessionlistener*  lxr = new_etch_listener ( uri, resx, iserverfact );
+
+    return lxr; // actually we may need to return the lxr's itransport*
+}
+
+
+void  new_server (thisx, delivery_service)   // from PerfHelper.newListener, the "server_factory" passed to new_etch_listener
+{   
+    // This is the "server_factory" passed to new_etch_listener, which is the java TransporFactory.getListener.
+    // This function is called by the tcp server's accept handler, through the server factory interface.
+    // it is currently virtual to the tcp server object, where it is called by etch_tcpsvr_acceptproc.
+    
+    // this function needs access to the uri, resources, and impl_factory function passed to new_listener,
+    // and to the vf instantiated by new_listener. TODO FIGURE OUT HOW
+
+    remote_XXX_client* client = new_remote_XXXX_client(dsvc, vf); // TODO
+    
+    XXXX_server* server = funcptr_new_XXXX_server(client);
+    
+    new_stub_XXXX_server(dsvc, server, pool, pool);
+}
+
+
+
+XXXX_server*  new_XXXX_server (remote_XXXX_client* client)    // our implementation of XXXX_server_factory
+{  
+   // our implementation of XXXX_server_factory (which is just funcptr(new_XXXX_server))
+    return new_impl_XXXX_server (client);
+}
+
+
+
+typedef struct  impl_XXXX_server
+{
+    remote_XXXX_client*  client;
+    i_objsession* iobjsession;
+    _session_control(); _session_notify(); _session_query(); // objsession stuff
+
+    i_XXXX_server* ixxxxserver;
+    etch_int32 (*add) (etch_int32* x,  etch_int32* y);   // XXXX_server stuff
+   // etc. more XXXX functions
+   // these interfaces must be explicit as well as embedded
+};
+
+
+
+XXXX_server*  new_impl_XXXX_server (remote_XXXX_client*  client)
+{
+     impl_XXXX_server	* newserver = new_object(......
+     newserver->client = client;
+     newserver->add = myaddfunc;
+     // etc. plug in all service virtuals
+     return newserver->ixxxserver;
+}
+
+
+------------------------------------------------------------------------------
+notes on symmetry
+------------------------------------------------------------------------------
+
+===============================
+SERVER SIDE
+=============================== 
+
+main:  
+    ImplXxxxServer (XxxxServer) = serverFactory = callback to new ImplXxxxServer ( RemoteXxxxClient client );
+    Transport listener = helper.newListener(uri, callback);  /* or "remote client", for symmetry */
+
+helper: 
+    RemoteXxxxClient client = new RemoteXxxxClient (ds, vf);
+    XxxxServer server = call back to new ImplXxxxServer (client );
+    new StubXxxxServer (ds, server, pool, pool); 
+    
+- - - - - - - - - - - -
+remote/local symmetry
+- - - - - - - - - - -  -    
+RemoteXxxxClient extends RemoteXxxx implements XxxxClient  
+    RemoteXxxx extends RemoteBase implements Xxxx  
+        RemoteBase (ds, vf )
+    XxxxClient extends Xxxx
+        /* server-directed interfaces plus any client-directed */
+
+ImplXxxxServer extends BaseXxxxServer  
+    RemoteXxxxClient client;
+    BaseXxxxServer implements XxxxServer, ObjSession
+        interface XxxxServer extends Xxxx
+
+
+===============================
+CLIENT SIDE
+=============================== 
+
+main: 
+    ImplXxxxClient = implFactory = callback to new ImplXxxxClient ( );	
+    RemoteXxxxServer server = helper.newServer ( uri, callback ) // **** new_perf_remote_server() in c
+    
+helper::newServer() // **** c binding new_remote_server()
+    deliveryService ds = TransportFactory.getTransport(uri,resx);
+    RemoteXxxxServer server = new RemoteXxxxServer  (ds, vf);
+    XxxxClient client = callback to newXxxxClient (server); 
+    new StubXxxxClient (ds, client, pool, pool)
+       
+ - - - - - - - - - - - -
+remote/local symmetry
+- - - - - - - - - - -  -   
+RemoteXxxxServer extends RemoteXxxx implements XxxxServer 
+    interface XxxxServer extends Xxxx /* also used by ImplXxxxServer */  	
+    
+ImplXxxxClient extends BaseXxxxClient
+    RemoteXxxxServer server;
+    BaseXxxxClient implements XxxxClient, ObjSession
+        XxxxClient extends Xxxx /* also used by RemoteXxxxClient */ 						
+        
+  
+              
+===============================
+COMMONALITIES
+===============================
+1. XxxxClient   
+       by ImplXxxxClient, RemoteXxxxClient  
+       
+2. XxxxServer
+       by ImplXxxxServer, RemoteXxxxServer        
+
+3. RemoteXxxx
+       by RemoteXxxxClient, RemoteXxxxServer 
+       
+4. Xxxx
+       by everything    
+   
+    
+===============================
+INHERITANCE
+===============================       
+       
+IMPL_XXXX_CLIENT
+ |  RemoteXxxxServer* server;
+  - BASE_XXXX_CLIENT
+    |- XXXX_CLIENT: XXXX (interfaces)
+    |- /* client-directed methods if any */
+    |- myfoo(); mybar(); etc. /* service XXXX interfaces */
+    |- mydata;
+     - OBJSESSION
+       |  _sessionControl(), _sessionNotify(), _sessionQuery()
+
+
+IMPL_XXXX_SERVER
+ |  RemotePerfClient* client;
+ |  myfoo() { } etc; { /* service method implementations */ }
+ |  mydata;
+  - BASE_XXXX_SERVER
+    |  myfoo(); mybar(); etc. /* service method empty stubs */  
+    |- XXXX_SERVER: XXXX (interfaces)
+    |- myfoo(); mybar(); etc. /* service method interfaces */
+    |  mydata;
+     - OBJSESSION
+       |  _sessionControl(), _sessionNotify(), _sessionQuery()     
+ 
+ 
+===========================
+C BINDING IMPLEMENTATION 
+=========================== 
+      
+SERVER SIDE
+-----------      
+xxxx_remote_client.h 
+    i_perf_client* perf_client_base;   
+    perf_remote*   perf_remote_base;  
+    
+xxxx_listener_main:
+    i_sessionlistener* listener = new_etch_listener (callbacks);
+        i_perf_server* new_server (void* thisx, etch_server_factory* p)
+            perf_server_impl* newserver = new_perf_server_impl (remoteclient);    
+    
+new_remote_client ()                     /* perf_remote_client.c */
+    rc->perf_remote_base = new_perf_remote ();       /* perf_remote.c */
+        * establish ds, vf, start and stop methods.
+        * establish transport, send, begincall, endcall methods
+        * copy stubs from remote.iperf
+    rc->perf_client_base = new_perf_client_base ();  /* perf_client.c */ 
+        * instantiate perf service interface, copy default method impls
+        * TODO don't re-implement service interface - pass existing iperf
+ 
+CLIENT SIDE
+-----------
+xxxx_remote_server.h 
+    i_perf_server* perf_server_base;  /* owned */
+    perf_remote*   perf_remote_base;  /* owned */
+    
+xxxx_client_main:
+    
+
+new_perf_remote_server ()
+    rc->perf_remote_base = new_perf_remote (thisx, ids, vf);
+    rc->perf_server_base = new_perf_server_base ();  

Added: incubator/etch/trunk/binding-c/runtime/c/project/notes/todo.txt
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/project/notes/todo.txt?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/project/notes/todo.txt (added)
+++ incubator/etch/trunk/binding-c/runtime/c/project/notes/todo.txt Wed Apr 22 17:25:43 2009
@@ -0,0 +1,246 @@
+
+___ 1. on all cache accessors lazy load cache if necessary.
+       this way we don't have to call init code in tests.
+
+OK_ 2. determine why in cachetest if we ask memtable to clean up
+       and there are two allocations, mem.first is OK and then
+       mem.next wraps. DONE was my bug.
+
+OK_ 3. jenkins_clear uses free when asked 
+       why were keys and values not etch_malloc'ed? maybe this is OK.
+       DONE we solved this issue by using installable callback on free.
+
+OK_ 4. write a true iterator for hashtable interface and all collections.
+       this will be a struct object that when instantiated, calls first()
+       and stores the current position as instance data. the iterator 
+       has three methods, next(), is_more(?), and destroy(). Each time next()   
+       is called it returns the current position, and calls next internally, 
+       storing the new current pos. it should probably permit a startat also.
+       current position instance data will probably be specific to the collection
+       and therefore would be a heap allocated member of the iterator object.
+       To do this entirely generally all collections would want to be objectized
+       with vtables similarly to the way instance data is done, and implement  
+       at least first() and next(). Add a destroy() handler as well, which might
+       want to have freekey and freeval arguments. DONE
+       
+OK_ 4.1 install iterator in struct value DONE
+
+OK_ 4.2 install iterator in array value DONE       
+
+OK  5. cache the etch_object vtable in a global variable, and reference this
+       in new_etchobject, in order that we don't have to do a cache lookup
+       on every object construction. DONE.
+
+OK_ 6. write tests for boxed objects 
+
+___ 7. configure etch_free to not necessarily complain if allocation untracked.
+       not sure how atm, we definitely can't have another parameter.
+
+___ 8. deal with the discontinuity between memory tracking table and the vtable cache.
+       when we clear the memtable after each test, we compromise the final cleanup of
+       the cache, which now has dangling pointers into the memtable. we deal with this
+       currently by not etch_malloc'ing vtables. maybe this is OK, but there is something
+       less than satisying about this arrangement.
+
+___ 9. make shallow copy non-virtual in etchobject. 
+
+OK_ 10. write ctor with dedicated vtable for boxed arraylist type, that permits destruction
+        of the boxed object with or without freeing memory for the list contents. since we
+        can't pass a "don't free content" parameter with the etchobjects's destroy(),
+        we'll need to be able to set a flag somewhere in the object itself to so indicate,
+        prior to calling destroy(). One way we can do this is by adding a parameter to 
+        new_etch_arraylist, which will set the is_readonly flag on the underlying etch_arraylist,
+        causing arraylist_destroy() to ignore its is_free_content parameter. PARTLY DONE 11/1.
+        we added the ctor flag to prevent memory cleanup attempt. we did not yet add a custom
+        ctor, so clone and destroy cleanup is still invoked from the default clone and destroy.
+
+OK_ 11. add an optional content destroy handler callback to collections. this would be made
+		simpler given item (4), objectizing collections with first() and next(), since we
+		would now have a vtable to which we would only need to add another virtual method.
+		PARTLY DONE installable callback on hashtables, still need to do arraylist. DONE.
+
+OK_ 12. add a content type property to collections differentiating between content for which
+        memory can be freed as a unit, and content consisting of multiple heap allocations
+        in particular etchobject. DONE.  
+
+OK_ 13. etchobject.size is not accurate for objects which have dynamic underlying content.
+		WON'T FIX -- the way it works is the way it must be, in order for anonymous copying
+		of objects to work the size must be the memory footprint of the object itself. 
+
+OK_ 14. change new_xxxxx ctors which construct aliased etchobject, to syntax new_boxed_xxxxx().
+	    this is not pretty but it is descriptive of what is happening, which the current ctor
+	    names are not. DONE.
+
+___ 15. add __LINE, __FILE, to exception object ctor
+ 
+___ 16. consider moving impl* and impl_type to etchobject, meaning we could always 
+        call destroy_instancedata on the impl, and would no longer need to subclass
+        objects simply because they have instance data.
+ 
+___ 17. define default exceptions -- STARTED
+
+OK? 18. create startup hashtable of exceptions, augmentable at runtime.
+		this is likely NOT AN ISSUE, exceptions likely do not have to be looked up,
+		but rather are static.
+
+OK? 19. determine how we are going to hash using complex objects as keys.
+        we need to add hashtable functionality to supply hashkey in advance.
+        we could make this much easier but somewhat less efficient by doing a
+        lookup() first to get the key, storing the key, and then doing the insert.
+        the downside is that we would compute the hashkey twice. PARTLY DONE.
+        the only objects as keys are currently id_name and related. we hash these
+        by declaring object length 4, since the hash key is in first 4 bytes.
+        we'll put off the rest of this until we need to hash other object keys,
+        if indeed we do.
+
+N/A 20. consider do-over as raw com. DECIDED NO.
+
+OK_ 21. allow destroy hashtable to etch_free content configurably. currently it free's
+		meaning we can't etch_malloc content. possibly a system hashtable should free,
+		others should etch_free. see also 21.1. DONE by installable callback.
+		
+___ 21.1 change memtable to a system hashtable. lose is_memtable_instance.	
+        this means changing memtable code to use direct jenk calls	
+
+___ 22. include ref problems with id_name and typedef'ed derivatives. problem arises
+		from putting the wrapped object defs in with the native object defs, meaning
+		we have to include all the object headers and code, along with hash, etc.
+		Move this stuff out and into another file, but do this only after a clean
+		check-in, so we can easily back out the code if need be.
+
+OK_ 23. generalize structval catch/throw code so we can use it on all objects DONE
+
+___ 24. add code file and code line number to exceptions. need throw macros to do so.
+
+OK_ 25. unfubar code module file name caching - possibly use existing global cache hashed
+        by path name. DONE used global cache, adding code for text keys, and for key as value.
+        
+OK_ 26. add serial number to allocations. DONE   
+
+OK_ 27. standardize cloning of keys - currently sometimes caller clones, sometimes not, 
+        copy should be made at as low a level as possible to facilitate clean code. WON'T FIX
+        
+___ 28. change short_type calls to constant enums          
+
+___ 29. enumerate class IDs, change assignments accordingly
+
+___ 30. do an impl_mask inherited from obj_mask. why?
+
+OK_ 31. add synchronization to arraylist DONE
+
+OK_ 32. add synchronization to hashtable DONE
+
+OK_ 33. unit test for arraylist synchronization DONE
+
+___ 34. unit test for hashtable synchronization
+
+OK_ 35. fix bug in arraylist_remove DONE
+        see test_threadpool::test_synched_arraylist
+        
+OK_ 36. implement a global last_result in order to communicate exception from
+        methods with void returns. is_exception would also query last_result.
+         
+OK_ 37. add code to reference count objects. DONE but see (50) below.
+
+___ 38. unit test for reference counting of objects. also see (50) below.
+
+___ 39. replace non-portable unicode conversion with portable. this is a
+        significant task, possibly best to ifdef the operating system
+        and use OS facilities.
+
+OK_ 40. previously thought that hash value was dependent on encoding.
+        however scott informs that identifiers always ascii. they are unicode
+        in current code. need to change these accordingly. so change id_name.name
+        and similar. ALTERNATIVE: continue to maintain an 16-bit version of the
+        name, but add an 8-bit version as well, or convert on the fly. DONE.
+        implementation temporarily converts to 8-bit before computing id value.
+
+OK_ 41. change flexbuffer get methods to return a result code and accept a pointer
+        to a returned value. since we can't throw exception, and any returned value
+        can be valid, we need a separate result for these methods. also change all
+        spots in the code which call these gets. DONE
+        
+___ 42. convert dedicated global cache code to use generic etchmap code. only 
+        difference is passing the hashmap and possibly alpha key buffer to
+        methods. eliminates the one-off code but fixes nothing otherwise.   
+        
+___ 43. change nativearray to permit more dimensions than 3. possibly add a fourth
+        dimension to simple syntax. add additional nativearray APIs to permit
+        n dimensions, by passing arrays as parameters. 
+        
+OK_ 44. code another method similar to etchobj_assign_to(0) which returns the
+        object assigned to, or make etchobj_assign_to() return the address. 
+        we may need this if (a) we use the inheritance model where the child
+        points at its instantiated parent object, and (b) we do child = parent
+        assignments on those objects. DONE 
+        
+___ 45. Populate etch_arraylist's and etch_hashtable's etch_collection_mask items
+        content_obj_type and content_class_id.   
+
+___ 46. Mark all objects in collections as static, thus destroy() has no effect.
+        WTF: not sure why we want to do this. Perhaps this means support the
+        ability to do so. Of course we already can mark the collection as
+        having static content; however if we assign one collection to another
+        we can't do this since both shells would be marked static content.
+        So this todo is apparently to address this scenario.
+
+___ 47. Change etch_arraylist to permit etch_nativearray as backing store. Since
+        natarray get() always returns a newly instantiated object, and arraylist
+        get() always returns a non-disposable, we would need to resolve the
+        inconsistencies of access in some manner.                      
+        
+___ 48. string object needs a static method to ensure one encoding or the other,
+        as opposed to conversion methods which we have. this would return the
+        existing buffer if already in the desired encoding, otherwise convert it. 
+        For example void* etchstring_getvalue(etch_string* s, const int encoding);
+        or wchar_t* etchstring_get_wvalue(), char* etchstring_get_nvalue(); 
+        
+___ 50. add methods to etch_syncobj.h, .c, to atomically operate on an objmask*
+        refcount. change all destructors accordingly. we would probably use the
+        APR atomic method to do this, so no need for explicit lock in our code.
+        note that we need a global method to sync on increment refcount also,
+        which uses the same lock as decrement.
+
+___ 51. add logic to create a vtable without caching it, and use this logic in the
+        construction of objects that will only be instantiated once.
+        
+OK_ 52. do not serialize a string's null terminator, and add a null terminator when
+        deserializing a string.
+
+OK_ 53. convert to wire encoding from unicode when serializing strings, and convert
+        from wire encoding to unicode when deserializing strings.  
+        
+___ 54. make etch c date object work the same as java, i.e. a date should serialize
+        and deserialize to the same values as the java version.  
+        
+___ 55. implement an internal arrayvalue representation which does not require
+        individual items to be objectized. this specifically addresses the byte
+        array, where we can't continue to render each byte as an object.
+
+___ 56. implement custom validators.
+
+___ 57. plug in custom validator to examples value factories, e.g. xmpl_perf_valufact,
+        parameters for dist().
+
+___ 58. override set_session on all classes whose session interface is sessionmessage,
+        ala etch_transport.c in which we already did so.
+        
+___ 59. make the generated value factory static type and fields more consistent with
+        those of the default vf. if they can actually be static, that would be best.
+        
+___ 60. change early complex inheritance objects to be simpler, e.g., masked.
+        if they need obj.parent, change them. then get rid of unneeded object fields.        
+        
+___ 61. change various object parameters to constant, e.g. etch_event. 
+                           
+OK_ 62. determine if we can link all the generated but unedited files into a static lib.
+        there are only four editable .c files, leaving 17 loose .c and .h files on the
+        client and 16 on the server. many of these are shared by each side, so a common
+        lib would be useful and cleaner.  
+        
+___ 63. eliminate i_deliveryservice instantiation, instead embedding i_deliveryservice
+        as the first part of deliveryservice. i_deliveryservice then becomes a mask. 
+        
+___ 64. server hangs on shutdown if a client is still open. for example, if a long sleep
+        on the client prevents closing the connection, then server hangs and eventually
+        crashes when it attempts to clean up client sessions.                                    
\ No newline at end of file

Added: incubator/etch/trunk/binding-c/runtime/c/project/readmefirst.txt
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/project/readmefirst.txt?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/project/readmefirst.txt (added)
+++ incubator/etch/trunk/binding-c/runtime/c/project/readmefirst.txt Wed Apr 22 17:25:43 2009
@@ -0,0 +1,5 @@
+note that when starting an etch client or server from the debugger,
+the working directory is not the same as when started from the
+command line. when starting from the debugger, the config and log
+directories are here. when started from the command line they
+are relative to \etch\bindings\c\project"
\ No newline at end of file

Added: incubator/etch/trunk/binding-c/runtime/c/project/test/test-readme-first.txt
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/project/test/test-readme-first.txt?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/project/test/test-readme-first.txt (added)
+++ incubator/etch/trunk/binding-c/runtime/c/project/test/test-readme-first.txt Wed Apr 22 17:25:43 2009
@@ -0,0 +1,86 @@
+
+Configuring properties for a test project in visual studio
+=======================================================================================
+NOTE: also see "troubleshooting" section below.
+Make these changes to project/properties defaults:
+
+Environment Variables
+  APRPATH   must identify the directory in which the Apache Portable Runtime is installed.
+            At this writing this is C:\workspace\tools\apache-apr\apr-1-2-11
+  CUNITPATH must identify the directory in which Cunit is installed.
+            At this writing this is C:\workspace\tools\cunit\cunit-2.1-0
+
+Configuration Properties
+  C/C++
+
+    General
+      * Additional Include Directories:  
+         ..\..\..\inc;
+         ..\..\..\ext\hashtab;
+         $(APRPATH)\inc
+         $(CUNITPATH)\inc
+      * Debug Information Format: C7 Compatible (/Z7)
+        (to intergate debug info such that we can step into multiple libs)
+      * Treat Warnings as Errors: Yes (/WX)
+        (since MS C compiler "warnings" are frequently serious errors)
+        
+    Preprocessor 
+      * Preprocessor Definitions: add APR_DECLARE_STATIC to this list
+		for example, WIN32;_DEBUG;_CONSOLE; APR_DECLARE_STATIC
+        (targets the static APR library)
+
+    Code Generation
+      * Enable Minimal Rebuild: No
+        (must be off in order for /Z7 to take effect)
+      * Enable C++ Exceptions:  No
+
+    Precompiled Headers
+      * Create/User Precompiled Header: Not Using Precompiled Headers
+
+    Advanced
+      * Compile As: Compile as C Code (/TC)
+
+  Linker
+  
+    General
+      * Enable Incremental Linking: No (/INCREMENTAL:NO)  
+      
+    Additional Library Directories
+      ..\..\..\lib
+      ..\..\..\ext\lib
+      $(APRPATH)\lib
+      $(CUNITPATH)\lib\win32
+      
+    Input
+      * Additional Dependencies: 
+          libcunit.lib etch.lib jenkhash.lib apr-1.lib WS2_32.LIB Mswsock.lib       
+
+    Command Line
+      * Additional options: /NODEFAULTLIB:LIBCMTD
+
+
+Additional linker import libraries
+=======================================================================================
+We might have copied references to libraries into the "Resource Files" folder of a test
+project. Libs may include libcunit.lib, common.lib, message.lib. Contro/drag from a lib 
+folder, or from another test project. This should not be the case, all link libs should
+be specified in linker options, however there may be early projects with references
+specified in Resource Files.
+
+
+Linker warning notes:
+=======================================================================================
+
+Rebuilding a test project may elicit this linker warning
+  LNK4099: PDB 'vc80.pdb' was not found with '..\..\..\lib\common.lib' 
+
+However we are compiling libraries (common, message, etc) with compatibility mode (/Z7),
+which means we do not need .pdb files for debug information. The linker warning LNK4099
+apparently cannot be suppressed however. This warning notwithstanding, you can step   
+into or breakpoint the library code from any test.
+
+
+Troubleshooting:
+=======================================================================================
+1. Problem:  Link errors on APR symbols, and the test's .obj file has a "1" appended.
+   Solution: Ensure APR_DECLARE_STATIC is included in Preprocessor Definitions 
\ No newline at end of file

Added: incubator/etch/trunk/binding-c/runtime/c/project/test/test_allocator/test_allocator.vcproj
URL: http://svn.apache.org/viewvc/incubator/etch/trunk/binding-c/runtime/c/project/test/test_allocator/test_allocator.vcproj?rev=767594&view=auto
==============================================================================
--- incubator/etch/trunk/binding-c/runtime/c/project/test/test_allocator/test_allocator.vcproj (added)
+++ incubator/etch/trunk/binding-c/runtime/c/project/test/test_allocator/test_allocator.vcproj Wed Apr 22 17:25:43 2009
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="test_allocator"
+	ProjectGUID="{9D561956-7962-45B7-9DFE-E3A114534CC7}"
+	RootNamespace="test_allocator"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\..\inc;..\..\..\ext\hashtab;&quot;$(APRPATH)\inc&quot;;&quot;$(CUNITPATH)\inc&quot;"
+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;APR_DECLARE_STATIC"
+				MinimalRebuild="false"
+				ExceptionHandling="0"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				WarnAsError="true"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="1"
+				CompileAs="1"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalOptions="/NODEFAULTLIB:LIBCMTD&#x0D;&#x0A;"
+				AdditionalDependencies="libcunit.lib etch.lib jenkhash.lib apr-1.lib WS2_32.LIB "
+				LinkIncremental="1"
+				AdditionalLibraryDirectories="..\..\..\lib;..\..\..\ext\lib;&quot;$(APRPATH)\lib&quot;;&quot;$(CUNITPATH)\lib\win32&quot;"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+				RuntimeLibrary="2"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath="..\..\..\src\test\common\test_allocator.c"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+			<File
+				RelativePath="..\..\..\3rdparty\cunit-2.1-0\lib\win32\vc80_libcunit.pdb"
+				>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>