2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
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 //%% $TOG: db_server_functions.C /main/6 1999/10/14 18:38:12 mgreess $
29 * @(#)db_server_functions.C 1.35 95/06/07
31 * Copyright (c) 1992 by Sun Microsystems, Inc.
33 * This file contains the functions that connect the DB server RPC
34 * interface to the DB server classes.
36 * As a function is implemented, it should commented
37 * out of the db_server_stubs.cc file.
42 #include <sys/param.h>
48 #include "api/c/tt_c.h"
49 #include "util/tt_file_system.h"
50 #include "util/tt_file_system_entry.h"
51 #include "util/tt_path.h"
52 #include "util/tt_port.h"
53 #include "util/tt_xdr_utils.h"
54 #include "util/tt_gettext.h"
55 #include "db/db_server.h"
56 #include "db/tt_db_access.h"
57 #include "db/tt_db_property.h"
58 #include "db/tt_db_access_utils.h"
59 #include "db/tt_db_property_utils.h"
60 #include "db/tt_db_rpc_routines.h"
61 #include "db_server_globals.h"
62 #include "tt_db_message_info_utils.h"
63 #include "tt_db_partition_global_map_ref.h"
64 #include "tt_db_server_consts.h"
65 #include "tt_db_server_db_utils.h"
66 #include "dm_access_cache.h"
67 #include "dm/dm_recfmts.h"
70 #if !defined(OPT_GARBAGE_THREADS)
71 #include <db/tt_db_client.h>
72 #include <db/tt_db_client_utils.h>
80 // This is the PID or TID of the procedure that is
81 // performing the garbage collection.
83 #if defined(USL) || defined(__uxp__)
84 int _tt_garbage_id = 0; // TID or PID.
86 int _tt_garbage_id = -1; // TID or PID.
89 int _tt_run_garbage_collect(int in_parallel);
91 static const char * sesProp = _TT_FILEJOIN_PROPNAME;
92 static const char * modDate = _MP_NODE_MOD_PROP;
93 static const char * propTable = "property_table";
95 extern _Tt_db_info _tt_db_table[_TT_MAX_ISFD];
97 static bool_t _tt_is_file_a_directory (const _Tt_string&);
98 static _Tt_string _tt_make_equivalent_object_id(const _Tt_string &objid,
99 const _Tt_string &partition);
100 static _Tt_db_results _tt_get_partition_db (const _Tt_string&,
101 _Tt_db_server_db_ptr&);
102 static _Tt_db_access_ptr
103 _tt_get_real_rpc_access (const _tt_access &rpc_access);
104 static _Tt_db_access_ptr _tt_get_file_access (const _Tt_string &file,
105 const _tt_access &rpc_access);
106 static _Tt_db_access_ptr _tt_get_unix_file_access (const _Tt_string &file);
107 static _Tt_string _tt_get_file_partition (const _Tt_string &file);
108 static _Tt_db_results
109 _tt_increment_file_properties_cache_level (const _Tt_db_server_db_ptr&,
111 const _Tt_db_access_ptr&,
113 static _Tt_db_results
114 _tt_get_file_properties_cache_level (const _Tt_db_server_db_ptr&,
116 const _Tt_db_access_ptr&,
118 static _Tt_string _tt_get_object_partition (const _Tt_string &objid);
119 static _Tt_db_results
120 _tt_increment_object_properties_cache_level (const _Tt_db_server_db_ptr&,
122 const _Tt_db_access_ptr&,
124 static _Tt_db_results
125 _tt_get_object_properties_cache_level (const _Tt_db_server_db_ptr&,
127 const _Tt_db_access_ptr&,
129 static void _tt_screen_object_properties (_Tt_db_property_list_ptr&);
131 static _Tt_string _tt_get_local_path (const _Tt_string &network_path,
132 _Tt_string &hostname,
133 _Tt_string &partition);
135 _tt_auth_level_results *_tt_get_min_auth_level_1 (void * /* dummy_arg */,
136 SVCXPRT * /* transp */)
138 static _tt_auth_level_results results;
139 results.auth_level = _tt_auth_level;
140 results.results = TT_DB_OK;
144 _tt_file_partition_results *_tt_get_file_partition_1 (char **file,
145 SVCXPRT * /* transp */)
147 static _tt_file_partition_results results;
149 _Tt_string hostname = _tt_gethostname();
151 _Tt_string file_hostname;
152 _Tt_string network_path = *file;
153 _Tt_string partition;
154 _Tt_string local_path = _tt_get_local_path (network_path,
157 results.partition = strdup((char *)partition);
159 if (file_hostname == hostname) {
160 network_path = file_hostname.cat(":").cat(local_path);
162 results.network_path = strdup((char *)network_path);
164 results.results = TT_DB_OK;
169 _tt_db_cache_results *_tt_create_file_1 (_tt_create_file_args *args,
170 SVCXPRT * /* transp */)
172 static _tt_db_cache_results results;
173 results.cache_level = -1;
175 _Tt_string real_file = args->file;
176 _Tt_string partition = _tt_get_file_partition(args->file);
177 _Tt_db_server_db_ptr db;
178 results.results = _tt_get_partition_db(partition, db);
180 _Tt_db_access_ptr access = _tt_get_file_access(real_file, args->access);
182 if (results.results == TT_DB_OK) {
183 // See if the file already exists by trying to get its access info
184 _Tt_db_access_ptr temp_access;
185 _Tt_db_results temp_results = db->getFileAccess(real_file,
189 // If the file exists...
190 if ((temp_results == TT_DB_OK) ||
191 (temp_results == TT_DB_ERR_ACCESS_DENIED)) {
192 results.results = TT_DB_ERR_FILE_EXISTS;
194 // Else, if the file does not exist...
195 else if (temp_results == TT_DB_ERR_NO_SUCH_FILE) {
196 results.results = TT_DB_OK;
199 results.results = temp_results;
203 if (results.results == TT_DB_OK) {
204 results.results = db->createFile(real_file, access);
206 if (results.results == TT_DB_OK) {
207 _Tt_db_property_list_ptr properties;
208 _tt_get_rpc_properties(args->properties, properties);
210 if (!properties.is_null()) {
211 results.results = db->setFileProperties(real_file,
216 if (results.results == TT_DB_OK) {
218 _tt_increment_file_properties_cache_level(db,
221 results.cache_level);
229 _tt_db_cache_results *_tt_create_obj_1 (_tt_create_obj_args *args,
230 SVCXPRT * /* transp */)
232 static _tt_db_cache_results results;
233 results.cache_level = -1;
235 _Tt_string partition = _tt_get_object_partition(args->objid);
236 _Tt_db_server_db_ptr db;
237 results.results = _tt_get_partition_db(partition, db);
239 _Tt_string real_file = args->file;
240 _Tt_db_access_ptr object_access = _tt_get_real_rpc_access(args->access);
242 if (results.results == TT_DB_OK) {
243 // See if the object already exists by trying to get the forward
245 _Tt_db_property_ptr temp_property;
246 _Tt_db_results temp_results =
247 db->getObjectProperty(args->objid,
248 TT_DB_FORWARD_POINTER_PROPERTY,
252 // If the property exists, remove the object
253 if (temp_results == TT_DB_OK) {
254 (void)db->removeObject(args->objid, object_access);
256 // Else if the object exists without a forward pointer...
257 else if (temp_results == TT_DB_ERR_NO_SUCH_PROPERTY) {
258 results.results = TT_DB_ERR_OBJECT_EXISTS;
260 // Else if the object does not exist...
261 else if (temp_results == TT_DB_ERR_NO_SUCH_OBJECT) {
262 results.results = TT_DB_OK;
265 results.results = temp_results;
269 if (results.results == TT_DB_OK) {
270 _Tt_db_access_ptr file_access = _tt_get_file_access(real_file,
272 results.results = db->createObject(real_file,
277 if (results.results == TT_DB_OK) {
278 _Tt_db_property_list_ptr properties;
279 _tt_get_rpc_properties(args->properties, properties);
281 if (!properties.is_null()) {
282 _tt_screen_object_properties (properties);
285 if (!properties.is_null()) {
286 results.results = db->setObjectProperties(args->objid,
291 // Set the otype of the object
292 if (results.results == TT_DB_OK) {
293 _Tt_db_property_ptr property = new _Tt_db_property;
294 property->name = TT_DB_OBJECT_TYPE_PROPERTY;
295 property->values->append(_Tt_string(args->otype));
297 results.results = db->setObjectProperty(args->objid,
302 if (results.results == TT_DB_OK) {
304 _tt_increment_object_properties_cache_level(db,
307 results.cache_level);
315 _tt_db_results *_tt_remove_file_1 (_tt_remove_file_args *args,
316 SVCXPRT * /* transp */)
318 static _tt_db_results results;
320 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
322 _Tt_string real_file = args->file;
323 _Tt_string partition = _tt_get_file_partition(args->file);
324 _Tt_db_server_db_ptr db;
325 results = _tt_get_partition_db(partition, db);
327 if (results == TT_DB_OK) {
328 // Get the list of children under the file to remove along with
329 // the file. The list includes the file itself.
330 _Tt_string_list_ptr children;
331 results = db->getFileChildren(real_file, children);
333 if (children->is_empty()) {
334 results = TT_DB_ERR_NO_SUCH_FILE;
337 _Tt_string_list_cursor children_cursor(children);
338 while ((results == TT_DB_OK) && children_cursor.next()) {
339 results = db->removeFile(*children_cursor, accessPtr);
347 _tt_db_results *_tt_remove_obj_1 (_tt_remove_obj_args *args,
348 SVCXPRT * /* transp */)
350 static _tt_db_results results;
352 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
354 _Tt_string partition = _tt_get_object_partition(args->objid);
355 _Tt_db_server_db_ptr db;
356 results = _tt_get_partition_db(partition, db);
358 if (results == TT_DB_OK) {
359 results = db->removeObject(args->objid, accessPtr);
361 if (results == TT_DB_OK) {
362 if (args->forward_pointer && strlen(args->forward_pointer)) {
363 // Allow everyone to read and delete the forward pointer
364 _Tt_db_access_ptr new_access = new _Tt_db_access;
365 new_access->user = (uid_t)-1;
366 new_access->group = (gid_t)-1;
367 new_access->mode = (mode_t)-1;
369 // Create a special forward pointer object with no file...
370 results = db->createObject((char *)NULL,
375 if (results == TT_DB_OK) {
376 _Tt_db_property_ptr property = new _Tt_db_property;
377 property->name = TT_DB_FORWARD_POINTER_PROPERTY;
378 property->values->append(_Tt_string(args->forward_pointer));
380 results = db->setObjectProperty(args->objid, property, accessPtr);
389 _tt_db_results *_tt_move_file_1 (_tt_move_file_args *args,
390 SVCXPRT * /* transp */)
392 static _tt_db_results results;
394 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
396 _Tt_string real_file = args->file;
397 _Tt_string real_new_file = args->new_file;
399 // Make sure we really need to do a move
400 if (real_file != real_new_file) {
402 _Tt_file_system_entry_ptr entry = fs.bestMatchToPath(real_file);
403 _Tt_file_system_entry_ptr new_entry = fs.bestMatchToPath(real_new_file);
405 _Tt_string partition = entry->getMountPoint();
406 _Tt_string new_partition = new_entry->getMountPoint();
408 if (partition == new_partition) {
409 // Get a connection to the partition DB
410 _Tt_db_server_db_ptr db;
411 results = _tt_get_partition_db(partition, db);
413 _Tt_string_list_ptr children;
414 if (results == TT_DB_OK) {
415 // Get a list of the files to move
416 results = db->getFileChildren(real_file, children);
419 if (results == TT_DB_OK) {
420 if (children->is_empty ()) {
421 results = TT_DB_ERR_NO_SUCH_FILE;
424 _Tt_string_list_cursor children_cursor(children);
425 while ((results == TT_DB_OK) && children_cursor.next()) {
426 // Construct the new file name by replacing the part
427 // that equals the "real_file" with the "real_new_file".
428 int length = (*children_cursor).len() - real_file.len();
429 _Tt_string new_child = real_new_file.cat("/");
430 new_child = new_child.cat((*children_cursor).right(length));
432 // Change the file name in the database
433 db->setFileFile(*children_cursor, new_child, accessPtr);
438 // Else, different partitions, therefore we can only move one
439 // non-directory file
440 else if (!_tt_is_file_a_directory(real_file)) {
441 // Get a connections to both partition DBs
442 _Tt_db_server_db_ptr db;
443 results = _tt_get_partition_db(partition, db);
445 _Tt_db_server_db_ptr new_db;
446 if (results == TT_DB_OK) {
447 results = _tt_get_partition_db(new_partition, new_db);
450 if (results == TT_DB_OK) {
451 _Tt_db_property_list_ptr properties;
452 _Tt_db_access_ptr current_access;
453 _Tt_string_list_ptr objids;
455 // Get all of the file's possesions
456 results = db->getFileProperties(real_file, accessPtr, properties);
457 if (results == TT_DB_OK) {
458 results = db->getFileAccess(real_file, accessPtr, current_access);
460 if (results == TT_DB_OK) {
461 results = db->getFileObjects(real_file, accessPtr, objids);
464 // Create the new file
465 if (results == TT_DB_OK) {
466 results = new_db->createFile(real_new_file, current_access);
469 // Copy the old file's properties to the new file
470 if (results == TT_DB_OK) {
471 results = new_db->setFileProperties(real_new_file,
476 // Create the new objects with equivalent objids on the new partition
477 _Tt_string_list_ptr new_objids;
478 if (results == TT_DB_OK && (!objids->is_empty())) {
479 new_objids = new _Tt_string_list;
481 // Loop through the file's objects
482 _Tt_string_list_cursor objids_cursor(objids);
483 while ((results == TT_DB_OK) && objids_cursor.next()) {
484 _Tt_string new_objid =
485 _tt_make_equivalent_object_id(*objids_cursor, new_partition);
486 new_objids->append(new_objid);
488 _Tt_db_property_list_ptr properties;
489 _Tt_db_access_ptr current_access;
491 // Get all of the object's possesions
492 results = db->getObjectProperties(*objids_cursor,
495 if (results == TT_DB_OK) {
496 results = db->getObjectAccess(*objids_cursor,
501 // Create the new object
502 if (results == TT_DB_OK) {
503 results = new_db->createObject(real_new_file,
509 // Copy the old object's properties to the new object
510 if (results == TT_DB_OK) {
511 results = new_db->setObjectProperties(new_objid,
518 // Remove the old file and all of its objects
519 if (results == TT_DB_OK) {
520 results = db->removeFile(real_file, accessPtr);
523 // Create the forwarding pointers for all of the objects on
525 if ((results == TT_DB_OK) && (!objids->is_empty())) {
526 _Tt_string_list_cursor objids_cursor(objids);
527 _Tt_string_list_cursor new_objids_cursor(new_objids);
529 while ((results == TT_DB_OK) &&
530 objids_cursor.next() &&
531 new_objids_cursor.next()) {
532 // Allow everyone to read and delete the forward pointer
533 _Tt_db_access_ptr new_access = new _Tt_db_access;
534 new_access->user = (uid_t)-1;
535 new_access->group = (gid_t)-1;
536 new_access->mode = (mode_t)-1;
538 // Create a special forward pointer object with no file...
539 results = db->createObject((char *)NULL,
544 if (results == TT_DB_OK) {
545 _Tt_db_property_ptr property = new _Tt_db_property;
546 property->name = TT_DB_FORWARD_POINTER_PROPERTY;
547 property->values->append(*new_objids_cursor);
549 results = db->setObjectProperty(*objids_cursor,
558 results = TT_DB_ERR_ILLEGAL_FILE;
562 results = TT_DB_ERR_SAME_FILE;
568 _tt_db_cache_results *_tt_set_file_props_1 (_tt_set_file_props_args *args,
569 SVCXPRT * /* transp */)
571 static _tt_db_cache_results results;
572 results.cache_level = -1;
574 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
576 _Tt_string real_file = args->file;
577 _Tt_string partition = _tt_get_file_partition(args->file);
578 _Tt_db_server_db_ptr db;
579 results.results = _tt_get_partition_db(partition, db);
581 if (results.results == TT_DB_OK) {
582 _Tt_db_property_list_ptr properties;
583 _tt_get_rpc_properties(args->properties, properties);
585 if (!properties.is_null()) {
586 results.results = db->setFileProperties(real_file,
591 results.results = TT_DB_ERR_ILLEGAL_PROPERTY;
594 if (results.results == TT_DB_OK) {
596 _tt_increment_file_properties_cache_level(db,
599 results.cache_level);
606 _tt_db_cache_results *_tt_set_file_prop_1 (_tt_set_file_prop_args *args,
607 SVCXPRT * /* transp */)
609 static _tt_db_cache_results results;
610 results.cache_level = -1;
612 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
614 _Tt_string real_file = args->file;
615 _Tt_string partition = _tt_get_file_partition(args->file);
616 _Tt_db_server_db_ptr db;
617 results.results = _tt_get_partition_db(partition, db);
619 if (results.results == TT_DB_OK) {
620 _Tt_db_property_ptr property;
621 _tt_get_rpc_property(args->property, property);
623 if (!property.is_null()) {
624 results.results = db->setFileProperty(real_file,
629 results.results = TT_DB_ERR_ILLEGAL_PROPERTY;
632 if (results.results == TT_DB_OK) {
634 _tt_increment_file_properties_cache_level(db,
637 results.cache_level);
644 _tt_db_cache_results *_tt_add_file_prop_1 (_tt_add_file_prop_args *args,
645 SVCXPRT * /* transp */)
647 static _tt_db_cache_results results;
648 results.cache_level = -1;
650 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
652 _Tt_string real_file = args->file;
653 _Tt_string partition = _tt_get_file_partition(args->file);
654 _Tt_db_server_db_ptr db;
655 results.results = _tt_get_partition_db(partition, db);
657 if (results.results == TT_DB_OK) {
658 _Tt_db_property_ptr property;
659 _tt_get_rpc_property(args->property, property);
661 if (!property.is_null()) {
662 results.results = db->addFileProperty(real_file,
668 results.results = TT_DB_ERR_ILLEGAL_PROPERTY;
671 if (results.results == TT_DB_OK) {
673 _tt_increment_file_properties_cache_level(db,
676 results.cache_level);
683 _tt_db_cache_results *_tt_delete_file_prop_1 (_tt_del_file_prop_args *args,
684 SVCXPRT * /* transp */)
686 static _tt_db_cache_results results;
687 results.cache_level = -1;
689 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
691 _Tt_string real_file = args->file;
692 _Tt_string partition = _tt_get_file_partition(args->file);
693 _Tt_db_server_db_ptr db;
694 results.results = _tt_get_partition_db(partition, db);
696 if (results.results == TT_DB_OK) {
697 _Tt_db_property_ptr property;
698 _tt_get_rpc_property(args->property, property);
700 if (!property.is_null()) {
701 results.results = db->deleteFileProperty(real_file,
706 results.results = TT_DB_ERR_ILLEGAL_PROPERTY;
709 if (results.results == TT_DB_OK) {
711 _tt_increment_file_properties_cache_level(db,
714 results.cache_level);
721 _tt_file_prop_results *_tt_get_file_prop_1 (_tt_get_file_prop_args *args,
722 SVCXPRT * /* transp */)
724 static _tt_file_prop_results results;
725 results.cache_level = -1;
727 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
729 _Tt_string real_file = args->file;
730 _Tt_string partition = _tt_get_file_partition(args->file);
731 _Tt_db_server_db_ptr db;
732 results.results = _tt_get_partition_db(partition, db);
734 if (results.results == TT_DB_OK) {
735 results.results = _tt_get_file_properties_cache_level(db,
738 results.cache_level);
741 _Tt_db_property_ptr property;
742 if ((results.cache_level > args->cache_level) &&
743 (results.results == TT_DB_OK)) {
744 results.results = db->getFileProperty(real_file,
749 _tt_set_rpc_property(property, results.property);
754 _tt_file_props_results *
755 _tt_get_file_props_1 (_tt_get_file_props_args *args,
756 SVCXPRT * /* transp */)
758 static _tt_file_props_results results;
759 results.cache_level = -1;
761 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
763 _Tt_string real_file = args->file;
764 _Tt_string partition = _tt_get_file_partition(args->file);
765 _Tt_db_server_db_ptr db;
766 results.results = _tt_get_partition_db(partition, db);
768 if (results.results == TT_DB_OK) {
769 results.results = _tt_get_file_properties_cache_level(db,
772 results.cache_level);
775 _Tt_db_property_list_ptr properties;
776 if ((results.cache_level > args->cache_level) &&
777 (results.results == TT_DB_OK)) {
778 results.results = db->getFileProperties(real_file,
782 _tt_set_rpc_properties(properties, results.properties);
787 _tt_file_objs_results *_tt_get_file_objs_1 (_tt_get_file_objs_args *args,
788 SVCXPRT * /* transp */)
790 static _tt_file_objs_results results;
792 // Make sure the returned cache level is higher then the callers
793 // cache level, so that the caller will use the returned data
794 results.cache_level = args->cache_level + 1;
796 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
798 _Tt_string real_file = args->file;
799 _Tt_string partition = _tt_get_file_partition(args->file);
800 _Tt_db_server_db_ptr db;
801 results.results = _tt_get_partition_db(partition, db);
803 _Tt_string_list_ptr objids;
804 if ((results.cache_level > args->cache_level) &&
805 (results.results == TT_DB_OK)) {
806 results.results = db->getFileObjects(real_file,
810 _tt_set_rpc_strings(objids, results.objids);
815 _tt_db_results *_tt_set_file_access_1 (_tt_set_file_access_args *args,
816 SVCXPRT * /* transp */)
818 static _tt_db_results results;
820 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
822 _Tt_string real_file = args->file;
823 _Tt_string partition = _tt_get_file_partition(args->file);
824 _Tt_db_server_db_ptr db;
825 results = _tt_get_partition_db(partition, db);
827 _Tt_db_access_ptr new_access;
828 if (results == TT_DB_OK) {
829 _tt_get_rpc_access(args->new_access, new_access);
831 if ((new_access->user == (uid_t)-1) ||
832 (new_access->group == (gid_t)-1) ||
833 (new_access->mode == (mode_t)-1)) {
834 _Tt_db_access_ptr current_access;
835 results = db->getFileAccess(real_file,
839 if (results == TT_DB_OK) {
840 if (new_access->user == (uid_t)-1) {
841 new_access->user = current_access->user;
844 if (new_access->group == (gid_t)-1) {
845 new_access->group = current_access->group;
848 if (new_access->mode == (mode_t)-1) {
849 new_access->mode = current_access->mode;
854 if (results == TT_DB_OK) {
855 results = db->setFileAccess(real_file, new_access, accessPtr);
862 _tt_file_access_results *_tt_get_file_access_1 (_tt_get_file_access_args *args,
863 SVCXPRT * /* transp */)
865 static _tt_file_access_results results;
867 _Tt_string real_file = args->file;
868 _Tt_string partition = _tt_get_file_partition(args->file);
869 _Tt_db_server_db_ptr db;
870 results.results = _tt_get_partition_db(partition, db);
872 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
874 _Tt_db_access_ptr current_access;
875 if (results.results == TT_DB_OK) {
876 results.results = db->getFileAccess(real_file,
880 _tt_set_rpc_access(current_access, results.access);
885 _tt_obj_props_results *_tt_set_obj_props_1 (_tt_set_obj_props_args *args,
886 SVCXPRT * /* transp */)
888 static _tt_obj_props_results results;
889 results.cache_level = -1;
891 _Tt_string partition = _tt_get_object_partition(args->objid);
892 _Tt_db_server_db_ptr db;
893 results.results = _tt_get_partition_db(partition, db);
895 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
897 if (results.results == TT_DB_OK) {
899 _tt_get_object_properties_cache_level(db,
902 results.cache_level);
905 _Tt_db_property_list_ptr properties;
907 // If the cache level in the DB is higher then the passed in
908 // cache level, then someone else must have updated before
909 // the callers last read from the DB --> update conflict...
910 if ((results.results == TT_DB_OK) &&
911 (results.cache_level > args->cache_level)) {
912 results.results = TT_DB_ERR_UPDATE_CONFLICT;
914 _Tt_db_results temp_results = db->getObjectProperties(args->objid,
918 if (results.results != TT_DB_OK) {
919 properties = (_Tt_db_property_list *)NULL;
920 results.results = temp_results;
923 _tt_set_rpc_properties(properties, results.properties);
925 // No update conflicts or any other weirdness...
926 if (results.results == TT_DB_OK) {
927 _tt_get_rpc_properties(args->properties, properties);
929 if (!properties.is_null()) {
930 _tt_screen_object_properties (properties);
933 if (!properties.is_null()) {
934 results.results = db->setObjectProperties(args->objid,
939 results.results = TT_DB_ERR_ILLEGAL_PROPERTY;
942 if (results.results == TT_DB_OK) {
944 _tt_increment_object_properties_cache_level(db,
947 results.cache_level);
954 _tt_obj_props_results *_tt_set_obj_prop_1 (_tt_set_obj_prop_args *args,
955 SVCXPRT * /* transp */)
957 static _tt_obj_props_results results;
958 results.cache_level = -1;
960 _Tt_string partition = _tt_get_object_partition(args->objid);
961 _Tt_db_server_db_ptr db;
962 results.results = _tt_get_partition_db(partition, db);
964 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
966 if (results.results == TT_DB_OK) {
968 _tt_get_object_properties_cache_level(db,
971 results.cache_level);
974 _Tt_db_property_list_ptr properties;
976 // If the cache level in the DB is higher then the passed in
977 // cache level, then someone else must have updated before
978 // the callers last read from the DB --> update conflict...
979 if ((results.results == TT_DB_OK) &&
980 (results.cache_level > args->cache_level)) {
981 results.results = TT_DB_ERR_UPDATE_CONFLICT;
983 _Tt_db_results temp_results = db->getObjectProperties(args->objid,
987 if (results.results != TT_DB_OK) {
988 properties = (_Tt_db_property_list *)NULL;
989 results.results = temp_results;
992 _tt_set_rpc_properties(properties, results.properties);
994 // No update conflicts or any other weirdness...
995 if (results.results == TT_DB_OK) {
996 _Tt_db_property_ptr property;
997 _tt_get_rpc_property(args->property, property);
999 if (!property.is_null()) {
1000 results.results = db->setObjectProperty(args->objid,
1005 results.results = TT_DB_ERR_ILLEGAL_PROPERTY;
1008 if (results.results == TT_DB_OK) {
1010 _tt_increment_object_properties_cache_level(db,
1013 results.cache_level);
1020 _tt_obj_props_results *_tt_add_obj_prop_1 (_tt_add_obj_prop_args *args,
1021 SVCXPRT * /* transp */)
1023 static _tt_obj_props_results results;
1024 results.cache_level = -1;
1026 _Tt_string partition = _tt_get_object_partition(args->objid);
1027 _Tt_db_server_db_ptr db;
1028 results.results = _tt_get_partition_db(partition, db);
1030 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
1032 if (results.results == TT_DB_OK) {
1034 _tt_get_object_properties_cache_level(db,
1037 results.cache_level);
1040 _Tt_db_property_list_ptr properties;
1042 // If the cache level in the DB is higher then the passed in
1043 // cache level, then someone else must have updated before
1044 // the callers last read from the DB --> update conflict...
1045 if ((results.results == TT_DB_OK) &&
1046 (results.cache_level > args->cache_level)) {
1047 results.results = TT_DB_ERR_UPDATE_CONFLICT;
1049 _Tt_db_results temp_results = db->getObjectProperties(args->objid,
1053 if (results.results != TT_DB_OK) {
1054 properties = (_Tt_db_property_list *)NULL;
1055 results.results = temp_results;
1058 _tt_set_rpc_properties(properties, results.properties);
1060 // No update conflicts or any other weirdness...
1061 if (results.results == TT_DB_OK) {
1062 _Tt_db_property_ptr property;
1063 _tt_get_rpc_property(args->property, property);
1065 if (!property.is_null()) {
1066 results.results = db->addObjectProperty(args->objid,
1072 results.results = TT_DB_ERR_ILLEGAL_PROPERTY;
1075 if (results.results == TT_DB_OK) {
1077 _tt_increment_object_properties_cache_level(db,
1080 results.cache_level);
1087 _tt_obj_props_results *_tt_delete_obj_prop_1 (_tt_del_obj_prop_args *args,
1088 SVCXPRT * /* transp */)
1090 static _tt_obj_props_results results;
1091 results.cache_level = -1;
1093 _Tt_string partition = _tt_get_object_partition(args->objid);
1094 _Tt_db_server_db_ptr db;
1095 results.results = _tt_get_partition_db(partition, db);
1097 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
1099 if (results.results == TT_DB_OK) {
1101 _tt_get_object_properties_cache_level(db,
1104 results.cache_level);
1107 // If the cache level in the DB is higher then the passed in
1108 // cache level, then someone else must have updated before
1109 // the callers last read from the DB --> update conflict...
1110 if ((results.results == TT_DB_OK) &&
1111 (results.cache_level > args->cache_level)) {
1112 results.results = TT_DB_ERR_UPDATE_CONFLICT;
1115 // No update conflicts or any other weirdness...
1117 if (results.results == TT_DB_OK) {
1118 _Tt_db_property_ptr property;
1119 _tt_get_rpc_property(args->property, property);
1121 if (!property.is_null()) {
1122 results.results = db->deleteObjectProperty(args->objid,
1127 results.results = TT_DB_ERR_ILLEGAL_PROPERTY;
1130 if (results.results == TT_DB_OK) {
1132 _tt_increment_object_properties_cache_level(db,
1135 results.cache_level);
1139 // The delete object prop function is the only object function that always
1140 // returns that latest object properties. The cache level passed in
1141 // is only used for update conflict detection.
1142 _Tt_db_property_list_ptr properties;
1143 if ((results.results == TT_DB_OK) ||
1144 (results.results == TT_DB_ERR_UPDATE_CONFLICT)) {
1145 _Tt_db_results temp_results = db->getObjectProperties(args->objid,
1149 if (results.results != TT_DB_OK) {
1150 properties = (_Tt_db_property_list *)NULL;
1151 results.results = temp_results;
1154 _tt_set_rpc_properties(properties, results.properties);
1159 _tt_obj_prop_results *_tt_get_obj_prop_1 (_tt_get_obj_prop_args *args,
1160 SVCXPRT * /* transp */)
1162 static _tt_obj_prop_results results;
1163 results.cache_level = -1;
1165 _Tt_string partition = _tt_get_object_partition(args->objid);
1166 _Tt_db_server_db_ptr db;
1167 results.results = _tt_get_partition_db(partition, db);
1169 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
1171 if (results.results == TT_DB_OK) {
1173 _tt_get_object_properties_cache_level(db,
1176 results.cache_level);
1179 _Tt_db_property_ptr property;
1181 // Only return values if the DB cache level is higher then the
1182 // callers cache level
1183 if ((results.results == TT_DB_OK) &&
1184 (results.cache_level > args->cache_level)) {
1185 results.results = db->getObjectProperty(args->objid,
1190 _tt_set_rpc_property(property, results.property);
1195 _tt_obj_props_results *_tt_get_obj_props_1 (_tt_get_obj_props_args *args,
1196 SVCXPRT * /* transp */)
1198 static _tt_obj_props_results results;
1199 results.cache_level = -1;
1201 _Tt_string partition = _tt_get_object_partition(args->objid);
1202 _Tt_db_server_db_ptr db;
1203 results.results = _tt_get_partition_db(partition, db);
1205 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
1207 if (results.results == TT_DB_OK) {
1209 _tt_get_object_properties_cache_level(db,
1212 results.cache_level);
1215 _Tt_db_property_list_ptr properties;
1217 // Only return values if the DB cache level is higher then the
1218 // callers cache level
1219 if ((results.results == TT_DB_OK) &&
1220 (results.cache_level > args->cache_level)) {
1221 results.results = db->getObjectProperties(args->objid,
1225 _tt_set_rpc_properties(properties, results.properties);
1230 _tt_db_results *_tt_set_obj_type_1 (_tt_set_obj_type_args *args,
1231 SVCXPRT * /* transp */)
1233 static _tt_db_results results;
1235 _Tt_string partition = _tt_get_object_partition(args->objid);
1236 _Tt_db_server_db_ptr db;
1237 results = _tt_get_partition_db(partition, db);
1239 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
1241 if (results == TT_DB_OK) {
1242 _Tt_db_property_ptr property = new _Tt_db_property;
1243 property->name = TT_DB_OBJECT_TYPE_PROPERTY;
1244 property->values->append(_Tt_string(args->otype));
1246 results = db->setObjectProperty(args->objid, property, accessPtr);
1252 _tt_obj_type_results *_tt_get_obj_type_1 (_tt_get_obj_type_args *args,
1253 SVCXPRT * /* transp */)
1255 static _tt_obj_type_results results;
1257 _Tt_string partition = _tt_get_object_partition(args->objid);
1258 _Tt_db_server_db_ptr db;
1259 results.results = _tt_get_partition_db(partition, db);
1261 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
1263 if (results.results == TT_DB_OK) {
1264 _Tt_db_property_ptr property;
1265 results.results = db->getObjectProperty(args->objid,
1266 TT_DB_OBJECT_TYPE_PROPERTY,
1270 results.otype = (char *)NULL;
1271 if (results.results == TT_DB_OK) {
1272 if (!property.is_null() && !property->is_empty()) {
1273 _Tt_string otype = (*property->values) [0];
1274 int length = otype.len();
1276 results.otype = (char *)malloc(length+1);
1277 memcpy(results.otype, (char *)otype, length);
1278 results.otype [length] = '\0';
1281 else if (results.results == TT_DB_ERR_NO_SUCH_PROPERTY) {
1282 results.results = TT_DB_ERR_NO_OTYPE;
1289 _tt_db_results *_tt_set_obj_file_1 (_tt_set_obj_file_args *args,
1290 SVCXPRT * /* transp */)
1292 static _tt_db_results results;
1294 _Tt_string partition = _tt_get_object_partition(args->objid);
1295 _Tt_db_server_db_ptr db;
1296 results = _tt_get_partition_db(partition, db);
1298 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
1300 if (results == TT_DB_OK) {
1301 results = db->setObjectFile(args->objid, args->file, accessPtr);
1307 _tt_obj_file_results *_tt_get_obj_file_1 (_tt_get_obj_file_args *args,
1308 SVCXPRT * /* transp */)
1310 static _tt_obj_file_results results;
1312 _Tt_string partition = _tt_get_object_partition(args->objid);
1313 _Tt_db_server_db_ptr db;
1314 results.results = _tt_get_partition_db(partition, db);
1316 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
1318 if (results.results == TT_DB_OK) {
1320 results.results = db->getObjectFile(args->objid,
1324 results.file = (char *)NULL;
1325 if (results.results == TT_DB_OK) {
1327 results.file = strdup((char *)file);
1335 _tt_db_results *_tt_set_obj_access_1 (_tt_set_obj_access_args *args,
1336 SVCXPRT * /* transp */)
1338 static _tt_db_results results;
1340 _Tt_string partition = _tt_get_object_partition(args->objid);
1341 _Tt_db_server_db_ptr db;
1342 results = _tt_get_partition_db(partition, db);
1344 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
1346 _Tt_db_access_ptr new_access;
1347 if (results == TT_DB_OK) {
1348 _tt_get_rpc_access(args->new_access, new_access);
1350 if ((new_access->user == (uid_t)-1) ||
1351 (new_access->group == (gid_t)-1) ||
1352 (new_access->mode == (mode_t)-1)) {
1353 _Tt_db_access_ptr current_access;
1354 results = db->getObjectAccess(args->objid,
1358 if (results == TT_DB_OK) {
1359 if (new_access->user == (uid_t)-1) {
1360 new_access->user = current_access->user;
1363 if (new_access->group == (gid_t)-1) {
1364 new_access->group = current_access->group;
1367 if (new_access->mode == (mode_t)-1) {
1368 new_access->mode = current_access->mode;
1373 if (results == TT_DB_OK) {
1374 results = db->setObjectAccess(args->objid, new_access, accessPtr);
1381 _tt_obj_access_results *_tt_get_obj_access_1 (_tt_get_obj_access_args *args,
1382 SVCXPRT * /* transp */)
1384 static _tt_obj_access_results results;
1386 _Tt_string partition = _tt_get_object_partition(args->objid);
1387 _Tt_db_server_db_ptr db;
1388 results.results = _tt_get_partition_db(partition, db);
1390 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
1392 _Tt_db_access_ptr current_access;
1393 if (results.results == TT_DB_OK) {
1394 results.results = db->getObjectAccess(args->objid,
1398 _tt_set_rpc_access(current_access, results.access);
1403 _tt_is_file_in_db_results *_tt_is_file_in_db_1 (_tt_is_file_in_db_args *args,
1404 SVCXPRT * /* transp */)
1406 static _tt_is_file_in_db_results results;
1408 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
1410 _Tt_string real_file = args->file;
1411 _Tt_string partition = _tt_get_file_partition(args->file);
1412 _Tt_db_server_db_ptr db;
1413 results.results = _tt_get_partition_db(partition, db);
1415 if (results.results == TT_DB_OK) {
1416 // See if the file already exists by trying to get its access info
1417 _Tt_db_access_ptr temp_access;
1418 _Tt_db_results temp_results = db->getFileAccess(real_file,
1422 // If the file exists...
1423 if ((temp_results == TT_DB_OK) ||
1424 (temp_results == TT_DB_ERR_ACCESS_DENIED)) {
1425 results.results = TT_DB_OK;
1428 results.results = temp_results;
1431 // See if the file is a directory
1432 results.directory_flag = _tt_is_file_a_directory(real_file);
1438 _tt_is_obj_in_db_results *_tt_is_obj_in_db_1 (_tt_is_obj_in_db_args *args,
1439 SVCXPRT * /* transp */)
1441 static _tt_is_obj_in_db_results results;
1442 results.forward_pointer = (char *)NULL;
1444 _Tt_string partition = _tt_get_object_partition(args->objid);
1445 _Tt_db_server_db_ptr db;
1446 results.results = _tt_get_partition_db(partition, db);
1448 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
1450 if (results.results == TT_DB_OK) {
1453 // See if the object has an entry in the file-object map
1454 results.results = db->getObjectFile(args->objid,
1458 // If no entry in the file-object map...
1459 if (results.results != TT_DB_OK) {
1460 _Tt_db_property_ptr property;
1462 // See if there is a forward pointer
1463 _Tt_db_results temp_results =
1464 db->getObjectProperty(args->objid,
1465 TT_DB_FORWARD_POINTER_PROPERTY,
1469 // If there is a forward pointer...
1470 if (temp_results == TT_DB_OK) {
1471 _Tt_string forward_pointer = (*property->values) [0];
1472 int length = forward_pointer.len();
1473 results.forward_pointer = (char *)malloc(length+1);
1475 memcpy(results.forward_pointer, (char *)forward_pointer, length);
1476 results.forward_pointer [length] = '\0';
1477 results.results = TT_DB_WRN_FORWARD_POINTER;
1485 _tt_db_results *_tt_queue_message_1 (_tt_queue_msg_args *args,
1486 SVCXPRT * /* transp */)
1488 static _tt_db_results results;
1490 bool_t property_written = FALSE;
1492 _Tt_db_server_db_ptr db;
1493 _Tt_string real_file = args->file;
1494 if (!args->message.body.body_len) {
1495 results = TT_DB_ERR_ILLEGAL_MESSAGE;
1498 _Tt_string partition = _tt_get_file_partition(args->file);
1499 results = _tt_get_partition_db(partition, db);
1502 if (results == TT_DB_OK) {
1503 _Tt_db_access_ptr accessPtr = _tt_get_unix_file_access(real_file);
1505 // Set the DB file access to be the same as the actual file. This
1506 // allows an easy method of controlled message security
1507 if (!accessPtr.is_null()) {
1508 results = db->setFileAccess(real_file, accessPtr, accessPtr);
1512 _Tt_db_access_ptr accessPtr = new _Tt_db_access;
1513 accessPtr->user = _tt_uid;
1514 accessPtr->group = _tt_gid;
1516 // Create a new message info structure for the new message
1517 _Tt_db_message_info_ptr message_info = new _Tt_db_message_info;
1518 if (results == TT_DB_OK) {
1521 // Get the current information on queued messages
1522 _Tt_db_property_ptr property;
1523 _Tt_string name = TT_DB_MESSAGE_INFO_PROPERTY;
1524 results = db->getFileProperty(real_file, name, accessPtr, property);
1526 // Default new message ID if there are none in the queue
1529 if (results == TT_DB_OK) {
1530 // Calculate the index for the last message info structure in
1532 int index = property->values->count() - 1;
1535 // Un-XDR the message info into the "last_message_info" object
1536 // and set the new message ID to the message ID in in
1537 // "last_message_info" + 1.
1538 _Tt_string message_info_bytes = (*property->values) [index];
1539 xdrmem_create(&xdrs,
1540 (char *)message_info_bytes,
1541 (u_int)message_info_bytes.len(),
1543 _Tt_db_message_info_ptr last_message_info = new _Tt_db_message_info;
1544 (void)last_message_info->xdr(&xdrs);
1545 message_id = last_message_info->messageID + 1;
1549 // It doesn't matter if there were no queued messages, as long as
1550 // there were no fatal errors
1551 if ((results == TT_DB_OK) ||
1552 (results == TT_DB_ERR_NO_SUCH_PROPERTY)) {
1555 // Put the new message info into the message info structure
1556 message_info->messageID = message_id;
1557 message_info->numParts = (args->message.body.body_len / ISMAXRECLEN) + 1;
1558 message_info->messageSize = args->message.body.body_len;
1559 _tt_get_rpc_strings(args->ptypes, message_info->ptypes);
1561 // Get the XDR size of the new message info structure
1563 _Tt_xdr_size_stream xdrsz;
1564 if (!message_info->xdr((XDR *)xdrsz)) {
1565 results = TT_DB_ERR_ILLEGAL_MESSAGE;
1567 length = (unsigned int) xdrsz.getsize();
1570 // XDR the message info structure into "temp_string"
1571 _Tt_string temp_string((int)length);
1572 if (results != TT_DB_ERR_ILLEGAL_MESSAGE) {
1573 xdrmem_create(&xdrs, (char *)temp_string, length, XDR_ENCODE);
1574 if (!message_info->xdr(&xdrs)) {
1575 results = TT_DB_ERR_ILLEGAL_MESSAGE;
1579 if (results != TT_DB_ERR_ILLEGAL_MESSAGE) {
1580 // Add the XDR'd message info to the message info property
1581 _Tt_db_property_ptr property = new _Tt_db_property;
1582 property->name = TT_DB_MESSAGE_INFO_PROPERTY;
1583 property->values->append(temp_string);
1585 results = db->addFileProperty(real_file, property, FALSE, accessPtr);
1586 property_written = TRUE;
1591 if (results == TT_DB_OK) {
1592 int length = ISMAXRECLEN;
1594 // Break up the message into ISMAXRECLEN sized parts and store
1595 // as separate properties
1597 (results == TT_DB_OK) && (i < message_info->numParts);
1599 // If this is the last part, it is probably shorter then
1600 // ISMAXRECLEN, so calculate the exact length
1601 if (i == message_info->numParts-1) {
1602 length = message_info->messageSize - (i * ISMAXRECLEN);
1605 // Copy the message part into a buffer
1606 _Tt_string message_part(length);
1607 memcpy((char *)message_part,
1608 args->message.body.body_val+i*ISMAXRECLEN,
1611 // Construct a property name of the form:
1613 // _TT_MSG_<ID#>_<PART#>
1616 sprintf(name, TT_DB_MESSAGE_PROPERTY, message_info->messageID, i);
1618 // Store the property
1619 _Tt_db_property_ptr property = new _Tt_db_property;
1620 property->name = name;
1621 property->values->append(message_part);
1623 results = db->setFileProperty(real_file, property, accessPtr);
1624 property_written = TRUE;
1628 if (property_written && (results == TT_DB_OK)) {
1630 results = _tt_increment_file_properties_cache_level(db,
1639 _tt_dequeue_msgs_results *
1640 _tt_dequeue_messages_1 (_tt_dequeue_msgs_args *args,
1641 SVCXPRT * /* transp */)
1643 static _tt_dequeue_msgs_results results;
1644 results.messages.messages_val = (_tt_message *)NULL;
1645 results.messages.messages_len = 0;
1647 bool_t property_written = FALSE;
1649 _Tt_string real_file = args->file;
1650 _Tt_string partition = _tt_get_file_partition(args->file);
1651 _Tt_db_server_db_ptr db;
1652 results.results = _tt_get_partition_db(partition, db);
1654 if (results.results == TT_DB_OK) {
1655 _Tt_db_access_ptr accessPtr = _tt_get_unix_file_access(real_file);
1657 // Set the DB file access to be the same as the actual file. This
1658 // allows an easy method of control for queued message security
1659 if (!accessPtr.is_null()) {
1660 results.results = db->setFileAccess(real_file,
1666 _Tt_db_access_ptr accessPtr = new _Tt_db_access;
1667 accessPtr->user = _tt_uid;
1668 accessPtr->group = _tt_gid;
1670 // Get the message info property
1671 _Tt_db_property_ptr property;
1672 if (results.results == TT_DB_OK) {
1673 _Tt_string name = TT_DB_MESSAGE_INFO_PROPERTY;
1674 results.results = db->getFileProperty(real_file,
1680 _Tt_db_message_info_ptr message_info = new _Tt_db_message_info;
1681 _Tt_string_list_ptr messages;
1683 if (results.results == TT_DB_ERR_NO_SUCH_PROPERTY) {
1684 results.results = TT_DB_OK;
1686 else if (results.results == TT_DB_OK) {
1687 _Tt_string_list_ptr dequeue_ptypes;
1688 _tt_get_rpc_strings(args->ptypes, dequeue_ptypes);
1690 _Tt_string_list_cursor dequeue_ptypes_cursor(dequeue_ptypes);
1692 // Loop through the message info property (effectively looping
1693 // through the message info entries)
1694 _Tt_string_list_cursor values_cursor(property->values);
1695 while (values_cursor.next()) {
1698 // Un-XDR a message info structure
1699 xdrmem_create(&xdrs,
1700 (char *)*values_cursor,
1701 (*values_cursor).len(),
1703 (void)message_info->xdr(&xdrs);
1705 // Eliminate all of the ptypes from the message info list
1706 // that match the callers ptype list.
1707 bool_t ptype_matched = FALSE;
1708 _Tt_string_list_cursor ptypes_cursor(message_info->ptypes);
1709 while (ptypes_cursor.next()) {
1710 while (dequeue_ptypes_cursor.next()) {
1711 if (*dequeue_ptypes_cursor == *ptypes_cursor) {
1712 ptypes_cursor.remove();
1713 ptype_matched = TRUE;
1719 // A ptype matched, this message is to be returned...
1720 if (ptype_matched) {
1721 if (messages.is_null()) {
1722 messages = new _Tt_string_list;
1725 // Reconstruct the message from the _TT_MSG_<ID#>_<PART#> properties
1726 _Tt_string message(message_info->messageSize);
1727 for (int i=0; (results.results == TT_DB_OK) &&
1728 (i < message_info->numParts); i++) {
1729 // Construct the property name
1731 sprintf(name, TT_DB_MESSAGE_PROPERTY, message_info->messageID, i);
1733 // Get the property value
1734 _Tt_db_property_ptr property;
1735 results.results = db->getFileProperty(real_file,
1739 if (results.results == TT_DB_OK) {
1740 _Tt_string message_bytes = (*property->values) [0];
1742 // Copy each succesive part into a large buffer
1743 memcpy((char *)message+i*ISMAXRECLEN,
1744 (char *)message_bytes,
1745 message_bytes.len());
1749 // Append the re-assembled message to the return list
1750 if (results.results == TT_DB_OK) {
1751 messages->append(message);
1755 // No more ptypes left for this message, dequeue it...
1756 if (message_info->ptypes->is_empty()) {
1757 values_cursor.remove();
1759 // Otherwise, update the property value with an updated version
1760 // of the message_info structure
1764 _Tt_xdr_size_stream xdrsz;
1766 // Get the XDR size of the updated message info structure
1767 (void)message_info->xdr((XDR *)xdrsz);
1768 length = (unsigned int) xdrsz.getsize();
1770 // XDR the message info structure into "temp_string"
1771 _Tt_string temp_string((int)length);
1772 xdrmem_create(&xdrs, (char *)temp_string, length, XDR_ENCODE);
1773 if (!message_info->xdr(&xdrs)) {
1774 // Update the property value
1775 *values_cursor = temp_string;
1780 // Put the message info property back into the DB. If all of
1781 // the message info structures have been deleted from the
1782 // property, then this should effectively delete the property.
1783 results.results = db->setFileProperty(real_file,
1786 property_written = TRUE;
1788 if (!messages.is_null()) {
1789 if ((results.results == TT_DB_OK) && !messages->is_empty()) {
1790 // Allocate enough space to transport the messages back to the
1792 results.messages.messages_val = (_tt_message *)
1793 malloc(sizeof(_tt_message)*
1795 results.messages.messages_len = messages->count();
1797 // Put the messages into the results structure
1799 _Tt_string_list_cursor messages_cursor(messages);
1800 while (messages_cursor.next()) {
1801 results.messages.messages_val [i].body.body_val =
1802 (char *)malloc((*messages_cursor).len());
1803 results.messages.messages_val [i].body.body_len =
1804 (*messages_cursor).len();
1805 memcpy(results.messages.messages_val [i].body.body_val,
1806 (char *)*messages_cursor,
1807 (*messages_cursor).len());
1814 if (property_written && (results.results == TT_DB_OK)) {
1816 results.results = _tt_increment_file_properties_cache_level(db,
1825 // Since we're calling the wrapped API calls, bringing in tt_c.h
1826 // doesn't get us the declarations we need, so we have to bring
1827 // these two in manually like this.
1829 extern char * _tt_file_netfile(const char *);
1830 extern char * _tt_netfile_file(const char *);
1831 extern Tt_status _tt_pointer_error(void *p);
1832 extern char * _tt_status_message(Tt_status s);
1835 // Call the API routine _tt_file_netfile() and return the
1837 _tt_file_netfile_results *
1838 _tt_file_netfile_1 (_tt_file_netfile_args *args, SVCXPRT * /* transp */)
1842 printf("DEBUG: SERVER: _tt_file_netfile_1: calling _tt_file_netfile(%s)\n",
1843 (char *) args->file_or_netfile);
1846 static _tt_file_netfile_results results;
1847 static char * canonical_path;
1849 // we have a netfilename, get the local file version...
1850 canonical_path = _tt_file_netfile(args->file_or_netfile);
1853 printf("DEBUG: SERVER: _tt_file_netfile_1: _tt_file_netfile(%s) returned %s\n",
1854 args->file_or_netfile, canonical_path);
1858 if (_tt_pointer_error(canonical_path) != TT_OK) {
1859 results.results = TT_DB_ERR_ILLEGAL_FILE;
1860 results.result_string = NULL;
1862 results.results = TT_DB_OK;
1863 results.result_string = canonical_path;
1865 results.tt_status = (int) _tt_pointer_error(canonical_path);
1868 printf("\t results.tt_status == %s\n",
1869 _tt_status_message(_tt_pointer_error(canonical_path)));
1876 // Call the API routine _tt_netfile_file() and return the
1878 _tt_file_netfile_results *
1879 _tt_netfile_file_1 (_tt_file_netfile_args *args, SVCXPRT * /* transp */)
1883 printf("DEBUG: SERVER: _tt_netfile_file_1: calling _tt_netfile_file(%s)\n",
1884 (char *) args->file_or_netfile);
1887 static _tt_file_netfile_results results;
1888 static char * canonical_path;
1890 // we have a netfilename, get the local file version...
1891 canonical_path = _tt_netfile_file(args->file_or_netfile);
1894 printf("DEBUG: SERVER: _tt_netfile_file_1: _tt_netfile_file(%s) returned %s\n",
1895 args->file_or_netfile, canonical_path);
1898 if (_tt_pointer_error(canonical_path) != TT_OK) {
1899 results.results = TT_DB_ERR_ILLEGAL_FILE;
1900 results.result_string = NULL;
1902 results.results = TT_DB_OK;
1903 results.result_string = canonical_path;
1905 results.tt_status = (int) _tt_pointer_error(canonical_path);
1908 printf("\t results.tt_status == %s\n",
1909 _tt_status_message(_tt_pointer_error(canonical_path)));
1917 // Delete the named session from the properties table.
1919 _tt_delete_session_results *
1920 _tt_delete_session_1(_tt_delete_session_args *args,
1921 SVCXPRT * /*NOTUSED*/)
1923 static _tt_delete_session_results results;
1924 Table_oid_prop record;
1927 int propLen = strlen(propTable);
1933 results.tt_status = TT_DB_OK;
1936 // For each property_table that we manage,
1937 // Compare the sessionID with the session that
1938 // we just found to be dead, and delete it.
1940 for (fileOffset = 0; fileOffset < _TT_MAX_ISFD; fileOffset++) {
1942 pathName = _tt_db_table[fileOffset].db_path;
1944 if (pathName && strlen(pathName) > 0) {
1945 if (_tt_db_table[fileOffset].client_has_open
1946 || _tt_db_table[fileOffset].server_has_open) {
1949 // Is the file name ".../property_table*" ?
1951 lastSlash = strrchr(pathName, '/');
1954 if (strncmp(propTable,lastSlash,propLen)==0) {
1956 // Get the FD and process the file.
1957 isfd=cached_isopen(pathName, ISINOUT);
1960 // Get the 1st record.
1963 isread(isfd, (char *)&record, ISFIRST);
1964 ((char *)(&record))[isreclen] = '\0';
1966 // Delte the named session.
1967 if (strcmp(sesProp, record.propname) == 0) {
1968 if (strcmp(args->session.value, record.propval) == 0) {
1974 // Unconditionally delete ALL _MODIFICATION_DATE's
1975 if (strcmp(modDate, record.propname) == 0) {
1984 if (isread(isfd, (char *)&record,ISNEXT) != 0) {
1988 ((char *)(&record))[isreclen] = '\0';
1989 if (strcmp(sesProp, record.propname) == 0) {
1990 if(strcmp(args->session.value,
1991 record.propval) == 0) {
1997 // Unconditionally delete ALL
1998 // _MODIFICATION_DATE's
1999 if (strcmp(modDate, record.propname) == 0) {
2005 cached_isclose(isfd);
2015 // *All* is an over statment.
2016 // It returns up to OPT_MAX_GET_SESSIONS sessions and the oidkey to use
2019 _tt_get_all_sessions_results *
2020 _tt_get_all_sessions_1(_tt_get_all_sessions_args * args,
2021 SVCXPRT * /*NOTUSED*/)
2023 static _tt_get_all_sessions_results results;
2025 static _Tt_string_list *list;
2026 list = new _Tt_string_list;
2030 int recordCount = 0;
2031 int propLen = strlen(propTable);
2036 _Tt_string propValue;
2037 Table_oid_prop record;
2040 // Empty out any existing session or key results.
2043 if (results.oidkey.oidkey_val != NULL) {
2044 free((char *)results.oidkey.oidkey_val);
2046 for (offset = 0 ; offset < list->count() ; offset++) {
2047 if (results.session_list.values_val[offset].value != NULL) {
2048 free(results.session_list.values_val[offset].value);
2051 if (results.session_list.values_val != NULL) {
2052 free((char *)results.session_list.values_val);
2053 results.session_list.values_val = NULL;
2055 memset(&results.oidkey, '\0', sizeof(results.oidkey));
2058 // For each property_table that we manage,
2059 // pull out all of the session-ids and pass them back (up
2060 // to OPT_MAX_GET_SESSIONS passed back in each call)
2062 for (offset = 0 ; offset < _TT_MAX_ISFD; offset++) {
2064 pathName = _tt_db_table[offset].db_path;
2066 if (pathName && strlen(pathName) > 0) {
2067 if (_tt_db_table[offset].client_has_open
2068 || _tt_db_table[offset].server_has_open) {
2071 // Is the file name ".../property_table*" ?
2073 lastSlash = strrchr(pathName, '/');
2076 if (strncmp(propTable, lastSlash, propLen) == 0) {
2078 // Get the FD and process the file.
2079 isfd = cached_isopen(pathName, ISINOUT);
2082 // If the user passed in a starting key,
2085 if (args->oidkey.oidkey_len > 0
2086 && args->oidkey.oidkey_val != NULL) {
2088 (char *)args->oidkey.oidkey_val);
2092 // Get the 1st record.
2094 isread(isfd, (char *)&record, ISFIRST);
2095 ((char *)(&record))[isreclen] = '\0';
2096 if (strcmp(sesProp, record.propname) == 0) {
2097 propValue = record.propval;
2099 // Append it to the list to send back.
2101 list->append(propValue);
2102 memset(&record, '\0', sizeof(record));
2105 while(isread(isfd, (char *)&record,ISNEXT) != -1) {
2106 ((char *)(&record))[isreclen] = '\0';
2107 if (strcmp(sesProp, record.propname) == 0) {
2108 propValue = record.propval;
2109 list->append(propValue);
2110 if (++recordCount > OPT_MAX_GET_SESSIONS-1) {
2111 results.oidkey.oidkey_val = NULL;
2113 (int *)&results.oidkey.oidkey_len,
2114 (char **)&results.oidkey.oidkey_val);
2119 memset(&record, '\0', sizeof(record));
2121 cached_isclose(isfd);
2122 if (recordCount > OPT_MAX_GET_SESSIONS-1) {
2130 results.session_list.values_len = list->count();
2131 if (results.session_list.values_len > 0) {
2132 results.session_list.values_val = (_tt_string *)malloc(sizeof(_tt_string *) * list->count());
2134 results.session_list.values_val = (_tt_string *)NULL;
2136 for (offset = 0 ; offset < results.session_list.values_len ; offset++) {
2137 propValue = list->top();
2138 results.session_list.values_val[offset].value = strdup(propValue);
2145 _tt_garbage_collect_results *
2146 _tt_garbage_collect_1(void * /*NOTUSED*/,
2147 SVCXPRT * /*NOTUSED*/)
2149 static _tt_garbage_collect_results results;
2152 memset(&results, '\0', sizeof(_tt_garbage_collect_results));
2154 #if defined(OPT_GARBAGE_THREADS)
2158 // Collect the garbage and delete old sessions in
2159 // a separate thread. As soon as the thread is started
2160 // this function returns and the dbserver is again
2161 // processing user requests.
2162 id = _tt_run_garbage_collect(OPT_GARBAGE_IN_PARALLEL);
2163 results.tt_status = (id >= 0) ? TT_OK : TT_ERR_INTERNAL;
2166 // Without threads, just compress (isgarbage) the
2167 // db files. The user program will check for and
2168 // delete old sessions.
2170 isgarbage_collect();
2171 results.tt_status = TT_OK;
2178 // ******* Static helper functions start here *******
2181 bool_t _tt_is_file_a_directory (const _Tt_string &file)
2183 // This is sometimes called with a network path and a non-network path.
2184 // Make sure we always give stat a non-network path.
2185 char *slash = strchr((char *)file, '/');
2186 char *path = strchr((char *)file, ':');
2187 if (path != slash-1) {
2188 path = (char *)NULL;
2190 DIR *dd = opendir(path ? path+1 : (char *)file);
2196 return (dd ? TRUE : FALSE);
2199 // Replace the old partition with the new partition in the object ID
2200 static _Tt_string _tt_make_equivalent_object_id (const _Tt_string &objid,
2201 const _Tt_string &partition)
2203 _Tt_string temp_string = (char *)objid;
2204 _Tt_string new_objid;
2206 temp_string = temp_string.rsplit (':', new_objid);
2207 new_objid = new_objid.cat(partition);
2212 static _Tt_db_results _tt_get_partition_db (const _Tt_string &partition,
2213 _Tt_db_server_db_ptr &db)
2215 _Tt_db_partition_global_map_ref db_map;
2216 _Tt_db_results results = TT_DB_OK;
2218 db = db_map.getDB(partition);
2220 results = TT_DB_ERR_DB_OPEN_FAILED;
2226 static _Tt_db_access_ptr _tt_get_real_rpc_access (const _tt_access &rpc_access)
2228 _Tt_db_access_ptr accessPtr;
2229 _tt_get_rpc_access(rpc_access, accessPtr);
2231 accessPtr->user = _tt_uid;
2232 accessPtr->group = (gid_t)-1;
2234 // Make sure the group ID is valid before using it
2235 for (int i=0; i < _tt_gidlen; i++) {
2236 if (_tt_gidlist [i] == _tt_gid) {
2237 accessPtr->group = _tt_gid;
2244 static _Tt_db_access_ptr _tt_get_file_access (const _Tt_string &file,
2245 const _tt_access &rpc_access)
2247 _Tt_db_access_ptr accessPtr = _tt_get_unix_file_access(file);
2249 if (accessPtr.is_null()) {
2250 accessPtr = _tt_get_real_rpc_access(rpc_access);
2253 accessPtr->mode = (mode_t)-1;
2259 static _Tt_db_access_ptr _tt_get_unix_file_access (const _Tt_string &file)
2261 _Tt_db_access_ptr accessPtr;
2263 struct stat stat_buf;
2265 // Make sure we always give stat a non-network path.
2266 _Tt_string local_path = file;
2268 if (_tt_is_network_path(file)) {
2269 _Tt_string temp_string;
2270 local_path = local_path.split(':', temp_string);
2273 if (!stat((char *)local_path, &stat_buf)) {
2274 accessPtr = new _Tt_db_access;
2275 accessPtr->user = stat_buf.st_uid;
2276 accessPtr->group = stat_buf.st_gid;
2277 accessPtr->mode = stat_buf.st_mode;
2283 static _Tt_string _tt_get_file_partition (const _Tt_string &file)
2285 _Tt_string temp_string;
2286 _Tt_string local_path = file;
2287 local_path = local_path.split(':', temp_string);
2290 _Tt_file_system_entry_ptr entry = fs.bestMatchToPath(local_path);
2292 return entry->getMountPoint();
2295 static _Tt_db_results
2296 _tt_increment_file_properties_cache_level
2297 (const _Tt_db_server_db_ptr &db,
2298 const _Tt_string &file,
2299 const _Tt_db_access_ptr &accessPtr,
2304 _Tt_db_property_ptr property;
2305 _Tt_db_results results =
2306 db->getFileProperty(file,
2307 TT_DB_PROPS_CACHE_LEVEL_PROPERTY,
2311 if (results == TT_DB_OK) {
2312 _Tt_string cache_level_bytes = (*property->values) [0];
2313 memcpy ((char *)&cache_level, (char *)cache_level_bytes, sizeof(int));
2316 memcpy ((char *)cache_level_bytes, (char *)&cache_level, sizeof(int));
2317 (*property->values) [0] = cache_level_bytes;
2319 results = db->setFileProperty(file,
2322 if (results != TT_DB_OK) {
2324 results = TT_DB_ERR_PROPS_CACHE_ERROR;
2327 else if (results == TT_DB_ERR_NO_SUCH_PROPERTY) {
2330 _Tt_string value(sizeof(int));
2331 memcpy((char *)value, (char *)&cache_level, sizeof(int));
2333 _Tt_db_property_ptr property = new _Tt_db_property;
2334 property->name = TT_DB_PROPS_CACHE_LEVEL_PROPERTY;
2335 property->values->append(value);
2337 results = db->setFileProperty(file,
2340 if (results != TT_DB_OK) {
2342 results = TT_DB_ERR_PROPS_CACHE_ERROR;
2346 results = TT_DB_ERR_PROPS_CACHE_ERROR;
2352 static _Tt_db_results
2353 _tt_get_file_properties_cache_level (const _Tt_db_server_db_ptr &db,
2354 const _Tt_string &file,
2355 const _Tt_db_access_ptr &accessPtr,
2360 _Tt_db_property_ptr property;
2361 _Tt_db_results results =
2362 db->getFileProperty(file,
2363 TT_DB_PROPS_CACHE_LEVEL_PROPERTY,
2366 if (results == TT_DB_OK) {
2367 _Tt_string cache_level_bytes = (*property->values) [0];
2368 memcpy ((char *)&cache_level, (char *)cache_level_bytes, sizeof(int));
2370 // The file was probably created for an object. The cache level
2371 // was never stored as a property...
2372 else if (results == TT_DB_ERR_NO_SUCH_PROPERTY) {
2373 results = _tt_increment_file_properties_cache_level(db,
2379 results = TT_DB_ERR_PROPS_CACHE_ERROR;
2385 static _Tt_string _tt_get_object_partition (const _Tt_string &objid)
2387 _Tt_string partition = (char *)objid;
2388 _Tt_string temp_string;
2390 // Get rid of file system type and hostname - the partition
2391 // is the only thing left
2392 partition = partition.split(':', temp_string);
2393 partition = partition.split(':', temp_string);
2394 partition = partition.split(':', temp_string);
2399 static _Tt_db_results
2400 _tt_increment_object_properties_cache_level
2401 (const _Tt_db_server_db_ptr &db,
2402 const _Tt_string &objid,
2403 const _Tt_db_access_ptr &accessPtr,
2408 _Tt_db_property_ptr property;
2409 _Tt_db_results results =
2410 db->getObjectProperty(objid,
2411 TT_DB_PROPS_CACHE_LEVEL_PROPERTY,
2415 if (results == TT_DB_OK) {
2416 _Tt_string cache_level_bytes = (*property->values) [0];
2417 memcpy ((char *)&cache_level, (char *)cache_level_bytes, sizeof(int));
2420 memcpy ((char *)cache_level_bytes, (char *)&cache_level, sizeof(int));
2421 (*property->values) [0] = cache_level_bytes;
2423 results = db->setObjectProperty(objid,
2426 if (results != TT_DB_OK) {
2428 results = TT_DB_ERR_PROPS_CACHE_ERROR;
2431 else if (results == TT_DB_ERR_NO_SUCH_PROPERTY) {
2434 _Tt_string value(sizeof(int));
2435 memcpy((char *)value, (char *)&cache_level, sizeof(int));
2437 _Tt_db_property_ptr property = new _Tt_db_property;
2438 property->name = TT_DB_PROPS_CACHE_LEVEL_PROPERTY;
2439 property->values->append(value);
2441 results = db->setObjectProperty(objid,
2444 if (results != TT_DB_OK) {
2446 results = TT_DB_ERR_PROPS_CACHE_ERROR;
2450 results = TT_DB_ERR_PROPS_CACHE_ERROR;
2456 static _Tt_db_results
2457 _tt_get_object_properties_cache_level (const _Tt_db_server_db_ptr &db,
2458 const _Tt_string &objid,
2459 const _Tt_db_access_ptr &accessPtr,
2464 _Tt_db_property_ptr property;
2465 _Tt_db_results results =
2466 db->getObjectProperty(objid,
2467 TT_DB_PROPS_CACHE_LEVEL_PROPERTY,
2471 if (results == TT_DB_OK) {
2472 _Tt_string cache_level_bytes = (*property->values) [0];
2473 memcpy ((char *)&cache_level, (char *)cache_level_bytes, sizeof(int));
2476 results = TT_DB_ERR_PROPS_CACHE_ERROR;
2483 _tt_screen_object_properties (_Tt_db_property_list_ptr &properties)
2485 _Tt_db_property_list_cursor properties_cursor (properties);
2486 while (properties_cursor.next ()) {
2487 if (properties_cursor->name == TT_DB_PROPS_CACHE_LEVEL_PROPERTY) {
2488 properties_cursor.remove ();
2490 else if (properties_cursor->name == TT_DB_OBJECT_TYPE_PROPERTY) {
2491 properties_cursor.remove ();
2495 if (properties->count () == 0) {
2496 properties = (_Tt_db_property_list *)NULL;
2500 static _Tt_string _tt_get_local_path (const _Tt_string &network_path,
2501 _Tt_string &hostname,
2502 _Tt_string &partition)
2504 _Tt_string temp_string = network_path;
2505 _Tt_string local_path = _tt_realpath (temp_string.split(':', hostname));
2507 _Tt_file_system file_system;
2508 _Tt_file_system_entry_ptr entry = file_system.bestMatchToPath(local_path);
2510 partition = entry->getMountPoint();
2512 _Tt_string loop_back_mount_point = entry->getLoopBackMountPoint();
2513 if (loop_back_mount_point.len()) {
2514 // Get the path info after the loop back mount point path
2515 local_path = local_path.right(local_path.len()-loop_back_mount_point.len());
2517 // Replace the loop back mount point path with the partition path
2518 local_path = partition.cat(local_path);
2525 // This is the thread that performs the garbage collection.
2526 // It is defined as a (void *) function for thr_create() compatibility.
2529 _tt_garbage_collect(void * /*NOTUSED*/)
2531 // thr_create() func returns (void *).
2532 void * results = NULL;
2534 _tt_get_all_sessions_args args;
2536 _Tt_string sessionId;
2537 _Tt_string_list *sessions;
2539 memset(&args, '\0', sizeof(args));
2541 #if defined(OPT_GARBAGE_THREADS)
2543 sigset_t new_thr_sigset;
2546 // Tell ourself (this thread only) to ignore all SIGs, or quit.
2548 if (sigfillset(&new_thr_sigset) != 0) {
2552 if (thr_sigsetmask(SIG_BLOCK, &new_thr_sigset, NULL) < 0) {
2557 isgarbage_collect(); // 1st compress the DB files.
2560 _Tt_db_client_ptr dbClient;
2562 if (!dbClient.is_null()
2563 && dbClient->getConnectionResults() == TT_DB_OK) {
2564 // Tell server to compress the files.
2565 dbClient->garbage_collect_in_server();
2568 // Get a list of all sessions.
2571 #if defined(OPT_GARBAGE_THREADS)
2572 _tt_get_all_sessions_results *sessionList;
2574 sessionList = _tt_get_all_sessions_1(&args, NULL);
2577 _Tt_string oneSession;
2579 sessions = new _Tt_string_list;
2582 ; offset < sessionList->session_list.values_len
2584 oneSession = sessionList->session_list.values_val[offset].value;
2585 sessions->append(oneSession);
2588 sessions = dbClient->get_all_sessions();
2590 if (sessions== NULL || sessions->count() == 0) {
2597 // Delete the list of sessions that are dead.
2600 #if defined(OPT_GARBAGE_THREADS)
2601 _tt_delete_session_args delsession;
2604 sessionId = sessions->top();
2605 if ((ttstatus=tt_default_session_set(sessionId)) != TT_OK) {
2607 #if defined(OPT_GARBAGE_THREADS)
2608 delsession.session.value = sessionId;
2609 _tt_delete_session_1(&delsession,NULL);
2611 dbClient->delete_session(sessionId);
2615 } while(sessions->count() > 0);
2617 #if defined(OPT_GARBAGE_THREADS)
2619 // Copy over the re-start key.
2620 // (for more than OPT_MAX_GET_SESSIONS).
2621 memcpy(&args.oidkey,
2622 &sessionList->oidkey,
2623 sizeof(args.oidkey));
2625 } while (args.oidkey.oidkey_len != 0);
2627 #if defined(OPT_GARBAGE_THREADS)
2628 mutex_unlock(&garbage_run_in_process);
2636 // Return the PID or TID of the running garbage collection function.
2639 _tt_run_garbage_collect(int in_parallel)
2641 extern FILE *errstr;
2643 /* Make sure in_parallel is used to quiet warnings */
2646 #if defined(OPT_GARBAGE_THREADS)
2647 static int mutex_inited = 0;
2649 // Error back from mutex_*() and thr_() funcs.
2652 // Times to try thr_create() if it return with EAGAIN.
2653 int create_tries = OPT_SOLARIS_THREADED_TRIES;
2655 if (!mutex_inited) {
2657 // Init the RPC syncronazation mutex lock.
2658 mutex_init(&rpc_client_busy, USYNC_THREAD, 0);
2659 mutex_init(&garbage_run_in_process, USYNC_PROCESS, 0);
2661 // Raise the priority of ourselfs to be higher
2662 // than our new thread.
2663 thr_setprio(thr_self(), 10);
2667 // See if anyone else is running, if so, then do not run
2668 // gabage collection again.
2670 if (mutex_trylock(&garbage_run_in_process) != 0) {
2671 return (_tt_garbage_id);
2677 // Start the thread and keep trying OPT_SOLARIS_THREADED_TRIES,
2678 // or until it works.
2680 while ((err = thr_create((void *)0, // stack_base - use default.
2681 (size_t)0, // stack_size - use default.
2682 _tt_garbage_collect,
2683 (void *)_TT_GARBAGE_COLLECTION_FREQUENCY,// Arg to func.
2684 THR_SUSPENDED|THR_BOUND,
2685 (thread_t *)&_tt_garbage_id)) < 0) {
2687 if (errno == EAGAIN && (--create_tries > 0)) {
2692 _tt_garbage_id = -2;
2694 // Get here only on thr_create() error.
2695 // Unable to create thread.
2697 _tt_syslog(errstr, LOG_ERR, "%s",
2698 catgets(_ttcatd, 5, 8,
2699 "Unable to start garbage collection thread. thr_create()\n"));
2704 // If we are to garbage collect in parallel, then
2705 // let the garbage thread continue at a low priority.
2707 // If we are not to garbage collect in parallel,
2708 // then let the thread run, then the main thread exits.
2710 if (in_parallel == TRUE) {
2711 if (_tt_garbage_id > 0) {
2713 // Lower the priority of garbage collection to lowest.
2714 thr_setprio(_tt_garbage_id, 0);
2717 thr_continue((thread_t)_tt_garbage_id);
2720 if (_tt_garbage_id > 0) {
2721 thr_continue((thread_t)_tt_garbage_id);
2729 #else //defined(OPT_GARBAGE_THREADS)
2731 #if defined(OPT_AUTO_GARBAG_COLLECT)
2733 // Do not start another, if one is running.
2735 if (in_parallel == TRUE) {
2736 if (_tt_garbage_id == -1) {
2738 // FORK and EXEC ourself '-G'.
2740 #if defined(OPT_BUG_AIX) || defined(OPT_BUG_USL) || defined(OPT_BUG_UXP)
2743 switch (_tt_garbage_id = (int)vfork()) {
2746 const char *newargv[3];
2748 newargv[0] = global_argv[0];
2752 execve((const char *)newargv[0],
2753 (char *const *)newargv,
2754 (char *const *)global_envp);
2756 _tt_syslog(errstr, LOG_ERR, "%s",
2757 catgets(_ttcatd, 5, 9,
2758 "Unable to fork() for garbage collection.\n"));
2759 _tt_garbage_id = -3;
2760 _exit(1); // ERROR, so exit new child.
2765 _tt_syslog(errstr, LOG_ERR, "%s",
2766 catgets(_ttcatd, 5, 9,
2767 "Unable to fork() for garbage collection.\n"));
2768 _tt_garbage_id = -4;
2776 #endif /* OPT_AUTO_GARBAGE_COLLECT*/
2777 exit((intptr_t)_tt_garbage_collect(NULL));
2778 #if defined(OPT_AUTO_GARBAG_COLLECT)
2780 #endif /* OPT_AUTO_GARBAGE_COLLECT*/
2782 #endif // ! OPT_GARBAGE_THREADS
2783 return (_tt_garbage_id);