Ejemplo n.º 1
0
rt_private uint32 pst_store(struct rt_store_context *a_context, EIF_REFERENCE object, uint32 a_object_count)
{
	/* Second pass of the store mechanism: writing on the disk. */
	EIF_REFERENCE o_ref;
	EIF_REFERENCE o_ptr;
	long i, nb_references;
	union overhead *zone = HEADER(object);
	uint16 flags;
	int is_expanded, has_volatile_attributes = 0;
	EIF_BOOLEAN object_needs_index;
	long saved_file_pos = 0;
	long saved_object_count = a_object_count;

	REQUIRE ("valid need_index and make_index", (need_index && make_index) || (!need_index && !make_index));

	if (need_index) {
		object_needs_index = (EIF_BOOLEAN) ((EIF_BOOLEAN (*)(EIF_REFERENCE, EIF_REFERENCE))need_index)
			(server,object);
		if (object_needs_index) {
				/* If the object needs an index, the buffer is flushed so that
				 * a new compression header is stored just before the object
				 * thus the decompression will work when starting the retrieve
				 * there */
			a_context->flush_buffer_function();
			saved_file_pos = file_position + parsing_position;
		}
	} else {
		object_needs_index = 0;
	}


	flags = zone->ov_flags;
	is_expanded = eif_is_nested_expanded(flags);
	if (!(is_expanded || (flags & EO_STORE)))
		return a_object_count;		/* Unmarked means already stored */
	else if (!is_expanded)
		a_object_count++;
	
	zone->ov_flags &= ~EO_STORE;	/* Unmark it */

#ifdef DEBUG
	printf("object 0x%" EIF_POINTER_DISPLAY " [%s %" EIF_POINTER_DISPLAY "]\n", (rt_uint_ptr) object, System(zone->ov_dtype).cn_generator, (rt_uint_ptr) zone->ov_flags);
#endif
	/* Evaluation of the number of references of the object */
	if (flags & EO_SPEC) {					/* Special object */
		if (flags & EO_REF) {				/* Special of reference/composite types */
			EIF_INTEGER count, elem_size;
			EIF_REFERENCE ref;

			count = RT_SPECIAL_COUNT(object);
			if (flags & EO_TUPLE) {
				EIF_TYPED_VALUE * l_item = (EIF_TYPED_VALUE *) object;
					/* Don't forget that first element of TUPLE is the BOOLEAN
					 * `object_comparison' attribute. */
				l_item++;
				count--;
				for (; count > 0; count--, l_item++) {
					if (eif_is_reference_tuple_item(l_item)) {
						o_ref = eif_reference_tuple_item(l_item);
						if (o_ref) {
							a_object_count = pst_store (a_context, o_ref, a_object_count);
						}
					}
				}
			} else if (!(flags & EO_COMP)) {		/* Special of references */
				for (ref = object; count > 0; count--,
						ref = (EIF_REFERENCE) ((EIF_REFERENCE *) ref + 1)) {
					o_ref = *(EIF_REFERENCE *) ref;
					if (o_ref != (EIF_REFERENCE) 0)
						a_object_count = pst_store (a_context, o_ref,a_object_count);
				}
			} else {						/* Special of composites */
				elem_size = RT_SPECIAL_ELEM_SIZE(object);
				for (ref = object + OVERHEAD; count > 0;
					count --, ref += elem_size) {
					a_object_count = pst_store (a_context, ref,a_object_count);
				}
			}
		}
	} else {								/* Normal object */
		nb_references = References(zone->ov_dtype);

		/* Traversal of references of `object' */
		for (
			o_ptr = object, i = 0;
			i < nb_references;
			i++, o_ptr = (EIF_REFERENCE) (((EIF_REFERENCE *) o_ptr) +1)
		) {
			o_ref = *(EIF_REFERENCE *)o_ptr;
			if (o_ref) {
				if (!EIF_IS_TRANSIENT_ATTRIBUTE(System(zone->ov_dtype), i)) {
					a_object_count = pst_store (a_context, o_ref, a_object_count);
				} else {
					has_volatile_attributes = 1;
				}
			}
		}
	}

	if (!is_expanded) {
		a_context->object_write_function(object, has_volatile_attributes);		/* write the object */
	}

	/* Call `make_index' on `server' with `object' */
    if (object_needs_index) {
		(make_index)(server, object, saved_file_pos, a_object_count - saved_object_count);
	}

	return a_object_count;
}
Ejemplo n.º 2
0
rt_public EIF_BOOLEAN spiso(register EIF_REFERENCE target, register EIF_REFERENCE source)
{
	/* Compare two special objects in term of their structures. `source'
	 * and `target' are refering two special objects. There is three cases:
	 * 1- either the elements are direct instances: block comparison.
	 * 2- either the elements are references: comparison of referenced
	 *	dynamic type.
	 * 3- or the elements are expanded: call `eiso' (special objects
	 *	cannot be expanded).
	 */

	union overhead *s_zone;				/* Source header */
	uint32 s_flags;						/* Source flags */
	/*uint32 t_flags;*/					/* Target flags */
	EIF_REFERENCE s_ref;
	EIF_REFERENCE t_ref;
	EIF_INTEGER count;				/* Common count */
	EIF_INTEGER elem_size;			/* Common element size */
	EIF_REFERENCE s_field, t_field;

	REQUIRE("special objects", (HEADER(target)->ov_flags & EO_SPEC) && (HEADER(source)->ov_flags & EO_SPEC));

	if (source == target)
		return EIF_TRUE;

	s_zone = HEADER(source);

#ifdef DEBUG
	dprintf(2)("spiso: source = 0x%lx [%d] target = 0x%lx [%d]\n",
		source, RT_SPECIAL_COUNT(source),
		target, RT_SPECIAL_COUNT(target));
#endif

	count = RT_SPECIAL_COUNT(source);
	if (count != RT_SPECIAL_COUNT(target))
		return EIF_FALSE;

	/* Second condition: same element size */
	elem_size = RT_SPECIAL_ELEM_SIZE(source);
	if (elem_size != RT_SPECIAL_ELEM_SIZE(target))
		return EIF_FALSE;

	s_flags = s_zone->ov_flags;

		/* In final mode, we can do block comparison on special of basic types
		 * or on special of expanded which have no references since they have no header.
		 * In workbench mode, block comparison is only possible on special of basic types. */
#ifdef WORKBENCH
	if (!(s_flags & EO_REF) && !(s_flags & EO_COMP)) {
#else
	if (!(s_flags & EO_REF)) {
#endif
		/* Case 1: specials filled with direct instances: block comparison */
		return EIF_TEST(!memcmp (source, target, (rt_uint_ptr) count * (rt_uint_ptr) elem_size));
	}

	if (s_flags & EO_TUPLE) {
		EIF_TYPED_VALUE * l_source = (EIF_TYPED_VALUE *) source;
		EIF_TYPED_VALUE * l_target = (EIF_TYPED_VALUE *) target;
			/* Don't forget that first element of TUPLE is the BOOLEAN
			 * `object_comparison' attribute. */
		for (; count > 0; count--, l_source++, l_target++) {
			if
				(eif_is_reference_tuple_item(l_source) &&
				eif_is_reference_tuple_item(l_target))
			{
				s_field = eif_reference_tuple_item (l_source);
				t_field = eif_reference_tuple_item (l_target);
				if ((s_field == NULL) && (t_field == NULL)) {
					continue;
				} else if ((s_field) && (t_field) && (Dtype(s_field) == Dtype(t_field))) {
					continue;
				} else {
					return EIF_FALSE;
				}
			}
		}
		return EIF_TRUE;
	} else if ((s_flags & EO_REF) && !(s_flags & EO_COMP)) {
		/* Case 2: specials filled with references: we have to check fields
		 * one by one.
		 */
		for(
			s_ref = (EIF_REFERENCE)source, t_ref = (EIF_REFERENCE) target;
			count > 0;
			count --,
				s_ref = (EIF_REFERENCE) ((EIF_REFERENCE *) s_ref + 1),
				t_ref = (EIF_REFERENCE) ((EIF_REFERENCE *) t_ref + 1)
		) {
			/* Evaluation of two references */
			s_field = *(EIF_REFERENCE *) s_ref;
			t_field = *(EIF_REFERENCE *) t_ref;
			if ((!s_field) && (!t_field))
				/* Two void references */
				continue;
			else if (		(((EIF_REFERENCE) 0) != s_field) &&
							(((EIF_REFERENCE) 0) != t_field) &&
							(Dtype(s_field) == Dtype(t_field))
					)
				/* Two non-void references on objects of same dynamic type */
				continue;
			else
				/* No ismorphism */
				return EIF_FALSE;
		}
		return EIF_TRUE;
	}

	/* Case 3: special objects filled with (non-special) expanded objects.
	 * we call then standard isomorphism test on normal objects.
	 */
	for (
		s_ref = source +OVERHEAD, t_ref = target+OVERHEAD;
		count >0;
		count--, s_ref += elem_size, t_ref += elem_size
	) {
		/* Iteration on expanded elements */
		if (!eiso(t_ref, s_ref))
			return EIF_FALSE;
	}

	return EIF_TRUE;
}

rt_public EIF_BOOLEAN ediso(EIF_REFERENCE target, EIF_REFERENCE source)
{
	/* Compare recursively the structure attached to `target' to the
	 * one attached to `source'. This is the standard Eiffel feature
	 * because it called recursively the standard isomorhic Eiffel
	 * feature.
	 * Return a boolean.
	 */

	RT_GET_CONTEXT
	EIF_BOOLEAN result;
#ifdef ISE_GC
	char g_status;		/* Save GC status */

	g_status = eif_gc_ison();
	if (g_status)
		eif_gc_stop();						/* Stop GC if enabled*/
#endif

	eif_equality_table = s_create(100);				/* Create search table */
	result = rdeepiso(target,source);	/* Recursive isomorphism test */

#ifdef ISE_GC
	if (g_status)
		eif_gc_run();						/* Enabled GC it was previously enabled */
#endif

	eif_rt_xfree((EIF_REFERENCE) (eif_equality_table->s_keys));	/* Free search table keys */
	eif_rt_xfree((EIF_REFERENCE) eif_equality_table);			/* Free search table descriptor */
	eif_equality_table = NULL;
	return result;
}
Ejemplo n.º 3
0
rt_private EIF_BOOLEAN rdeepiso(EIF_REFERENCE target,EIF_REFERENCE source)
{
	/* Recursive isomorphism test.
	 * Return a boolean.
	 */

	RT_GET_CONTEXT
	union overhead *zone = HEADER(target);	/* Target header */
	uint32 flags;							/* Target flags */
	EIF_REFERENCE s_ref, t_ref, t_field, s_field;
	EIF_INTEGER count, elem_size;

	flags = zone->ov_flags;

	/* Check if the object has already been inspected */
	if (s_put(eif_equality_table, target) == EIF_SEARCH_CONFLICT)
		return EIF_TRUE;

	/* Isomorphism test between `source' and `target'.
	 * Two cases: either a normal object or a special object.
	 */
	if (flags & EO_SPEC) {
		/* Special or tuple objects */
		if (!spiso(target, source))
			return EIF_FALSE;

		if (!(flags & EO_REF))
			/* No reference to inspect */
			return EIF_TRUE;

		/* Evaluation of the count of the target special object */
		count = RT_SPECIAL_COUNT(target);

		if (flags & EO_TUPLE) {
			EIF_TYPED_VALUE * l_source = (EIF_TYPED_VALUE *) source;
			EIF_TYPED_VALUE * l_target = (EIF_TYPED_VALUE *) target;
				/* Don't forget that first element of TUPLE is the BOOLEAN
				 * `object_comparison' attribute. */
			for (; count > 0; count--, l_source++, l_target++) {
				if
					(eif_is_reference_tuple_item(l_source) &&
					eif_is_reference_tuple_item(l_target))
				{
					s_field = eif_reference_tuple_item (l_source);
					t_field = eif_reference_tuple_item (l_target);
					if ((s_field == NULL) && (t_field == NULL)) {
						continue;
					} else if ((s_field) && (t_field)) {
						if (!rdeepiso(t_field, s_field)) {
							return EIF_FALSE;
						}
					} else {
						return EIF_FALSE;
					}
				}
			}
			return EIF_TRUE;
		} else if (!(flags & EO_COMP)) {
			CHECK("Special of reference", flags & EO_REF);
			/* Specials filled with references: we have to iterate on fields
			* two by two.
			*/
			/* Evaluation of the count of the target special object */
			for(
				s_ref = (EIF_REFERENCE)source, t_ref = (EIF_REFERENCE) target;
				count > 0;
				count --,
					s_ref = (EIF_REFERENCE) ((EIF_REFERENCE *) s_ref + 1),
					t_ref = (EIF_REFERENCE) ((EIF_REFERENCE *) t_ref + 1)
			) {
				/* Evaluation of two references */
				s_field = *(EIF_REFERENCE *) s_ref;
				t_field = *(EIF_REFERENCE *) t_ref;
				if ((((EIF_REFERENCE) 0) == s_field) && (((EIF_REFERENCE) 0) == t_field))
					/* Two void references */
					continue;
				else if ((EIF_REFERENCE) 0 != s_field && (EIF_REFERENCE) 0 != t_field) {
					/* Recursion on references of the special object */
					if (!rdeepiso(t_field, s_field))
						return EIF_FALSE;
				} else
					return EIF_FALSE;
			}
			return EIF_TRUE;
		} else {
			CHECK("Special of expanded with references", flags & EO_REF);
			/* Special objects filled with (non-special) expanded objects.
			 * we call then standard isomorphism test on normal objects.
			 */
			elem_size = RT_SPECIAL_ELEM_SIZE(target);
			for (
				s_ref = source+OVERHEAD, t_ref = target+OVERHEAD;
				count > 0;
				count--, s_ref += elem_size, t_ref += elem_size
			) {
				/* Iteration on expanded elements which cannot be special
				 * objects
				 */
				if (!(rdeepiter(t_ref, s_ref)))
					return EIF_FALSE;
			}
			return EIF_TRUE;
		}
	} else {
		/* Normal object */
		if (!eiso(target, source))
			return EIF_FALSE;

		/* Iteration on references */
		return rdeepiter(target, source);
	}
	/* NOTREACHED */
	return EIF_FALSE;
}
Ejemplo n.º 4
0
rt_private void rdeepclone (EIF_REFERENCE source, EIF_REFERENCE enclosing, rt_uint_ptr offset)
/* Source object to be cloned */
/* Object receiving clone */
/* Offset within enclosing where attachment is made */
{
    /* Recursive deep clone of `source' is attached to `receiver'. Then
     * enclosing parameter gives us a pointer to where the address of the
     * currently built object lies, or in other words, it's the object on
     * which we are currently recurring. That way, we are able to perform aging
     * tests when the attachment to the receiving reference is done.
     */

    RT_GET_CONTEXT
    EIF_REFERENCE clone, c_field;
    uint16 flags;
    EIF_INTEGER count, elem_size;

    REQUIRE("source not null", source);
    REQUIRE("enclosing not null", enclosing);

    flags = HEADER(source)->ov_flags;

    if (!(flags & EO_STORE)) {		/* Object has already been cloned */

        /* Object is no longer marked: it has already been duplicated and
         * thus the resulting duplication is in the hash table.
         */

        clone = *hash_search(&hclone, source);
        *(EIF_REFERENCE *) (enclosing + offset) = clone;
        CHECK ("Not forwarded", !(HEADER (enclosing)->ov_size & B_FWD));
        RTAR(enclosing, clone);
        return;
    }

    /* The object has not already been duplicated */

    flags &= ~EO_STORE;						/* Unmark the object */
    HEADER(source)->ov_flags = flags;		/* Resynchronize object flags */
    clone = duplicate(source, enclosing, offset);	/* Duplicate object */

    /* The object has now been duplicated and entered in the H table */

    if (flags & EO_SPEC) {					/* Special object */
        if (!(flags & EO_REF)) {				/* No references */
            return;
        }
        count = RT_SPECIAL_COUNT(clone);			/* Number of items in special */

        /* If object is filled up with references, loop over it and recursively
         * deep clone them. If the object has expanded objects, then we need
         * to update their possible intra expanded fields (in case they
         * themselves have expanded objects) and also to deep clone them.
         */

        if (flags & EO_TUPLE) {
            EIF_TYPED_VALUE * l_target = (EIF_TYPED_VALUE *) clone;
            EIF_TYPED_VALUE * l_source = (EIF_TYPED_VALUE *) source;
            /* Don't forget that first element of TUPLE is the BOOLEAN
             * `object_comparison' attribute. */
            for (offset = 0; count > 0; count--, l_target++, l_source++, offset +=sizeof(EIF_TYPED_VALUE)) {
                if (eif_is_reference_tuple_item(l_source)) {
                    c_field = eif_reference_tuple_item(l_target);
                    if (c_field) {
                        rdeepclone(c_field, clone, offset);
                    }
                }
            }
        } else if (!(flags & EO_COMP))	{	/* Special object filled with references */
            for (offset = 0; count > 0; count--, offset += REFSIZ) {
                c_field = *(EIF_REFERENCE *) (clone + offset);
                /* Iteration on non void references and Eiffel references */
                if (c_field) {
                    rdeepclone(c_field, clone, offset);
                }
            }
        } else {					/* Special filled with expanded objects */
            elem_size = RT_SPECIAL_ELEM_SIZE(clone);
            for (offset = OVERHEAD; count > 0; count--, offset += elem_size)
                expanded_update(source, clone + offset, DEEP);
        }

    } else
        expanded_update(source, clone, DEEP); /* Update intra expanded refs */
}