rev 397 - in trunk: include/prothon modules/Prosist src

SVN User <[email protected]> Tue, 20 Apr 2004 20:13:27 -0400
Newsgroups gmane.comp.lang.prothon.cvs
Message-ID <[email protected]>
Author: mark
Date: 2004-04-20 20:13:24 -0400 (Tue, 20 Apr 2004)
New Revision: 397

Modified:
   trunk/include/prothon/prothon.h
   trunk/include/prothon/prothon_dll.h
   trunk/modules/Prosist/Prosist.c
   trunk/src/builtins-list.c
   trunk/src/object.c
Log:
more work on prosist, added list_item_set

Modified: trunk/include/prothon/prothon.h
===================================================================
--- trunk/include/prothon/prothon.h	2004-04-19 21:12:55 UTC (rev 396)
+++ trunk/include/prothon/prothon.h	2004-04-21 00:13:24 UTC (rev 397)
@@ -633,6 +633,9 @@
 // LIST_ITEM: Access object i from list
 obj_p list_item(isp ist, obj_p list, int i);
 
+// LIST_ITEM_SET: Set object i in list
+void list_item_set(isp ist, obj_p list, int i, obj_p new_item);
+
 // LISTn: Convenience list create functions
 // list1, list2, ... are convenience functions that allow you to create
 // new list objects that contain 1 to 8 item objects.
@@ -1063,6 +1066,17 @@
 void clr_unclonable(obj_p obj);
 int   is_unclonable(obj_p obj);
 
+//************************** ARCHIVED BIT ***********************************
+// Each object has a bit called archived.  This bit tells whether an object has
+// been write-locked (modified) since the last time it was stored via whatever
+// perstistance storage system is controlling this bit, such as prosist.  The
+// interpreter sets this bit to false when the object is created and when the
+// object is write locked and never sets it to true.  The persistence application
+// is responsbile for maintaining this bit otherwise.
+void set_archived(obj_p obj);		
+void clr_archived(obj_p obj);
+int   is_archived(obj_p obj);
+
 //************************** DELETE LOCKING ***********************************
 // The garbage collection process in the memory manager will delete any object
 // that isn't recursively contained in the root globals container.  This means

Modified: trunk/include/prothon/prothon_dll.h
===================================================================
--- trunk/include/prothon/prothon_dll.h	2004-04-19 21:12:55 UTC (rev 396)
+++ trunk/include/prothon/prothon_dll.h	2004-04-21 00:13:24 UTC (rev 397)
@@ -76,6 +76,7 @@
 	void		(*switch_proto)(isp ist, obj_p obj, obj_p new_proto);
 	obj_p		(*list_append)(isp ist, obj_p list_obj, obj_p item);
 	obj_p		(*list_item)(isp ist, obj_p list, int i);
+	void		(*list_item_set)(isp ist, obj_p list_obj, int i, obj_p new_item);
 	size_t		(*list_len)(isp ist, obj_p list);
 	void		(*list_clear)(isp ist, obj_p list_obj);
 	obj_p		(*list1)(isp ist, obj_p p1);
@@ -131,6 +132,9 @@
 	void		  (*del_unlock)(obj_p obj);	
 	void	   (*set_immutable)(obj_p obj);		
 	void	   (*clr_immutable)(obj_p obj);
+	void		(*set_archived)(obj_p obj);		
+	void		(*clr_archived)(obj_p obj);
+	int          (*is_archived)(obj_p obj);
 
 	void		(*set_obj_rdacc)(obj_p obj, int access);
 	void		(*set_obj_wracc)(obj_p obj, int access);
@@ -229,6 +233,7 @@
 #define switch_proto		(*services->switch_proto)
 #define list_append			(*services->list_append)
 #define list_item			(*services->list_item)
+#define list_item_set		(*services->list_item_set)
 #define list_len			(*services->list_len)
 #define list_clear			(*services->list_clear)
 #define new_hash_obj		(*services->new_hash_obj)
@@ -285,6 +290,9 @@
 #define new_dict_obj	 	(*services->new_dict_obj)	 
 #define proto_len		 	(*services->proto_len)		 
 #define proto_item		 	(*services->proto_item)		 
+#define set_archived	 	(*services->set_archived)
+#define clr_archived	 	(*services->clr_archived)
+#define is_archived	 		(*services->is_archived)
 
 #endif // OBJECT_H
 

Modified: trunk/modules/Prosist/Prosist.c
===================================================================
--- trunk/modules/Prosist/Prosist.c	2004-04-19 21:12:55 UTC (rev 396)
+++ trunk/modules/Prosist/Prosist.c	2004-04-21 00:13:24 UTC (rev 397)
@@ -70,6 +70,7 @@
 	obj_p		idobj_to_id;
 	obj_p		id_to_obj;
 	obj_p		obj_to_id;
+	obj_p		proxies;
 } dbrec_t;
 
 typedef dbrec_t* dbrec_p;
@@ -114,14 +115,18 @@
 
 #define ADD_REF(obj) ADD_NUM(obj_to_id_f(ist, dbrecp, (obj)))
 
+
+//******************************** load_dbm_int *******************************
 i32_t load_dbm_int(char* key) {
 	return 0;
 }
 
+//******************************** store_dbm_int ******************************
 void store_dbm_int(char* key, i32_t val) {
 
 }
 
+//******************************** obj_to_id_f ********************************
 i32_t obj_to_id_f(isp ist, dbrec_p dbrecp, obj_p obj) {
 	obj_p id_obj = dict_item(ist, dbrecp->obj_to_id, obj);
 	if (!id_obj) {
@@ -132,6 +137,19 @@
 	return (int) id_obj->data.i64;
 }
 
+//******************************** obj_registered_QUES ************************
+int obj_registered_QUES(isp ist, dbrec_p dbrecp, obj_p obj) {
+	obj_p id_obj = dict_item(ist, dbrecp->obj_to_id, obj);
+	if (!id_obj) {
+		id_obj = NEW_INT(dbrecp->nextid++);
+		dict_add(ist, dbrecp->obj_to_id, obj, id_obj);
+		dict_add(ist, dbrecp->id_to_obj, id_obj, obj);
+		return FALSE;
+	}
+	return TRUE;
+}
+
+//******************************** obj_to_datum *******************************
 apr_datum_t obj_to_datum(isp ist, dbrec_p dbrecp, obj_p obj) {
 	obj_p id_tuple, proxy_obj;
 	int bad_proxy = FALSE;
@@ -223,6 +241,19 @@
 	return datum;
 }
 
+//******************************** commit *************************************
+void commit(ist, dbrecp) {
+/*
+	root_datum = obj_to_datum(ist, dbrecp, dbrecp->root); if_exc_return;
+	if (!root_datum.dptr) {
+		raise_exception(ist, ProsistExc_OBJ, "root object is not storable");
+		return;
+	}
+	aprerr = apr_dbm_store(dbrecp->db, apr_str("0"), root_datum);
+	IF_APR_DBM_ERR(dbrecp->db, "storing root object") return;
+*/
+}
+
 //******************************** apr_str ************************************
 apr_datum_t apr_str(char* str){
 	apr_datum_t apr_str;
@@ -236,22 +267,105 @@
 	return NULL;
 }
 
+//******************************** unlock_list ********************************
+void unlock_list(isp ist, obj_p olst) {
+	int i, llen = (int) list_len(ist, olst);
+	for(i=0; i < llen; i++) {					
+		obj_p item = list_item(ist, olst, i);		
+		if (item != OBJ(NONE))					
+			read_unlock(ist, item);				
+	}											
+	del_unlock(olst);
+}
 
-//******************************** store_object *******************************
-void store_object(isp ist, dbrec_p dbrecp) {
-	apr_status_t aprerr;
-	apr_datum_t  root_datum;
+//******************************** rdlock_append ******************************
+int rdlock_append(isp ist, dbrec_p dbrecp, obj_p olst, obj_p obj) {
+	if_rdlock(obj) {								
+		unlock_list(ist, olst);
+		return TRUE;
+	}
+	if (is_unclonable(obj) || obj_registered_QUES(ist, dbrecp, obj))
+		return FALSE;
+
+	list_append(ist, olst, obj);
+	return FALSE;
+}
+
+//******************************** add_locked_objs ****************************
+void add_locked_objs(isp ist, dbrec_p dbrecp, int *loidx, obj_p locked_objs) {
+	obj_p id_tuple, proxy_obj;
+	int i, idx=0, plen, tuple_type=FALSE;
+	obj_p obj = list_item(ist, locked_objs, *loidx);
+	
+	if (id_tuple = get_attr(ist, obj, SYM(__ID__))) {
+		dict_add(ist, dbrecp->id_to_idobj, id_tuple, obj);
+		dict_add(ist, dbrecp->idobj_to_id, obj, id_tuple);
+		(*loidx)++;
+		return;
+	}
+	proxy_obj = call_func0(ist, obj, SYM(__TOSTORPROXY__));
+	if (ist->exception_obj) { unlock_list(ist, locked_objs); return; }
+	
+	if (proxy_obj == OBJ(NONE) || is_unclonable(proxy_obj)) { 
+		del_unlock(proxy_obj); 
+		read_unlock(ist, obj);
+		list_item_set(ist, locked_objs, *loidx, OBJ(NONE));
+		(*loidx)++;
+		return;
+	}
+	if (proxy_obj->data_type == DATA_TYPE_DATAPTR) {
+		tuple_type = has_proto_QUES(ist, proxy_obj, OBJ(TUPLE_PROTO));
+		if (!tuple_type && !has_proto_QUES(ist, proxy_obj, OBJ(STRING_PROTO))) {
+			raise_exception(ist, ProsistExc_OBJ, "unstorable object (data ptr) found in tree");
+			unlock_list(ist, locked_objs); 
+			return;
+		}
+	}
+	dict_add(ist, dbrecp->proxies, obj, proxy_obj);
+	(*loidx)++;
+
+	plen = proto_len(ist, proxy_obj);
+	for(i=0; i < plen; i++) {
+		obj_p proto = proto_item(ist, proxy_obj, i);
+		if (rdlock_append(ist, dbrecp, locked_objs, proto)) return;
+	}
+	if (proxy_obj->has_attrs) {
+		attr_key_t key = attr_first_key(ist, proxy_obj);
+		while(key) {
+			obj_p attr = attr_value_by_key(ist, proxy_obj, key);
+			if (rdlock_append(ist, dbrecp, locked_objs, attr)) return;
+			key = attr_next_key(ist, proxy_obj, key);
+		}
+	}
+	if (tuple_type) {
+		int llen = (int) list_len(ist, proxy_obj);
+		for (i=0; i < llen; i++) {
+			obj_p item = list_item(ist, proxy_obj, i);
+			if (rdlock_append(ist, dbrecp, locked_objs, item)) return;
+		}
+	}
+}
+
+//******************************** store_new_db *******************************
+void store_new_db(isp ist, dbrec_p dbrecp) {
+	obj_p locked_objs;
+	int idx = 0;
 	if (apr_dbm_exists(dbrecp->db, apr_str("0"))) {
 		raise_exception(ist, ProsistExc_OBJ, "Database already exists");
 		return;
 	}
-	root_datum = obj_to_datum(ist, dbrecp, dbrecp->root); if_exc_return;
-	if (!root_datum.dptr) {
+	if (is_unclonable(dbrecp->root)){
 		raise_exception(ist, ProsistExc_OBJ, "root object is not storable");
 		return;
 	}
-	aprerr = apr_dbm_store(dbrecp->db, apr_str("0"), root_datum);
-	IF_APR_DBM_ERR(dbrecp->db, "storing root object") return;
+	// use ist->lockstack for this?
+	locked_objs = new_list_obj(ist, 20); 
+	if (rdlock_append(ist, dbrecp, locked_objs, dbrecp->root)) return;
+	while (idx < (int) list_len(ist, locked_objs)) {
+		add_locked_objs(ist, dbrecp, &idx, locked_objs);
+		if_exc_return;
+	}
+	commit(ist, dbrecp);
 }
 
 
@@ -328,14 +442,15 @@
 	dbrecp->idobj_to_id = NEW_DICT(4*INITIAL_OBJ_COUNT);
 	dbrecp->id_to_obj   = NEW_DICT(4*INITIAL_OBJ_COUNT);
 	dbrecp->obj_to_id   = NEW_DICT(4*INITIAL_OBJ_COUNT);
+	dbrecp->proxies     = NEW_DICT(4*INITIAL_OBJ_COUNT);
 
 	if (root_obj == OBJ(NONE)) {
 		dbrecp->nextid = load_dbm_int("!nextid");
 		dbrecp->root   = load_object(ist, dbrecp);  
 	} else {
 		dbrecp->root   = root_obj;
-		dbrecp->nextid = 1;
-		store_object(ist, dbrecp);  
+		dbrecp->nextid = 0;
+		store_new_db(ist, dbrecp);  if_exc_return NULL; 
 		store_dbm_int("!nextid", dbrecp->nextid);
 	}
 	return OBJ(NONE);

Modified: trunk/src/builtins-list.c
===================================================================
--- trunk/src/builtins-list.c	2004-04-19 21:12:55 UTC (rev 396)
+++ trunk/src/builtins-list.c	2004-04-21 00:13:24 UTC (rev 397)
@@ -136,6 +136,13 @@
 	return res;
 }
 
+//********************************* list_item_set *****************************
+void list_item_set(isp ist, obj_p list_obj, int i, obj_p new_item){
+	wrlock_rtrn(list_obj);
+	listitem(list_obj, i) = new_item;
+	write_unlock(ist, list_obj);
+}
+
 //********************************* list_append *******************************
 obj_p list_append(isp ist, obj_p list_obj, obj_p item){
 	list_p lstp;

Modified: trunk/src/object.c
===================================================================
--- trunk/src/object.c	2004-04-19 21:12:55 UTC (rev 396)
+++ trunk/src/object.c	2004-04-21 00:13:24 UTC (rev 397)
@@ -133,6 +133,7 @@
 	dll_services.switch_proto  = switch_proto;
 	dll_services.list_append	  = list_append;
 	dll_services.list_item		  = list_item;	
+	dll_services.list_item_set	  = list_item_set;	
 	dll_services.list_len		  = list_len;
 	dll_services.list_clear		  = list_clear;
 	dll_services.new_hash_obj	  = new_hash_obj;	
@@ -172,6 +173,9 @@
 	dll_services.del_unlock	      = del_unlock;
 	dll_services.set_immutable	  = set_immutable;
 	dll_services.clr_immutable	  = clr_immutable;
+	dll_services.set_archived     = set_archived;  
+	dll_services.clr_archived	  = clr_archived;	
+	dll_services.is_archived	  = is_archived;	
 	dll_services.get_pr_head_pool = get_pr_head_pool;
 	dll_services.dict_keys_values = dict_keys_values;
 	dll_services.set_obj_rdacc    = set_obj_rdacc;
@@ -323,6 +327,29 @@
 	return res;
 }
 
+//********************************* set_archived ****************************
+void set_archived(obj_p obj){
+	get_wrlock(obj, NO_WAIT);
+	obj->archived = TRUE; 
+	free_wrlock(obj);
+}
+
+//********************************* clr_archived ****************************
+void clr_archived(obj_p obj){
+	get_wrlock(obj, NO_WAIT);
+	obj->archived = FALSE; 
+	free_wrlock(obj);
+}
+
+//********************************* is_archived *****************************
+int is_archived(obj_p obj) {
+	int res;
+	get_wrlock(obj, NO_WAIT);
+	res = obj->archived; 
+	free_wrlock(obj);
+	return res;
+}
+
 //********************************* set_obj_rdacc *****************************
 void set_obj_rdacc(obj_p obj, int access) {
 	get_wrlock(obj, NO_WAIT);