1 /* Copyright (C) 2000-2010 Thomas Bopp, Thorsten Hampel, Ludger Merkens
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 * $Id: proxy.pike,v 1.6 2010/08/21 19:38:00 astra Exp $
20 #include <exception.h>
29 private object oSteamObj;
30 public object oNext, oPrev;
34 private mapping mDecorationObjects;
35 private array aDecorationObjects; // cache
38 private Thread.Mutex loadMutex = Thread.Mutex(); // save loading
42 * create a proxy for a sTeam-Object
43 * @returns void (is a constructor)
44 * @args int _id - the object ID of the associated object
45 * int init - create proxy only, or create new object
46 * string prog - class for the associated object
48 final void create(int _id, object|void oTrue, void|int _class)
54 mDecorationObjects = ([ ]);
55 aDecorationObjects = ({ });
60 iStatus = PSTAT_SAVE_OK;
62 // master()->append(this_object());
66 * @function get_object_id
67 * @returns int (the object id to the associated object)
69 final int get_object_id()
74 final int get_object_class()
79 function f = find_function("get_object_class");
80 catch(iClassID = f());
84 final void set_steam_obj(object o)
86 if ((CALLER == _Database || CALLER == _Persistence) && !objectp(oSteamObj))
92 * set the status of the proxy. Changes can only be done by either server
95 * @param int _status - new status to set
98 final void set_status(int _status)
101 if (c == _Database || c == _Server || c == _Persistence || c == oSteamObj)
106 private int i_am_in_backtrace()
108 foreach(backtrace(), mixed preceed)
110 if (function_object(preceed[2]) == oSteamObj) {
120 * Drop the corresponding steam object.
122 * @return 0 or 1 depending if the drop is successfull.
126 if ( !objectp(oSteamObj) )
128 else if ( iStatus == PSTAT_SAVE_PENDING)
130 call(drop, 2.0); // drop later
133 else if ( i_am_in_backtrace()) // don't drop an object wich is a caller
138 object lock = loadMutex->trylock();
139 if (!objectp(lock)) {
140 call(drop, 2.0); // drop later
144 // the object should also be removed from memory ?!
147 master()->got_dropped(this_object());
149 iStatus = PSTAT_DISK;
155 * Find a function inside the proxy object.
157 * @param string fun - the function to find
158 * @return a functionp of the function or 0
160 final function find_function (string fun)
162 if ( !objectp(oSteamObj) )
164 if ( !objectp(oSteamObj) )
168 if ( f = oSteamObj[fun] )
170 foreach ( aDecorationObjects, object decoration ) {
171 if ( !objectp(decoration) ) continue;
172 f = decoration->find_function( fun );
181 object loadLock = loadMutex->lock();
182 if ( !objectp(oSteamObj) ) {
185 switch(_Persistence->load_object(this_object(), iOID)) {
187 iStatus = PSTAT_FAIL_COMPILE;
190 iStatus = PSTAT_FAIL_DELETED;
193 iStatus = PSTAT_FAIL_DELETED;
196 iStatus = PSTAT_FAIL_UNSERIALIZE;
199 if ( iStatus == PSTAT_DISK )
200 iStatus = PSTAT_SAVE_OK;
202 if (!objectp(oSteamObj)) {
207 master()->got_loaded(this_object());
219 mapping (string:mixed) fLocal = ([
220 "get_object_class": get_object_class,
221 "get_object_id" : get_object_id,
222 "get_object_class": get_object_class,
223 "set_status": set_status,
224 "set_decoration_object": set_decoration_object,
226 "find_function" : find_function,
228 "set_steam_obj": set_steam_obj,
231 "get_object" : get_object,
235 * `->() The indexing operator is replaced in proxy.pike to redirect function
236 * calls to the associated object.
237 * @param string func - the function to redirect
238 * @return mixed - usually the function pointer to the function in question
239 * __null() in case of error
243 final mixed `->(string func)
248 if ((f=fLocal[func]) && (func!="get_object") && (func!="find_function"))
250 // double check for loadlock due to performance reasons
251 // usually loading is only called once and this way performance
252 // is better when already loaded
254 if (!objectp(oSteamObj))
261 if (f = fLocal[func])
264 if ( !(f = oSteamObj[func]) ) {
265 foreach ( aDecorationObjects, object decoration ) {
266 if ( !objectp(decoration) ) continue;
267 mixed deco_f = decoration->find_function( func );
268 if ( deco_f ) return deco_f;
273 if (func == "get_identifier")
274 master()->front(this_object());
280 * dummy function, replacing a broken function, in case of error
292 * forces to load the content of an object from the database
293 * is this function used ? - astra
296 final int|object force_load()
299 object loadLock = loadMutex->lock();
303 x= _Persistence->load_object(this_object(), oSteamObj);
306 case 1: iStatus = PSTAT_FAIL_COMPILE;
308 case 0: iStatus = PSTAT_FAIL_DELETED;
310 case 2: iStatus = PSTAT_FAIL_COMPILE;
316 x= _Persistence->load_object(this_object(), iOID);
319 case 1: iStatus = PSTAT_FAIL_COMPILE;
321 case 0: iStatus = PSTAT_FAIL_DELETED;
323 case 2: iStatus = PSTAT_FAIL_COMPILE;
335 * get the associated Object from this proxy
339 * @see _Database.load_object
341 final object get_object()
347 * Called when the object including the proxy are destructed.
352 master()->remove(this_object());
357 * The function returns the status of the proxy, which is actually
358 * the status of the corresponding object.
361 * @return PSTAT_DISK ( 0) - on disk
362 * PSTAT_SAVE_OK ( 1) - in memory
363 * PSTAT_SAVE_PENDING ( 2) - in memory, but dirty (not implemented)
364 * PSTAT_DELETED ( 3) - deleted from database
365 * PSTAT_FAIL_COMPILE (-1) - failed to load (compilation failure)
366 * PSTAT_FAIL_UNSERIALIZE (-2) - failed to load (serialization failure)
367 * PSTAT_FAIL_DELETED (-3) - failed to load (deleted from database)
368 * @see database.h for PSTAT constants.
374 if (!objectp(oSteamObj))
382 return "/kernel/proxy.pike("+iOID+"/"+
383 ({ "PSTAT_FAIL_DELETED", "PSTAT_FAIL_UNSERIALIZE" ,
384 "PSTAT_FAIL_COMPILE", "PSTAT_DISK", "PSTAT_SAVE_OK",
385 "PSTAT_SAVE_PENDING", "PSTAT_DELETED" })[iStatus+3]+")";
388 void set_decoration_object ( string path, object|void decoration )
390 if ( CALLER != oSteamObj )
391 steam_error( "No access to set decoration instance in proxy !" );
392 if ( objectp(decoration) )
393 mDecorationObjects[ path ] = decoration;
395 m_delete( mDecorationObjects, path );
396 aDecorationObjects = values( mDecorationObjects ); // refresh cache
399 public int swap(int minSwapTime)
401 if (time() - iTime > minSwapTime) {