src/midgard_object_parameter.c

00001 /* 
00002  * Copyright (C) 2006 Piotr Pokora <piotr.pokora@infoglob.pl>
00003  *
00004  * This program is free software; you can redistribute it and/or modify it
00005  * under the terms of the GNU Lesser General Public License as published
00006  * by the Free Software Foundation; either version 2 of the License, or
00007  * (at your option) any later version.
00008  * 
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  * 
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017  */
00018 
00019 #include "midgard_core_object.h"
00020 #include "midgard/types.h"
00021 
00022 /* We do not use this hash table because of nature of 
00023  * Apache processes. Simply one request is not one process
00024  * so this global hash table should be moved to internal cache */
00025 /* GHashTable *objects_ptrs = NULL; */
00026 
00027 
00028 static MidgardCollector *__get_parameters_collector(MgdObject *object, 
00029                 const gchar *domain)
00030 {
00031         GHashTable *domains;
00032         const gchar *guid = object->private->guid;
00033         GQuark guidq = g_quark_from_string(guid);
00034         GQuark domainq = g_quark_from_string(domain);
00035         
00036         /* Initialize objects_ptrs hash , this is the first call 
00037          * to parameter method for any object */
00038         if(object->private->_params == NULL) {
00039                 object->private->_params = g_hash_table_new_full(NULL, NULL, 
00040                                 NULL, (GDestroyNotify) g_hash_table_destroy);
00041                 domains = g_hash_table_new(NULL, NULL);
00042                 g_hash_table_insert(domains, (gpointer)domainq, NULL);
00043                 g_hash_table_insert(object->private->_params, (gpointer)guidq, domains);
00044                 return NULL;
00045         }
00046 
00047         domains = g_hash_table_lookup(object->private->_params, (gpointer)guidq);
00048         /* Objects_ptrs hash is already initialized but particular 
00049          * object doesn't exist in hash */
00050         if(!domains) {
00051                 domains = g_hash_table_new(NULL, NULL);
00052                 g_hash_table_insert(domains, (gpointer)domainq, NULL);
00053                 g_hash_table_insert(object->private->_params, (gpointer)guidq, domains);
00054                 return NULL;
00055         }
00056 
00057         /* object already exists in hash , look for domain hash and return it. */
00058         return g_hash_table_lookup(domains, (gpointer)domainq);
00059 }
00060 
00061 static void __register_domain_collector(
00062                 MgdObject *object, const gchar *domain, MidgardCollector *mc)
00063 {
00064         const gchar *guid = object->private->guid;
00065         GQuark guidq = g_quark_from_string(guid);
00066         GQuark domainq = g_quark_from_string(domain);   
00067 
00068         GHashTable *domains = 
00069                 g_hash_table_lookup(object->private->_params, (gpointer)guidq);
00070 
00071         g_hash_table_insert(domains, (gpointer)domainq, mc);
00072 }
00073 
00074 static gboolean __is_guid_valid(MgdObject *self)
00075 {
00076         if(self->private->guid == NULL) {
00077 
00078                 midgard_set_error(self->mgd->_mgd,
00079                                 MGD_GENERIC_ERROR,
00080                                 MGD_ERR_INVALID_PROPERTY_VALUE,
00081                                 " Guid property is NULL for %s. ", 
00082                                 G_OBJECT_TYPE_NAME(self));
00083                 g_warning("%s", self->mgd->_mgd->err->message); 
00084                 g_clear_error(&self->mgd->_mgd->err);
00085                 return FALSE;
00086         }
00087 
00088         if(!midgard_is_guid(self->private->guid)) {
00089 
00090                 midgard_set_error(self->mgd->_mgd,
00091                                 MGD_GENERIC_ERROR,
00092                                 MGD_ERR_INVALID_PROPERTY_VALUE,
00093                                 " Guid property is invalid for %s. ", 
00094                                 G_OBJECT_TYPE_NAME(self));
00095                 g_warning("%s", self->mgd->_mgd->err->message);
00096                 g_clear_error(&self->mgd->_mgd->err);
00097                 return FALSE;
00098         }
00099 
00100         return TRUE;
00101 }
00102 
00103 const GValue *midgard_object_get_parameter(MgdObject *self,
00104                 const gchar *domain, const gchar *name)
00105 {
00106         g_assert(self);
00107 
00108         if(!__is_guid_valid(self))
00109                 return NULL;
00110 
00111         GValue *ret_value;
00112         MidgardCollector *domain_collector = 
00113                 __get_parameters_collector(self, domain);
00114 
00115         if(domain_collector == NULL){
00116                 
00117                 /* Initialize collector for object and its domain */
00118                 GValue *domain_value = g_new0(GValue, 1);
00119                 g_value_init(domain_value, G_TYPE_STRING);
00120                 g_value_set_string(domain_value, domain);
00121 
00122                 MidgardCollector *mc = 
00123                         midgard_collector_new(self->mgd->_mgd,
00124                                         "midgard_parameter",
00125                                         "domain", domain_value);
00126                 
00127                 /* FIXME, probably we should pass NULL as value argument
00128                  * and get *all* parameters */
00129                 midgard_collector_set_key_property(mc, 
00130                                 "name", NULL);
00131                 
00132                 /* Add value */
00133                 midgard_collector_add_value_property(mc, "value");
00134 
00135                 /* Limit records to these with parent guid */
00136                 GValue *guid_value = g_new0(GValue, 1);
00137                 g_value_init(guid_value, G_TYPE_STRING);
00138                 g_value_set_string(guid_value, self->private->guid);
00139         
00140                 midgard_collector_add_constraint(mc,
00141                                 "parentguid", "=", guid_value);
00142                 g_value_unset(guid_value);
00143 
00144                 midgard_collector_execute(mc);
00145                 
00146                 /* prepend collector to object's parameter list 
00147                  * we will free it in MgdObject destructor */
00148 
00149                 self->private->parameters = 
00150                         g_slist_prepend(self->private->parameters, mc);
00151 
00152                 ret_value = 
00153                         midgard_collector_get_subkey(mc, name, "value");
00154 
00155                 __register_domain_collector(self, domain, mc);
00156 
00157                 return (const GValue*)ret_value;
00158         
00159         } else {
00160                 
00161                 ret_value = 
00162                         midgard_collector_get_subkey(
00163                                         domain_collector, name, "value");
00164                 return (const GValue *)ret_value;
00165         }
00166 
00167         return NULL;
00168 }
00169 
00170 gboolean midgard_object_set_parameter(MgdObject *self,
00171                 const gchar *domain, const gchar *name,
00172                 GValue *value, gboolean lang) 
00173 {
00174 
00175         g_assert(self);
00176 
00177         if(!__is_guid_valid(self))
00178                 return FALSE;
00179                 
00180         MgdObject *param;
00181         const gchar *value_string =
00182                 g_value_get_string(value);
00183         gboolean delete_parameter = FALSE;
00184         gboolean do_return_true = FALSE;
00185 
00186         if(g_str_equal(value_string, ""))
00187                 delete_parameter = TRUE;
00188 
00189         const GValue *get_value = 
00190                 midgard_object_get_parameter(self,
00191                                 domain, name);
00192 
00193         MidgardCollector *domain_collector =
00194                 __get_parameters_collector(self, domain);
00195 
00196         /* This is the case when set_parameter is invoked
00197          * before any get_parameter */
00198         if(get_value == NULL && delete_parameter) {
00199                 MIDGARD_ERRNO_SET(self->mgd, MGD_ERR_NOT_EXISTS);
00200                 return FALSE;
00201         }
00202 
00203         /* Parameter doesn't exist. We have to create it */
00204         if(get_value == NULL && !delete_parameter){
00205                 
00206                 param = midgard_object_new(
00207                                 self->mgd, "midgard_parameter", NULL);
00208                 g_object_set(param, 
00209                                 "domain", domain, 
00210                                 "name", name,
00211                                 "parentguid", self->private->guid,
00212                                 NULL);
00213                 g_object_set_property(G_OBJECT(param), "value", value);
00214 
00215                 if(midgard_object_create(param)) {
00216                         
00217                         if(!midgard_collector_set(domain_collector,
00218                                                 name, "value", value)){
00219                                 g_warning("Failed to update parameter's cache"); 
00220                         }
00221                         g_object_unref(param);
00222                         return TRUE;
00223                 } else {
00224                         /* Error should be already set by create */
00225                         g_object_unref(param);
00226                         return FALSE;
00227                 }
00228 
00229         
00230                 /* Parameter exists. if value is '' we delete it.
00231                  * In any other case we update it */
00232         } else {
00233                 
00234                 MidgardQueryBuilder *builder = 
00235                         midgard_query_builder_new(self->mgd,
00236                                         "midgard_parameter");
00237                 GValue gval = {0,};
00238                 g_value_init(&gval, G_TYPE_STRING);
00239                 g_value_set_string(&gval, self->private->guid);
00240                 midgard_query_builder_add_constraint(builder,
00241                                 "parentguid", "=", &gval);
00242                 g_value_unset(&gval);
00243 
00244                 g_value_init(&gval, G_TYPE_STRING);
00245                 g_value_set_string(&gval, domain);
00246                 midgard_query_builder_add_constraint(builder,
00247                                 "domain", "=", &gval);
00248                 g_value_unset(&gval);
00249 
00250                 g_value_init(&gval, G_TYPE_STRING);
00251                 g_value_set_string(&gval, name);
00252                 midgard_query_builder_add_constraint(builder,
00253                                 "name", "=", &gval);
00254                 g_value_unset(&gval);
00255 
00256                 guint n_objects = 0;
00257                 GObject **ret_object =
00258                         midgard_query_builder_execute(
00259                                         builder, &n_objects);
00260         
00261                 g_object_unref(builder);
00262                 if(n_objects < 1){              
00263                         return FALSE;
00264                 }
00265 
00266                 if(delete_parameter){
00267 
00268                         if(midgard_object_delete(
00269                                                 MIDGARD_OBJECT(ret_object[0]))) {
00270                                 midgard_collector_remove_key(
00271                                                 domain_collector,
00272                                                 name);
00273                                 do_return_true = TRUE;                          
00274                         }
00275                         
00276                 } else {
00277                         
00278                         g_object_set(ret_object[0], "value", value_string, NULL);
00279                         if(midgard_object_update(
00280                                                 MIDGARD_OBJECT(ret_object[0]))) {
00281                                 midgard_collector_set(domain_collector,
00282                                                 name, "value", value);
00283                                 do_return_true = TRUE;
00284                         }
00285                 }
00286                 
00287                 g_object_unref(ret_object[0]);
00288                 g_free(ret_object);
00289                 if(do_return_true)
00290                         return TRUE;
00291 
00292         }
00293 
00294         return FALSE;
00295 }

Generated on Thu Feb 22 06:15:18 2007 for midgard-core by  doxygen 1.4.6