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;"$(APRPATH)\inc";"$(CUNITPATH)\inc""
+ 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
"
+ AdditionalDependencies="libcunit.lib etch.lib jenkhash.lib apr-1.lib WS2_32.LIB "
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="..\..\..\lib;..\..\..\ext\lib;"$(APRPATH)\lib";"$(CUNITPATH)\lib\win32""
+ 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>