Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / lib / tt / lib / db / tt_db_object.C
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 //%%  (c) Copyright 1993, 1994 Hewlett-Packard Company                  
24 //%%  (c) Copyright 1993, 1994 International Business Machines Corp.    
25 //%%  (c) Copyright 1993, 1994 Sun Microsystems, Inc.                   
26 //%%  (c) Copyright 1993, 1994 Novell, Inc.                             
27 //%%  $XConsortium: tt_db_object.C /main/3 1995/10/23 10:03:44 rswiston $                                                       
28 /*
29  * tt_db_object.cc - Implement the TT DB server object class.
30  *
31  * Copyright (c) 1992 by Sun Microsystems, Inc.
32  *
33  */
34
35 #include "db/tt_db_create_objid.h"
36 #include "db/tt_db_key_utils.h"
37 #include "db/tt_db_network_path.h"
38 #include "db/tt_db_object_utils.h"
39 #include "db/tt_db_objid_to_key.h"
40 #include "db/tt_db_access.h"
41 #include "db/tt_db_property.h"
42
43 #define TT_DB_PROPS_CACHE_LEVEL_PROPERTY "_MODIFICATION_DATE"
44
45 _Tt_db_object::_Tt_db_object ()
46 {
47   setTtDBObjectDefaults();
48 }
49
50 _Tt_db_object::_Tt_db_object (const _Tt_string &objid)
51 {
52   setTtDBObjectDefaults();
53   dbObjectID = objid;
54
55   getDBObjectHostnameFromID ();
56   if (isObjectInDatabase()) {
57     dbObjectPropertiesCacheLevel = -1;
58  
59     setCurrentDBAccess ();
60     dbResults =
61       dbObjectDatabase->getObjectProperties(dbObjectID,
62                                             dbObjectPropertiesCacheLevel,
63                                             dbObjectProperties);
64
65     memoryObjectCreated = TRUE;
66
67     if ((dbResults == TT_DB_ERR_DB_CONNECTION_FAILED) ||
68         (dbResults == TT_DB_ERR_RPC_CONNECTION_FAILED)) {
69       dbHostnameGlobalMapRef.removeDB (dbObjectHostname);
70     }
71   }
72   else {
73     dbResults = TT_DB_ERR_NO_SUCH_OBJECT;
74   }
75 }
76
77 void _Tt_db_object::setTtDBObjectDefaults ()
78 {
79   checkedDatabase = FALSE;
80   dbObjectAccess = new _Tt_db_access;
81   dbObjectCurrentAccess = new _Tt_db_access;
82   dbObjectProperties = new _Tt_db_property_list;
83   dbObjectPropertiesCacheLevel = -1;
84   dbResults = TT_DB_OK;
85   forwardPointerFlag = FALSE;
86   memoryObjectCreated = FALSE;
87 }
88
89 _Tt_db_object::~_Tt_db_object ()
90 {
91 }
92
93 void _Tt_db_object::setCurrentAccess (const _Tt_db_access_ptr &access)
94 {
95   dbObjectCurrentAccess = access;
96 }
97
98 _Tt_db_access_ptr _Tt_db_object::getCurrentAccess () const
99 {
100   return dbObjectCurrentAccess;
101 }
102
103 _Tt_string _Tt_db_object::create (const _Tt_string &file)
104 {
105         _Tt_string empty;
106         return create(file, empty);
107 }
108
109 _Tt_string _Tt_db_object::create (const _Tt_string &file,
110                                   const _Tt_string &key)
111 {
112   if (!memoryObjectCreated) {
113     if (!file.len()) {
114       dbResults = TT_DB_ERR_ILLEGAL_FILE;
115     }
116     else {
117       dbResults = createMemoryObject(file, key);
118
119       if (dbResults == TT_DB_OK) {
120         memoryObjectCreated = TRUE;
121       }
122     }
123   }
124   else {
125     dbResults = TT_DB_ERR_OBJECT_EXISTS;
126   }
127
128   return dbObjectID;
129 }
130
131 _Tt_db_results _Tt_db_object::write ()
132 {
133   if (!isObjectInDatabase()) {
134     dbResults = createDBObject();
135   }
136   else {
137     _Tt_db_property_list_ptr properties_in_db;
138
139     // Find the cache level property and make sure it is up to date
140     // with the actual cache level
141     // XXX - This needs to be done with 4/93 DB servers.  10/93 DB servers
142     // will protect the cache level property on the DB server side.
143     _Tt_db_property_list_cursor properties_cursor (dbObjectProperties);
144     _Tt_string cache_level_bytes (sizeof (int));
145
146     while (properties_cursor.next ()) {
147       if (properties_cursor->name ==  TT_DB_PROPS_CACHE_LEVEL_PROPERTY) {
148         memcpy ((char *)cache_level_bytes,
149                 &dbObjectPropertiesCacheLevel,
150                 sizeof (int));
151         properties_cursor->values->flush ();
152         properties_cursor->values->append (cache_level_bytes);
153       }
154     }
155
156     setCurrentDBAccess ();
157     dbResults =
158       dbObjectDatabase->setObjectProperties(dbObjectID,
159                                             dbObjectProperties,
160                                             properties_in_db,
161                                             dbObjectPropertiesCacheLevel);
162
163     // If there was an update conflict, that means someone else wrote
164     // new props to the DB since this object had read its cached props.
165     // The _Tt_db_client object returns the properties currently in the
166     // database when this type of conflict occurs.
167     if (dbResults == TT_DB_ERR_UPDATE_CONFLICT) {
168       dbObjectProperties = properties_in_db;
169     }
170   }
171
172   return processDBResults();
173 }
174
175 _Tt_db_results _Tt_db_object::refresh ()
176 {
177   // Check if it is in the database and force it to find the object
178   // if it has been moved.
179   if (isObjectInDatabase(TRUE)) {
180     int                      cache_level = dbObjectPropertiesCacheLevel;
181     _Tt_db_property_list_ptr properties;
182
183     setCurrentDBAccess ();
184     dbResults = dbObjectDatabase->getObjectProperties(dbObjectID,
185                                                       cache_level,
186                                                       properties);
187
188     // Update the cache if the _Tt_db_client has new property data
189     if (cache_level > dbObjectPropertiesCacheLevel) {
190       dbObjectPropertiesCacheLevel = cache_level;
191       dbObjectProperties = properties;
192     }
193   }
194   else {
195     dbResults = TT_DB_OK;
196   }
197
198   return processDBResults();
199 }
200
201 _Tt_db_results _Tt_db_object::remove ()
202 {
203   if (isObjectInDatabase()) {
204     setCurrentDBAccess ();
205     dbResults = dbObjectDatabase->removeObject(dbObjectID,
206                                                _Tt_string((char *)NULL));
207     
208     if (dbResults == TT_DB_OK) {
209       setTtDBObjectDefaults();
210     }
211   }
212   else {
213     dbResults = TT_DB_ERR_NO_SUCH_OBJECT;
214   }
215
216   return processDBResults();
217 }
218
219 _Tt_db_results _Tt_db_object::remove (const _Tt_string &forward_pointer)
220 {
221   if (isObjectInDatabase()) {
222     setCurrentDBAccess ();
223     dbResults = dbObjectDatabase->removeObject(dbObjectID, forward_pointer);
224     
225     if (dbResults == TT_DB_OK) {
226       setTtDBObjectDefaults();
227     }
228   }
229   else {
230     dbResults = TT_DB_ERR_NO_SUCH_OBJECT;
231   }
232
233   return processDBResults();
234 }
235
236 _Tt_string _Tt_db_object::copy (const _Tt_string &new_file)
237 {
238   _Tt_string new_objid;
239
240   if (!new_file.len()) {
241     dbResults = TT_DB_ERR_ILLEGAL_FILE;
242     return new_objid;
243   }
244
245   if (isObjectInDatabase()) {
246     dbObjectFile = getFile();
247
248     _Tt_string new_local_file;
249     _Tt_string new_hostname;
250     _Tt_string new_partition;
251     _Tt_string new_file_network_path;
252     dbResults = _tt_db_network_path(new_file,
253                                     new_local_file,
254                                     new_hostname,
255                                     new_partition,
256                                     new_file_network_path);
257
258     if (dbResults == TT_DB_OK) {
259       // If we're not copying to the exact same file
260       if (dbObjectFile != new_file_network_path) {
261         _Tt_db_object_ptr new_object = new _Tt_db_object;
262         new_objid = new_object->create(new_file_network_path);
263         dbResults = new_object->getDBResults();
264
265         if ((dbResults == TT_DB_OK) && new_objid.len()) {
266           // Refresh the current object's info
267           dbResults = internalRefresh();
268           if (dbResults == TT_DB_OK) {
269             (void)new_object->setAccess(dbObjectAccess);
270             (void)new_object->setProperties(dbObjectProperties);
271             (void)new_object->setType(dbObjectType);
272             dbResults = new_object->write();
273           }
274         }
275       }
276       else {
277         dbResults = TT_DB_ERR_SAME_OBJECT;
278       }
279     }
280   }
281   else {
282     dbResults = TT_DB_ERR_NO_SUCH_OBJECT;
283   }
284
285   dbResults = processDBResults();
286   return new_objid;
287 }
288
289 _Tt_string _Tt_db_object::move (const _Tt_string &new_file)
290 {
291   _Tt_string new_objid;
292
293   if (!new_file.len()) {
294     dbResults = TT_DB_ERR_ILLEGAL_FILE;
295     return new_objid;
296   }
297
298   if (isObjectInDatabase()) {
299     dbObjectFile = getFile();
300
301     _Tt_string new_local_file;
302     _Tt_string new_hostname;
303     _Tt_string new_partition;
304     _Tt_string new_file_network_path;
305     dbResults = _tt_db_network_path(new_file,
306                                     new_local_file,
307                                     new_hostname,
308                                     new_partition,
309                                     new_file_network_path);
310
311     // If we're not moving to the exact same file
312     if (dbObjectFile != new_file_network_path) {
313       new_objid = makeEquivalentObjectID(new_hostname, new_partition);
314
315       if ((dbResults == TT_DB_OK) && new_objid.len()) {
316         // If the objids are still the same, we only need to change the
317         // object's file in the database...
318         if (dbObjectID == new_objid) {
319           dbResults = dbObjectDatabase->setObjectFile(dbObjectID,
320                                                       new_file_network_path);
321
322           if (dbResults == TT_DB_OK) {
323             dbResults = TT_DB_WRN_SAME_OBJECT_ID;
324           }
325         }
326         // Different objids and therefore different partitions or hosts
327         else {
328           _Tt_db_object_ptr new_object = new _Tt_db_object;
329           dbResults = new_object->setObjectID(new_objid);
330
331           // The new object should not exist, yet...
332           if (dbResults == TT_DB_ERR_NO_SUCH_OBJECT) {
333             new_object->dbObjectHostname = new_hostname;
334             new_object->dbObjectFile = new_file_network_path;
335
336             // Refresh the current object's info
337             dbResults = internalRefresh();
338             if (dbResults == TT_DB_OK) {
339               (void)new_object->setAccess(dbObjectAccess);
340               (void)new_object->setProperties(dbObjectProperties);
341               (void)new_object->setType(dbObjectType);
342               dbResults = new_object->write();
343             }
344           }
345           // If the new object already exists, then there is something
346           // weird going on...
347           else if (dbResults == TT_DB_OK) {
348             dbResults = TT_DB_ERR_CORRUPT_DB;
349           }
350
351           if (dbResults == TT_DB_OK) {
352             // Remove current object from the DB and specify the new objid
353             // as the forward pointer.
354             dbResults = remove(new_objid);
355
356             if (dbResults == TT_DB_OK) {
357               setTtDBObjectDefaults();
358               dbResults = setObjectID(new_objid);
359             }
360           }
361         }
362       }
363       else {
364         if (dbResults == TT_DB_OK) {
365           dbResults = TT_DB_ERR_ILLEGAL_OBJECT;
366         }
367       }
368     }
369     else {
370       dbResults = TT_DB_ERR_SAME_OBJECT;
371     }
372   }
373   else {
374     dbResults = TT_DB_ERR_NO_SUCH_OBJECT;
375   }
376
377   dbResults = processDBResults();
378   return new_objid;
379 }
380
381 _Tt_db_results
382 _Tt_db_object::setProperty (const _Tt_db_property_ptr &property)
383 {
384   if (property->name.len()) {
385     // See if a property with the same name exists...
386     bool_t found = FALSE;
387     _Tt_db_property_list_cursor properties_cursor(dbObjectProperties);
388     while (properties_cursor.next()) {
389       if (properties_cursor->name == property->name) {
390         found = TRUE;
391         break;
392       }
393     } 
394     
395     // If a property with the same name exists...
396     if (found) {
397       // If the new property has no values specified, then just
398       // delete the old property...
399       if (property->is_empty()) {
400         properties_cursor.remove();
401       }
402       // Else, we actually want to set some values...
403       else {
404         *properties_cursor = property;
405       }
406     }
407     // Else, no property with same name exists, just append the new
408     // property (if it's not empty)
409     else { if (!property->is_empty())
410                dbObjectProperties->append(property);
411     }
412
413     dbResults = TT_DB_OK;
414   }
415   else {
416     dbResults = TT_DB_ERR_ILLEGAL_PROPERTY;
417   }
418
419   return dbResults;
420 }
421
422 _Tt_db_results
423  _Tt_db_object::setProperties (const _Tt_db_property_list_ptr &properties)
424 {
425   // Replace the old properties with the new list
426   dbObjectProperties = properties;
427
428   return dbResults;
429 }
430
431 _Tt_db_results
432 _Tt_db_object::addProperty (const _Tt_db_property_ptr &property,
433                             bool_t                     unique)
434 {
435   if (property->name.len()) {
436     bool_t found = FALSE; 
437
438     // See if a property with the same name exists in the cache
439     _Tt_db_property_list_cursor properties_cursor(dbObjectProperties);
440     while (properties_cursor.next()) { 
441       if (properties_cursor->name == property->name) { 
442         found = TRUE;
443         break; 
444       }   
445     } 
446      
447     // If a property with the same name exists...
448     if (found) {
449       _Tt_string_list_cursor values_cursor(property->values);
450
451       // If a unique property name-value combinations are to be added...
452       if (unique) {
453         _Tt_string_list_cursor cache_values_cursor(properties_cursor->values);
454
455         // Loop through the values to be added
456         while (values_cursor.next()) {
457           cache_values_cursor.reset();
458         
459           // Compare versus values already in the cache
460           bool_t is_unique = TRUE;
461           while (cache_values_cursor.next()) {
462             if (*cache_values_cursor == *values_cursor) {
463               is_unique = FALSE;
464             }
465           }
466       
467           // If unique, append the value to the cache values
468           if (is_unique) {
469             properties_cursor->values->append(*values_cursor);
470           }
471         }
472       }
473       // Else uniqueness is not a requirement...
474       else {
475         while (values_cursor.next()) {
476           properties_cursor->values->append(*values_cursor);
477         }
478       }
479       
480       dbResults = TT_DB_OK;
481     }
482     else {
483       dbObjectProperties->append(property);
484       dbResults = TT_DB_OK;
485     }
486   }
487   else {
488     dbResults = TT_DB_ERR_ILLEGAL_PROPERTY;
489   }
490
491   return dbResults;
492 }
493
494 _Tt_db_results
495 _Tt_db_object::deleteProperty (const _Tt_db_property_ptr &property)
496 {
497   if (isObjectInDatabase()) {
498     setCurrentDBAccess();
499
500     // Delete the property on the database immediately and refresh
501     // the cache with the latest and greatest.  If the cache level
502     // here is not as high as the cache level in the DB, then the
503     // delete will fail.
504     dbResults =
505       dbObjectDatabase->deleteObjectProperty(dbObjectID,
506                                              property,
507                                              dbObjectProperties,
508                                              dbObjectPropertiesCacheLevel);
509   }
510   else {
511     dbResults = TT_DB_ERR_NO_SUCH_OBJECT;
512   }
513
514   return processDBResults();
515 }
516
517 _Tt_db_property_ptr _Tt_db_object::getProperty (const _Tt_string &name)
518 {
519   _Tt_db_property_ptr property;
520   
521   if (name.len()) {
522     bool_t found = FALSE;  
523     _Tt_db_property_list_cursor properties_cursor(dbObjectProperties); 
524
525     // See if a property matches the specified name
526     while (properties_cursor.next()) { 
527       if (properties_cursor->name == name) {  
528         found = TRUE; 
529         break;  
530       }   
531     }  
532       
533     if (found) {
534       property = *properties_cursor;
535       dbResults = TT_DB_OK;
536     }
537     else {
538       dbResults = TT_DB_ERR_NO_SUCH_PROPERTY;
539     }
540   }
541   else {
542     dbResults = TT_DB_ERR_ILLEGAL_PROPERTY;
543   }
544
545   return property;
546 }
547
548 _Tt_db_property_list_ptr _Tt_db_object::getProperties ()
549 {
550   dbResults = TT_DB_OK;
551   return dbObjectProperties;
552 }
553
554 _Tt_db_results _Tt_db_object::setType (const _Tt_string &type)
555 {
556   if (!isObjectInDatabase()) {
557     dbObjectType = type;
558     dbResults = TT_DB_OK;
559   }
560   else {
561     dbResults = TT_DB_ERR_OTYPE_ALREADY_SET;
562   }
563
564   return dbResults;
565 }
566
567 _Tt_string _Tt_db_object::getType ()
568 {
569   if (!dbObjectType.len() && isObjectInDatabase()) {
570     setCurrentDBAccess();
571     dbResults = dbObjectDatabase->getObjectType(dbObjectID, dbObjectType);
572   }
573   else {
574     dbResults = TT_DB_OK;
575   }
576
577   dbResults = processDBResults();
578   return dbObjectType;
579 }
580
581 _Tt_string _Tt_db_object::getFile ()
582 {
583   if (isObjectInDatabase()) {
584     setCurrentDBAccess();
585     dbResults = dbObjectDatabase->getObjectFile(dbObjectID, dbObjectFile);
586   }
587   else {
588     dbResults = TT_DB_OK;
589   }
590
591   dbResults = processDBResults();
592   return dbObjectFile;
593 }
594
595 _Tt_db_results _Tt_db_object::setAccess (const _Tt_db_access_ptr &access)
596 {
597   dbObjectAccess = access;
598
599   if (isObjectInDatabase()) {
600     setCurrentDBAccess();
601     dbResults = dbObjectDatabase->setObjectAccess(dbObjectID, dbObjectAccess);
602   }
603   else {
604     dbResults = TT_DB_OK;
605   }
606
607   return processDBResults();
608 }
609
610 _Tt_db_access_ptr _Tt_db_object::getAccess ()
611 {
612   if (isObjectInDatabase()) {
613     setCurrentDBAccess();
614     dbResults = dbObjectDatabase->getObjectAccess(dbObjectID, dbObjectAccess);
615   }
616   else {
617     dbResults = TT_DB_OK;
618   }
619
620   dbResults = processDBResults();
621   return dbObjectAccess;
622 }
623
624 _Tt_string _Tt_db_object::getObjectKey () const
625 {
626   _Tt_string key_string;
627
628   if (dbObjectID.len()) {
629     key_string = _tt_db_objid_to_key(dbObjectID);
630   }
631
632   return key_string;
633 }
634
635 _Tt_db_results
636 _Tt_db_object::createMemoryObject (const _Tt_string &file,
637                                    const _Tt_string& keystr)
638 {
639   _Tt_string local_file;
640   _Tt_string partition;
641
642   dbObjectID = (char *)NULL;
643   dbResults = _tt_db_network_path(file,
644                                   local_file,
645                                   dbObjectHostname,
646                                   partition,
647                                   dbObjectFile);
648
649   if (dbResults == TT_DB_OK) {
650           // Create a key for the new object,
651           // or use the passed-in one if present
652           _Tt_db_key_ptr key;
653           if (keystr.len()) {
654                   key = new _Tt_db_key(keystr);
655           }
656           else {
657                   key = new _Tt_db_key();
658           }
659
660           dbObjectID = _tt_db_create_objid(key, "NFS",
661                                            dbObjectHostname, partition);
662   }
663
664   return dbResults;
665 }
666
667 void _Tt_db_object::getDBObjectHostnameFromID ()
668 {
669   if (dbObjectID.len()) {
670     _Tt_string objid_string = dbObjectID;
671     _Tt_string temp_string;
672
673     // Get rid of the file system type
674     objid_string = objid_string.split(':', temp_string);
675     if (objid_string.len() && temp_string.len()) {
676       objid_string = objid_string.split(':', temp_string);
677     }
678
679     // Get the hostname
680     if (objid_string.len() && temp_string.len()) {
681       objid_string = objid_string.split(':', dbObjectHostname);
682     }
683   }
684 }
685
686 _Tt_db_results _Tt_db_object::createDBObject ()
687 {
688   if (dbObjectID.len()) {
689     if (dbObjectType.len()) {
690       dbObjectDatabase = dbHostnameGlobalMapRef.getDB(dbObjectHostname,
691                                                       dbObjectHostname,
692                                                       dbResults);
693
694       if (!dbObjectDatabase.is_null()) {
695         setCurrentDBAccess();
696         dbResults =
697           dbObjectDatabase->createObject (dbObjectFile,
698                                           dbObjectID,
699                                           dbObjectType,
700                                           dbObjectProperties,
701                                           dbObjectAccess,
702                                           dbObjectPropertiesCacheLevel);
703
704           dbObjectPropertiesCacheLevel = -1;
705
706         if (dbResults == TT_DB_OK) {
707           dbResults = internalRefresh ();
708         }
709       }
710     }
711     else {
712       dbResults = TT_DB_ERR_NO_OTYPE;
713     }
714   }
715   else {
716     dbResults = TT_DB_ERR_ILLEGAL_OBJECT;
717   }
718
719   return dbResults;
720 }
721
722 _Tt_db_results _Tt_db_object::setObjectID (const _Tt_string &new_objid)
723 {
724   dbObjectID = new_objid;
725   getDBObjectHostnameFromID();
726
727   dbResults = (isObjectInDatabase(TRUE) ? TT_DB_OK :
728                                           TT_DB_ERR_NO_SUCH_OBJECT);
729   return dbResults;
730 }
731
732 _Tt_string
733 _Tt_db_object::makeEquivalentObjectID (const _Tt_string &hostname,
734                                        const _Tt_string &partition)
735 {
736   _Tt_string new_objid = _tt_db_objid_to_key(dbObjectID);
737   new_objid = new_objid.cat(":NFS");
738   new_objid = new_objid.cat(":").cat(hostname);
739   new_objid = new_objid.cat(":").cat(partition);
740   return new_objid;
741 }
742
743 bool_t _Tt_db_object::isObjectInDatabase (bool_t force)
744 {
745   _Tt_string forward_pointer;
746
747   if ((!checkedDatabase || force) && dbObjectHostname.len()) {
748     // Get the DB connection for this objects DB host
749     dbObjectDatabase = dbHostnameGlobalMapRef.getDB(dbObjectHostname,
750                                                     dbObjectHostname,
751                                                     dbResults);
752     if (!dbObjectDatabase.is_null()) {
753       setCurrentDBAccess();
754
755       // See if the object is in the actual database and also check for
756       // a forward pointer
757       _Tt_string forward_pointer;
758       dbResults = dbObjectDatabase->isObjectInDatabase(dbObjectID,
759                                                        forward_pointer);
760     }
761
762     // Either a failure or a forward pointer...
763     if (dbResults != TT_DB_OK) {
764       if (dbResults == TT_DB_ERR_NO_SUCH_OBJECT) {
765         dbHostnameGlobalMapRef.removeDB(dbObjectHostname);
766         dbObjectDatabase = (_Tt_db_client *)NULL;
767         dbResults = TT_DB_OK;
768       }
769       else if (dbResults == TT_DB_WRN_FORWARD_POINTER) {
770         // Change this objects ID to the forward pointer.  The "setObjectID"
771         // member function will call "isObjectInDatabase" again and the
772         // forward pointer chain will eventually resolve to the final
773         // resting place of the object.
774         dbResults = setObjectID(forward_pointer);
775         forwardPointerFlag = TRUE;
776       }
777     }
778
779     checkedDatabase = TRUE;
780   }
781
782   return (dbObjectDatabase.is_null() ? FALSE : TRUE);
783 }
784
785 _Tt_db_results _Tt_db_object::internalRefresh ()
786 {
787   setCurrentDBAccess ();
788   dbResults =
789     dbObjectDatabase->getObjectProperties(dbObjectID,
790                                           dbObjectPropertiesCacheLevel,
791                                           dbObjectProperties);
792
793   if (dbResults == TT_DB_OK) {
794     dbResults = dbObjectDatabase->getObjectAccess(dbObjectID, dbObjectAccess);
795   }
796
797   if (dbResults == TT_DB_OK) {
798     dbResults = dbObjectDatabase->getObjectType(dbObjectID, dbObjectType);
799   }
800
801   return dbResults;
802 }
803
804 _Tt_db_results _Tt_db_object::processDBResults ()
805 {
806   // If an RPC fails, assume the DB server went down and attemp to
807   // reconnect to it
808   if ((dbResults == TT_DB_ERR_DB_CONNECTION_FAILED) ||
809       (dbResults == TT_DB_ERR_RPC_CONNECTION_FAILED)) {
810     if (!dbObjectDatabase.is_null()) {
811       dbHostnameGlobalMapRef.removeDB(dbObjectHostname);
812       dbObjectDatabase = dbHostnameGlobalMapRef.getDB(dbObjectHostname,
813                                                       dbObjectHostname,
814                                                       dbResults);
815
816     }
817   }   
818   // Else if the results were OK, but the forward pointer flag was set,
819   // return TT_WRN_FORWARD_POINTER
820   else if ((dbResults == TT_DB_OK) && forwardPointerFlag) {
821     forwardPointerFlag = FALSE;
822     dbResults = TT_DB_WRN_FORWARD_POINTER;
823   }
824
825   return dbResults;
826