Пример #1
0
static PHP_METHOD(midgard_query_builder, include_deleted)
{
	MidgardConnection *mgd = mgd_handle(TSRMLS_C);
	CHECK_MGD(mgd);

	RETVAL_FALSE;

	if (zend_parse_parameters_none() == FAILURE)
		return;

	_GET_BUILDER_OBJECT;

	midgard_query_builder_include_deleted(builder);

	RETURN_TRUE;
}
Пример #2
0
/**
 * midgard_replicator_import_object:
 * @object: #MidgardDBObject instance
 * @force: toggle to force import
 *
 * Imports given object to underlying storage
 *
 * Cases to return %FALSE:
 * <itemizedlist>
 * <listitem><para>
 * Given guid is NULL or empty string (MGD_ERR_INVALID_PROPERTY_VALUE)
 * </para></listitem>
 * <listitem><para>
 * Object is already imported (MGD_ERR_OBJECT_IMPORTED)
 * </para></listitem>
 * <listitem><para>
 * Object identified is deleted (MGD_ERR_OBJECT_DELETED)
 * </para></listitem>
 * <listitem><para>
 * Object doesn't provide metadata one (MGD_ERR_NO_METADATA)
 * </para></listitem>
 * </itemizedlist>
 *
 * Set @force toggle if you want to import object even if it's already imported or deleted.
 *
 * Returns: %TRUE on success, %FALSE otherwise
 */ 
gboolean 
midgard_replicator_import_object (MidgardDBObject *object, gboolean force)
{	
	MidgardConnection *mgd = MGD_OBJECT_CNC (object);
	const gchar *guid = MGD_OBJECT_GUID (object);

	g_return_val_if_fail (mgd != NULL, FALSE);
	g_return_val_if_fail (g_type_is_a (G_OBJECT_TYPE (object), MIDGARD_TYPE_DBOBJECT), FALSE);

	MIDGARD_ERRNO_SET(object->dbpriv->mgd, MGD_ERR_OK);
	gboolean ret_val = FALSE;

	if (guid == NULL || (guid && *guid == '\0')) {		
		MIDGARD_ERRNO_SET_STRING (mgd, MGD_ERR_INVALID_PROPERTY_VALUE, "NULL or empty guid");
		return ret_val;
	}

	MidgardMetadata *dbmetadata = NULL;
	MidgardMetadata *metadata = MGD_DBOBJECT_METADATA (object);
	if (!metadata) {
		MIDGARD_ERRNO_SET_STRING (mgd, MGD_ERR_NO_METADATA, "Metadata class not available.");
		return ret_val;
	}

	g_signal_emit(object, MIDGARD_OBJECT_GET_CLASS(object)->signal_action_import, 0);

	/* Get object from database */
	MidgardQueryBuilder *builder = midgard_query_builder_new(mgd, G_OBJECT_TYPE_NAME(object));
	if(!builder)
		return FALSE;

	GValue pval = {0, };
	/* Add guid constraint */
	g_value_init(&pval,G_TYPE_STRING);
	g_object_get_property(G_OBJECT(object), "guid", &pval);
	midgard_query_builder_add_constraint(builder, "guid", "=", &pval);
	g_value_unset(&pval);
	
	/* Get db object which is "elder" than imported one */
	/*
	g_value_init(&pval,G_TYPE_STRING);
	g_object_get_property(G_OBJECT(object->metadata), "revised", &pval);
	midgard_query_builder_add_constraint(builder, 
			"metadata.revised", "<", &pval);
	g_value_unset(&pval);
	*/

	/* Get deleted or undeleted object */
	midgard_query_builder_include_deleted (builder);

	guint n_objects;
	GObject **_dbobjects = midgard_query_builder_execute (builder, &n_objects);
	MidgardObject *dbobject;

	if (!_dbobjects){
	
		g_object_unref (G_OBJECT (builder));
		
		if ((mgd->errnum == MGD_ERR_OBJECT_PURGED) && force) {

			/* we need to delete repligard entry here 
			 * In any other case we need to change core's API a bit
			 * and make create method more complicated with 
			 * additional needless cases */

			GString *sql = g_string_new ("DELETE from repligard WHERE ");
			g_string_append_printf (sql,
					"typename = '%s' AND guid = '%s' ",
					G_OBJECT_TYPE_NAME (object),
					MGD_OBJECT_GUID (object));
			midgard_core_query_execute (MGD_OBJECT_CNC (object), sql->str, TRUE);
			g_string_free (sql, TRUE);
			
			ret_val =  _midgard_object_create (MIDGARD_OBJECT (object), MGD_OBJECT_GUID (object), OBJECT_UPDATE_IMPORTED);		
			return ret_val;
		}

		if (mgd->errnum == MGD_ERR_NOT_EXISTS || mgd->errnum == MGD_ERR_OK) {

			ret_val =  _midgard_object_create (MIDGARD_OBJECT(object), MGD_OBJECT_GUID(object), OBJECT_UPDATE_IMPORTED);
			return ret_val;
		}

	} else {

		gchar *updated, *dbupdated;
		dbobject = (MidgardObject *)_dbobjects[0];
		g_free (_dbobjects);

		GValue updated_timestamp = {0, };
		g_value_init (&updated_timestamp, MGD_TYPE_TIMESTAMP);
		GValue dbupdated_timestamp = {0, };
		g_value_init (&dbupdated_timestamp, MGD_TYPE_TIMESTAMP);
		
		metadata = MGD_DBOBJECT_METADATA (object);
		dbmetadata = MGD_DBOBJECT_METADATA (dbobject);

		/* Compare revised datetimes. We must know if imported 
		 * object is newer than that one which exists in database */
		g_object_get_property (G_OBJECT (metadata), "revised", &updated_timestamp);
		g_object_get_property (G_OBJECT (dbmetadata), "revised", &dbupdated_timestamp);

		updated = midgard_timestamp_get_string_from_value ((const GValue *)&updated_timestamp);
		dbupdated = midgard_timestamp_get_string_from_value ((const GValue *)&dbupdated_timestamp);

		g_value_unset (&updated_timestamp);
		g_value_unset (&dbupdated_timestamp);

		/* We can use g_ascii_strcasecmp as it type cast every single 
		 * pointer to integer and unsigned char returning substract result */		
		gint datecmp;
	
	     	if (updated == NULL) {

			g_warning ("Trying to import ivalid object. metadata.revised property holds NULL (Object: %s)", 
					MGD_OBJECT_GUID (object));

			if (dbupdated)
				g_free (dbupdated);

			g_object_unref (dbobject);

			return FALSE;
		}

		if (dbupdated == NULL) {

			g_warning ("Trying to import object for invalid object stored in database. metadata.revised property holds NULL (Database object:%s)", MGD_OBJECT_GUID (object));

			if (updated)
				g_free (updated);

			g_object_unref (dbobject);

			return FALSE;
		}

		if (force) {

			datecmp = -1;
		
		} else {
			
			datecmp = g_ascii_strcasecmp ((const gchar *)dbupdated, (const gchar *)updated);
		}

		g_free(updated);
		g_free(dbupdated);

		gboolean deleted;
		gboolean ret;

		if (datecmp > 0 || datecmp == 0) {
			
			/* Database object is more recent or exactly the same */	
			g_object_unref (dbobject);	
			MIDGARD_ERRNO_SET (mgd, MGD_ERR_OBJECT_IMPORTED);
	
			return FALSE;

		} else if (datecmp < 0) {
			
			/* Database object is elder */	
			
			/* DELETE */
			g_object_get (G_OBJECT (metadata), "deleted", &deleted, NULL);
			/* Imported object is marked as deleted , so 
			 * * we delete object from database */
			if (deleted) {

				ret = midgard_object_delete (dbobject, FALSE);
				g_object_unref (dbobject);
				return ret;
			}

			/* UPDATE */
		
			MidgardMetadata *db_metadata = MGD_DBOBJECT_METADATA (dbobject);

			/* Check if dbobject is deleted */
			g_object_get (db_metadata, "deleted", &deleted, NULL);

			guint undelete;
			g_object_get (G_OBJECT (metadata), "deleted", &undelete, NULL);

			if ((deleted && !undelete)) {
				midgard_schema_object_factory_object_undelete (mgd, MGD_OBJECT_GUID (dbobject));
				goto _update_object;
			}

			if (deleted && !force) {
				
				MIDGARD_ERRNO_SET (mgd, MGD_ERR_OBJECT_DELETED);
				g_object_unref (dbobject);
				return FALSE;
			}

			_update_object:
			ret = _midgard_object_update (MIDGARD_OBJECT (object), OBJECT_UPDATE_IMPORTED, NULL);
			g_object_unref (dbobject);
			return ret;
		}		
	}

	return FALSE;
}