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 int _tt_garbage_id = -1; // TID or PID.
84 int _tt_run_garbage_collect(int in_parallel);
86 static const char * sesProp = _TT_FILEJOIN_PROPNAME;
87 static const char * modDate = _MP_NODE_MOD_PROP;
88 static const char * propTable = "property_table";
90 extern _Tt_db_info _tt_db_table[_TT_MAX_ISFD];
92 static bool_t _tt_is_file_a_directory (const _Tt_string&);
93 static _Tt_string _tt_make_equivalent_object_id(const _Tt_string &objid,
94 const _Tt_string &partition);
95 static _Tt_db_results _tt_get_partition_db (const _Tt_string&,
96 _Tt_db_server_db_ptr&);
97 static _Tt_db_access_ptr
98 _tt_get_real_rpc_access (const _tt_access &rpc_access);
99 static _Tt_db_access_ptr _tt_get_file_access (const _Tt_string &file,
100 const _tt_access &rpc_access);
101 static _Tt_db_access_ptr _tt_get_unix_file_access (const _Tt_string &file);
102 static _Tt_string _tt_get_file_partition (const _Tt_string &file);
103 static _Tt_db_results
104 _tt_increment_file_properties_cache_level (const _Tt_db_server_db_ptr&,
106 const _Tt_db_access_ptr&,
108 static _Tt_db_results
109 _tt_get_file_properties_cache_level (const _Tt_db_server_db_ptr&,
111 const _Tt_db_access_ptr&,
113 static _Tt_string _tt_get_object_partition (const _Tt_string &objid);
114 static _Tt_db_results
115 _tt_increment_object_properties_cache_level (const _Tt_db_server_db_ptr&,
117 const _Tt_db_access_ptr&,
119 static _Tt_db_results
120 _tt_get_object_properties_cache_level (const _Tt_db_server_db_ptr&,
122 const _Tt_db_access_ptr&,
124 static void _tt_screen_object_properties (_Tt_db_property_list_ptr&);
126 static _Tt_string _tt_get_local_path (const _Tt_string &network_path,
127 _Tt_string &hostname,
128 _Tt_string &partition);
130 _tt_auth_level_results *_tt_get_min_auth_level_1 (void * /* dummy_arg */,
131 SVCXPRT * /* transp */)
133 static _tt_auth_level_results results;
134 results.auth_level = _tt_auth_level;
135 results.results = TT_DB_OK;
139 _tt_file_partition_results *_tt_get_file_partition_1 (char **file,
140 SVCXPRT * /* transp */)
142 static _tt_file_partition_results results;
144 _Tt_string hostname = _tt_gethostname();
146 _Tt_string file_hostname;
147 _Tt_string network_path = *file;
148 _Tt_string partition;
149 _Tt_string local_path = _tt_get_local_path (network_path,
152 results.partition = strdup((char *)partition);
154 if (file_hostname == hostname) {
155 network_path = file_hostname.cat(":").cat(local_path);
157 results.network_path = strdup((char *)network_path);
159 results.results = TT_DB_OK;
164 _tt_db_cache_results *_tt_create_file_1 (_tt_create_file_args *args,
165 SVCXPRT * /* transp */)
167 static _tt_db_cache_results results;
168 results.cache_level = -1;
170 _Tt_string real_file = args->file;
171 _Tt_string partition = _tt_get_file_partition(args->file);
172 _Tt_db_server_db_ptr db;
173 results.results = _tt_get_partition_db(partition, db);
175 _Tt_db_access_ptr access = _tt_get_file_access(real_file, args->access);
177 if (results.results == TT_DB_OK) {
178 // See if the file already exists by trying to get its access info
179 _Tt_db_access_ptr temp_access;
180 _Tt_db_results temp_results = db->getFileAccess(real_file,
184 // If the file exists...
185 if ((temp_results == TT_DB_OK) ||
186 (temp_results == TT_DB_ERR_ACCESS_DENIED)) {
187 results.results = TT_DB_ERR_FILE_EXISTS;
189 // Else, if the file does not exist...
190 else if (temp_results == TT_DB_ERR_NO_SUCH_FILE) {
191 results.results = TT_DB_OK;
194 results.results = temp_results;
198 if (results.results == TT_DB_OK) {
199 results.results = db->createFile(real_file, access);
201 if (results.results == TT_DB_OK) {
202 _Tt_db_property_list_ptr properties;
203 _tt_get_rpc_properties(args->properties, properties);
205 if (!properties.is_null()) {
206 results.results = db->setFileProperties(real_file,
211 if (results.results == TT_DB_OK) {
213 _tt_increment_file_properties_cache_level(db,
216 results.cache_level);
224 _tt_db_cache_results *_tt_create_obj_1 (_tt_create_obj_args *args,
225 SVCXPRT * /* transp */)
227 static _tt_db_cache_results results;
228 results.cache_level = -1;
230 _Tt_string partition = _tt_get_object_partition(args->objid);
231 _Tt_db_server_db_ptr db;
232 results.results = _tt_get_partition_db(partition, db);
234 _Tt_string real_file = args->file;
235 _Tt_db_access_ptr object_access = _tt_get_real_rpc_access(args->access);
237 if (results.results == TT_DB_OK) {
238 // See if the object already exists by trying to get the forward
240 _Tt_db_property_ptr temp_property;
241 _Tt_db_results temp_results =
242 db->getObjectProperty(args->objid,
243 TT_DB_FORWARD_POINTER_PROPERTY,
247 // If the property exists, remove the object
248 if (temp_results == TT_DB_OK) {
249 (void)db->removeObject(args->objid, object_access);
251 // Else if the object exists without a forward pointer...
252 else if (temp_results == TT_DB_ERR_NO_SUCH_PROPERTY) {
253 results.results = TT_DB_ERR_OBJECT_EXISTS;
255 // Else if the object does not exist...
256 else if (temp_results == TT_DB_ERR_NO_SUCH_OBJECT) {
257 results.results = TT_DB_OK;
260 results.results = temp_results;
264 if (results.results == TT_DB_OK) {
265 _Tt_db_access_ptr file_access = _tt_get_file_access(real_file,
267 results.results = db->createObject(real_file,
272 if (results.results == TT_DB_OK) {
273 _Tt_db_property_list_ptr properties;
274 _tt_get_rpc_properties(args->properties, properties);
276 if (!properties.is_null()) {
277 _tt_screen_object_properties (properties);
280 if (!properties.is_null()) {
281 results.results = db->setObjectProperties(args->objid,
286 // Set the otype of the object
287 if (results.results == TT_DB_OK) {
288 _Tt_db_property_ptr property = new _Tt_db_property;
289 property->name = TT_DB_OBJECT_TYPE_PROPERTY;
290 property->values->append(_Tt_string(args->otype));
292 results.results = db->setObjectProperty(args->objid,
297 if (results.results == TT_DB_OK) {
299 _tt_increment_object_properties_cache_level(db,
302 results.cache_level);
310 _tt_db_results *_tt_remove_file_1 (_tt_remove_file_args *args,
311 SVCXPRT * /* transp */)
313 static _tt_db_results results;
315 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
317 _Tt_string real_file = args->file;
318 _Tt_string partition = _tt_get_file_partition(args->file);
319 _Tt_db_server_db_ptr db;
320 results = _tt_get_partition_db(partition, db);
322 if (results == TT_DB_OK) {
323 // Get the list of children under the file to remove along with
324 // the file. The list includes the file itself.
325 _Tt_string_list_ptr children;
326 results = db->getFileChildren(real_file, children);
328 if (children->is_empty()) {
329 results = TT_DB_ERR_NO_SUCH_FILE;
332 _Tt_string_list_cursor children_cursor(children);
333 while ((results == TT_DB_OK) && children_cursor.next()) {
334 results = db->removeFile(*children_cursor, accessPtr);
342 _tt_db_results *_tt_remove_obj_1 (_tt_remove_obj_args *args,
343 SVCXPRT * /* transp */)
345 static _tt_db_results results;
347 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
349 _Tt_string partition = _tt_get_object_partition(args->objid);
350 _Tt_db_server_db_ptr db;
351 results = _tt_get_partition_db(partition, db);
353 if (results == TT_DB_OK) {
354 results = db->removeObject(args->objid, accessPtr);
356 if (results == TT_DB_OK) {
357 if (args->forward_pointer && strlen(args->forward_pointer)) {
358 // Allow everyone to read and delete the forward pointer
359 _Tt_db_access_ptr new_access = new _Tt_db_access;
360 new_access->user = (uid_t)-1;
361 new_access->group = (gid_t)-1;
362 new_access->mode = (mode_t)-1;
364 // Create a special forward pointer object with no file...
365 results = db->createObject((char *)NULL,
370 if (results == TT_DB_OK) {
371 _Tt_db_property_ptr property = new _Tt_db_property;
372 property->name = TT_DB_FORWARD_POINTER_PROPERTY;
373 property->values->append(_Tt_string(args->forward_pointer));
375 results = db->setObjectProperty(args->objid, property, accessPtr);
384 _tt_db_results *_tt_move_file_1 (_tt_move_file_args *args,
385 SVCXPRT * /* transp */)
387 static _tt_db_results results;
389 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
391 _Tt_string real_file = args->file;
392 _Tt_string real_new_file = args->new_file;
394 // Make sure we really need to do a move
395 if (real_file != real_new_file) {
397 _Tt_file_system_entry_ptr entry = fs.bestMatchToPath(real_file);
398 _Tt_file_system_entry_ptr new_entry = fs.bestMatchToPath(real_new_file);
400 _Tt_string partition = entry->getMountPoint();
401 _Tt_string new_partition = new_entry->getMountPoint();
403 if (partition == new_partition) {
404 // Get a connection to the partition DB
405 _Tt_db_server_db_ptr db;
406 results = _tt_get_partition_db(partition, db);
408 _Tt_string_list_ptr children;
409 if (results == TT_DB_OK) {
410 // Get a list of the files to move
411 results = db->getFileChildren(real_file, children);
414 if (results == TT_DB_OK) {
415 if (children->is_empty ()) {
416 results = TT_DB_ERR_NO_SUCH_FILE;
419 _Tt_string_list_cursor children_cursor(children);
420 while ((results == TT_DB_OK) && children_cursor.next()) {
421 // Construct the new file name by replacing the part
422 // that equals the "real_file" with the "real_new_file".
423 int length = (*children_cursor).len() - real_file.len();
424 _Tt_string new_child = real_new_file.cat("/");
425 new_child = new_child.cat((*children_cursor).right(length));
427 // Change the file name in the database
428 db->setFileFile(*children_cursor, new_child, accessPtr);
433 // Else, different partitions, therefore we can only move one
434 // non-directory file
435 else if (!_tt_is_file_a_directory(real_file)) {
436 // Get a connections to both partition DBs
437 _Tt_db_server_db_ptr db;
438 results = _tt_get_partition_db(partition, db);
440 _Tt_db_server_db_ptr new_db;
441 if (results == TT_DB_OK) {
442 results = _tt_get_partition_db(new_partition, new_db);
445 if (results == TT_DB_OK) {
446 _Tt_db_property_list_ptr properties;
447 _Tt_db_access_ptr current_access;
448 _Tt_string_list_ptr objids;
450 // Get all of the file's possesions
451 results = db->getFileProperties(real_file, accessPtr, properties);
452 if (results == TT_DB_OK) {
453 results = db->getFileAccess(real_file, accessPtr, current_access);
455 if (results == TT_DB_OK) {
456 results = db->getFileObjects(real_file, accessPtr, objids);
459 // Create the new file
460 if (results == TT_DB_OK) {
461 results = new_db->createFile(real_new_file, current_access);
464 // Copy the old file's properties to the new file
465 if (results == TT_DB_OK) {
466 results = new_db->setFileProperties(real_new_file,
471 // Create the new objects with equivalent objids on the new partition
472 _Tt_string_list_ptr new_objids;
473 if (results == TT_DB_OK && (!objids->is_empty())) {
474 new_objids = new _Tt_string_list;
476 // Loop through the file's objects
477 _Tt_string_list_cursor objids_cursor(objids);
478 while ((results == TT_DB_OK) && objids_cursor.next()) {
479 _Tt_string new_objid =
480 _tt_make_equivalent_object_id(*objids_cursor, new_partition);
481 new_objids->append(new_objid);
483 _Tt_db_property_list_ptr properties;
484 _Tt_db_access_ptr current_access;
486 // Get all of the object's possesions
487 results = db->getObjectProperties(*objids_cursor,
490 if (results == TT_DB_OK) {
491 results = db->getObjectAccess(*objids_cursor,
496 // Create the new object
497 if (results == TT_DB_OK) {
498 results = new_db->createObject(real_new_file,
504 // Copy the old object's properties to the new object
505 if (results == TT_DB_OK) {
506 results = new_db->setObjectProperties(new_objid,
513 // Remove the old file and all of its objects
514 if (results == TT_DB_OK) {
515 results = db->removeFile(real_file, accessPtr);
518 // Create the forwarding pointers for all of the objects on
520 if ((results == TT_DB_OK) && (!objids->is_empty())) {
521 _Tt_string_list_cursor objids_cursor(objids);
522 _Tt_string_list_cursor new_objids_cursor(new_objids);
524 while ((results == TT_DB_OK) &&
525 objids_cursor.next() &&
526 new_objids_cursor.next()) {
527 // Allow everyone to read and delete the forward pointer
528 _Tt_db_access_ptr new_access = new _Tt_db_access;
529 new_access->user = (uid_t)-1;
530 new_access->group = (gid_t)-1;
531 new_access->mode = (mode_t)-1;
533 // Create a special forward pointer object with no file...
534 results = db->createObject((char *)NULL,
539 if (results == TT_DB_OK) {
540 _Tt_db_property_ptr property = new _Tt_db_property;
541 property->name = TT_DB_FORWARD_POINTER_PROPERTY;
542 property->values->append(*new_objids_cursor);
544 results = db->setObjectProperty(*objids_cursor,
553 results = TT_DB_ERR_ILLEGAL_FILE;
557 results = TT_DB_ERR_SAME_FILE;
563 _tt_db_cache_results *_tt_set_file_props_1 (_tt_set_file_props_args *args,
564 SVCXPRT * /* transp */)
566 static _tt_db_cache_results results;
567 results.cache_level = -1;
569 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
571 _Tt_string real_file = args->file;
572 _Tt_string partition = _tt_get_file_partition(args->file);
573 _Tt_db_server_db_ptr db;
574 results.results = _tt_get_partition_db(partition, db);
576 if (results.results == TT_DB_OK) {
577 _Tt_db_property_list_ptr properties;
578 _tt_get_rpc_properties(args->properties, properties);
580 if (!properties.is_null()) {
581 results.results = db->setFileProperties(real_file,
586 results.results = TT_DB_ERR_ILLEGAL_PROPERTY;
589 if (results.results == TT_DB_OK) {
591 _tt_increment_file_properties_cache_level(db,
594 results.cache_level);
601 _tt_db_cache_results *_tt_set_file_prop_1 (_tt_set_file_prop_args *args,
602 SVCXPRT * /* transp */)
604 static _tt_db_cache_results results;
605 results.cache_level = -1;
607 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
609 _Tt_string real_file = args->file;
610 _Tt_string partition = _tt_get_file_partition(args->file);
611 _Tt_db_server_db_ptr db;
612 results.results = _tt_get_partition_db(partition, db);
614 if (results.results == TT_DB_OK) {
615 _Tt_db_property_ptr property;
616 _tt_get_rpc_property(args->property, property);
618 if (!property.is_null()) {
619 results.results = db->setFileProperty(real_file,
624 results.results = TT_DB_ERR_ILLEGAL_PROPERTY;
627 if (results.results == TT_DB_OK) {
629 _tt_increment_file_properties_cache_level(db,
632 results.cache_level);
639 _tt_db_cache_results *_tt_add_file_prop_1 (_tt_add_file_prop_args *args,
640 SVCXPRT * /* transp */)
642 static _tt_db_cache_results results;
643 results.cache_level = -1;
645 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
647 _Tt_string real_file = args->file;
648 _Tt_string partition = _tt_get_file_partition(args->file);
649 _Tt_db_server_db_ptr db;
650 results.results = _tt_get_partition_db(partition, db);
652 if (results.results == TT_DB_OK) {
653 _Tt_db_property_ptr property;
654 _tt_get_rpc_property(args->property, property);
656 if (!property.is_null()) {
657 results.results = db->addFileProperty(real_file,
663 results.results = TT_DB_ERR_ILLEGAL_PROPERTY;
666 if (results.results == TT_DB_OK) {
668 _tt_increment_file_properties_cache_level(db,
671 results.cache_level);
678 _tt_db_cache_results *_tt_delete_file_prop_1 (_tt_del_file_prop_args *args,
679 SVCXPRT * /* transp */)
681 static _tt_db_cache_results results;
682 results.cache_level = -1;
684 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
686 _Tt_string real_file = args->file;
687 _Tt_string partition = _tt_get_file_partition(args->file);
688 _Tt_db_server_db_ptr db;
689 results.results = _tt_get_partition_db(partition, db);
691 if (results.results == TT_DB_OK) {
692 _Tt_db_property_ptr property;
693 _tt_get_rpc_property(args->property, property);
695 if (!property.is_null()) {
696 results.results = db->deleteFileProperty(real_file,
701 results.results = TT_DB_ERR_ILLEGAL_PROPERTY;
704 if (results.results == TT_DB_OK) {
706 _tt_increment_file_properties_cache_level(db,
709 results.cache_level);
716 _tt_file_prop_results *_tt_get_file_prop_1 (_tt_get_file_prop_args *args,
717 SVCXPRT * /* transp */)
719 static _tt_file_prop_results results;
720 results.cache_level = -1;
722 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
724 _Tt_string real_file = args->file;
725 _Tt_string partition = _tt_get_file_partition(args->file);
726 _Tt_db_server_db_ptr db;
727 results.results = _tt_get_partition_db(partition, db);
729 if (results.results == TT_DB_OK) {
730 results.results = _tt_get_file_properties_cache_level(db,
733 results.cache_level);
736 _Tt_db_property_ptr property;
737 if ((results.cache_level > args->cache_level) &&
738 (results.results == TT_DB_OK)) {
739 results.results = db->getFileProperty(real_file,
744 _tt_set_rpc_property(property, results.property);
749 _tt_file_props_results *
750 _tt_get_file_props_1 (_tt_get_file_props_args *args,
751 SVCXPRT * /* transp */)
753 static _tt_file_props_results results;
754 results.cache_level = -1;
756 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
758 _Tt_string real_file = args->file;
759 _Tt_string partition = _tt_get_file_partition(args->file);
760 _Tt_db_server_db_ptr db;
761 results.results = _tt_get_partition_db(partition, db);
763 if (results.results == TT_DB_OK) {
764 results.results = _tt_get_file_properties_cache_level(db,
767 results.cache_level);
770 _Tt_db_property_list_ptr properties;
771 if ((results.cache_level > args->cache_level) &&
772 (results.results == TT_DB_OK)) {
773 results.results = db->getFileProperties(real_file,
777 _tt_set_rpc_properties(properties, results.properties);
782 _tt_file_objs_results *_tt_get_file_objs_1 (_tt_get_file_objs_args *args,
783 SVCXPRT * /* transp */)
785 static _tt_file_objs_results results;
787 // Make sure the returned cache level is higher then the callers
788 // cache level, so that the caller will use the returned data
789 results.cache_level = args->cache_level + 1;
791 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
793 _Tt_string real_file = args->file;
794 _Tt_string partition = _tt_get_file_partition(args->file);
795 _Tt_db_server_db_ptr db;
796 results.results = _tt_get_partition_db(partition, db);
798 _Tt_string_list_ptr objids;
799 if ((results.cache_level > args->cache_level) &&
800 (results.results == TT_DB_OK)) {
801 results.results = db->getFileObjects(real_file,
805 _tt_set_rpc_strings(objids, results.objids);
810 _tt_db_results *_tt_set_file_access_1 (_tt_set_file_access_args *args,
811 SVCXPRT * /* transp */)
813 static _tt_db_results results;
815 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
817 _Tt_string real_file = args->file;
818 _Tt_string partition = _tt_get_file_partition(args->file);
819 _Tt_db_server_db_ptr db;
820 results = _tt_get_partition_db(partition, db);
822 _Tt_db_access_ptr new_access;
823 if (results == TT_DB_OK) {
824 _tt_get_rpc_access(args->new_access, new_access);
826 if ((new_access->user == (uid_t)-1) ||
827 (new_access->group == (gid_t)-1) ||
828 (new_access->mode == (mode_t)-1)) {
829 _Tt_db_access_ptr current_access;
830 results = db->getFileAccess(real_file,
834 if (results == TT_DB_OK) {
835 if (new_access->user == (uid_t)-1) {
836 new_access->user = current_access->user;
839 if (new_access->group == (gid_t)-1) {
840 new_access->group = current_access->group;
843 if (new_access->mode == (mode_t)-1) {
844 new_access->mode = current_access->mode;
849 if (results == TT_DB_OK) {
850 results = db->setFileAccess(real_file, new_access, accessPtr);
857 _tt_file_access_results *_tt_get_file_access_1 (_tt_get_file_access_args *args,
858 SVCXPRT * /* transp */)
860 static _tt_file_access_results results;
862 _Tt_string real_file = args->file;
863 _Tt_string partition = _tt_get_file_partition(args->file);
864 _Tt_db_server_db_ptr db;
865 results.results = _tt_get_partition_db(partition, db);
867 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
869 _Tt_db_access_ptr current_access;
870 if (results.results == TT_DB_OK) {
871 results.results = db->getFileAccess(real_file,
875 _tt_set_rpc_access(current_access, results.access);
880 _tt_obj_props_results *_tt_set_obj_props_1 (_tt_set_obj_props_args *args,
881 SVCXPRT * /* transp */)
883 static _tt_obj_props_results results;
884 results.cache_level = -1;
886 _Tt_string partition = _tt_get_object_partition(args->objid);
887 _Tt_db_server_db_ptr db;
888 results.results = _tt_get_partition_db(partition, db);
890 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
892 if (results.results == TT_DB_OK) {
894 _tt_get_object_properties_cache_level(db,
897 results.cache_level);
900 _Tt_db_property_list_ptr properties;
902 // If the cache level in the DB is higher then the passed in
903 // cache level, then someone else must have updated before
904 // the callers last read from the DB --> update conflict...
905 if ((results.results == TT_DB_OK) &&
906 (results.cache_level > args->cache_level)) {
907 results.results = TT_DB_ERR_UPDATE_CONFLICT;
909 _Tt_db_results temp_results = db->getObjectProperties(args->objid,
913 if (results.results != TT_DB_OK) {
914 properties = (_Tt_db_property_list *)NULL;
915 results.results = temp_results;
918 _tt_set_rpc_properties(properties, results.properties);
920 // No update conflicts or any other weirdness...
921 if (results.results == TT_DB_OK) {
922 _tt_get_rpc_properties(args->properties, properties);
924 if (!properties.is_null()) {
925 _tt_screen_object_properties (properties);
928 if (!properties.is_null()) {
929 results.results = db->setObjectProperties(args->objid,
934 results.results = TT_DB_ERR_ILLEGAL_PROPERTY;
937 if (results.results == TT_DB_OK) {
939 _tt_increment_object_properties_cache_level(db,
942 results.cache_level);
949 _tt_obj_props_results *_tt_set_obj_prop_1 (_tt_set_obj_prop_args *args,
950 SVCXPRT * /* transp */)
952 static _tt_obj_props_results results;
953 results.cache_level = -1;
955 _Tt_string partition = _tt_get_object_partition(args->objid);
956 _Tt_db_server_db_ptr db;
957 results.results = _tt_get_partition_db(partition, db);
959 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
961 if (results.results == TT_DB_OK) {
963 _tt_get_object_properties_cache_level(db,
966 results.cache_level);
969 _Tt_db_property_list_ptr properties;
971 // If the cache level in the DB is higher then the passed in
972 // cache level, then someone else must have updated before
973 // the callers last read from the DB --> update conflict...
974 if ((results.results == TT_DB_OK) &&
975 (results.cache_level > args->cache_level)) {
976 results.results = TT_DB_ERR_UPDATE_CONFLICT;
978 _Tt_db_results temp_results = db->getObjectProperties(args->objid,
982 if (results.results != TT_DB_OK) {
983 properties = (_Tt_db_property_list *)NULL;
984 results.results = temp_results;
987 _tt_set_rpc_properties(properties, results.properties);
989 // No update conflicts or any other weirdness...
990 if (results.results == TT_DB_OK) {
991 _Tt_db_property_ptr property;
992 _tt_get_rpc_property(args->property, property);
994 if (!property.is_null()) {
995 results.results = db->setObjectProperty(args->objid,
1000 results.results = TT_DB_ERR_ILLEGAL_PROPERTY;
1003 if (results.results == TT_DB_OK) {
1005 _tt_increment_object_properties_cache_level(db,
1008 results.cache_level);
1015 _tt_obj_props_results *_tt_add_obj_prop_1 (_tt_add_obj_prop_args *args,
1016 SVCXPRT * /* transp */)
1018 static _tt_obj_props_results results;
1019 results.cache_level = -1;
1021 _Tt_string partition = _tt_get_object_partition(args->objid);
1022 _Tt_db_server_db_ptr db;
1023 results.results = _tt_get_partition_db(partition, db);
1025 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
1027 if (results.results == TT_DB_OK) {
1029 _tt_get_object_properties_cache_level(db,
1032 results.cache_level);
1035 _Tt_db_property_list_ptr properties;
1037 // If the cache level in the DB is higher then the passed in
1038 // cache level, then someone else must have updated before
1039 // the callers last read from the DB --> update conflict...
1040 if ((results.results == TT_DB_OK) &&
1041 (results.cache_level > args->cache_level)) {
1042 results.results = TT_DB_ERR_UPDATE_CONFLICT;
1044 _Tt_db_results temp_results = db->getObjectProperties(args->objid,
1048 if (results.results != TT_DB_OK) {
1049 properties = (_Tt_db_property_list *)NULL;
1050 results.results = temp_results;
1053 _tt_set_rpc_properties(properties, results.properties);
1055 // No update conflicts or any other weirdness...
1056 if (results.results == TT_DB_OK) {
1057 _Tt_db_property_ptr property;
1058 _tt_get_rpc_property(args->property, property);
1060 if (!property.is_null()) {
1061 results.results = db->addObjectProperty(args->objid,
1067 results.results = TT_DB_ERR_ILLEGAL_PROPERTY;
1070 if (results.results == TT_DB_OK) {
1072 _tt_increment_object_properties_cache_level(db,
1075 results.cache_level);
1082 _tt_obj_props_results *_tt_delete_obj_prop_1 (_tt_del_obj_prop_args *args,
1083 SVCXPRT * /* transp */)
1085 static _tt_obj_props_results results;
1086 results.cache_level = -1;
1088 _Tt_string partition = _tt_get_object_partition(args->objid);
1089 _Tt_db_server_db_ptr db;
1090 results.results = _tt_get_partition_db(partition, db);
1092 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
1094 if (results.results == TT_DB_OK) {
1096 _tt_get_object_properties_cache_level(db,
1099 results.cache_level);
1102 // If the cache level in the DB is higher then the passed in
1103 // cache level, then someone else must have updated before
1104 // the callers last read from the DB --> update conflict...
1105 if ((results.results == TT_DB_OK) &&
1106 (results.cache_level > args->cache_level)) {
1107 results.results = TT_DB_ERR_UPDATE_CONFLICT;
1110 // No update conflicts or any other weirdness...
1112 if (results.results == TT_DB_OK) {
1113 _Tt_db_property_ptr property;
1114 _tt_get_rpc_property(args->property, property);
1116 if (!property.is_null()) {
1117 results.results = db->deleteObjectProperty(args->objid,
1122 results.results = TT_DB_ERR_ILLEGAL_PROPERTY;
1125 if (results.results == TT_DB_OK) {
1127 _tt_increment_object_properties_cache_level(db,
1130 results.cache_level);
1134 // The delete object prop function is the only object function that always
1135 // returns that latest object properties. The cache level passed in
1136 // is only used for update conflict detection.
1137 _Tt_db_property_list_ptr properties;
1138 if ((results.results == TT_DB_OK) ||
1139 (results.results == TT_DB_ERR_UPDATE_CONFLICT)) {
1140 _Tt_db_results temp_results = db->getObjectProperties(args->objid,
1144 if (results.results != TT_DB_OK) {
1145 properties = (_Tt_db_property_list *)NULL;
1146 results.results = temp_results;
1149 _tt_set_rpc_properties(properties, results.properties);
1154 _tt_obj_prop_results *_tt_get_obj_prop_1 (_tt_get_obj_prop_args *args,
1155 SVCXPRT * /* transp */)
1157 static _tt_obj_prop_results results;
1158 results.cache_level = -1;
1160 _Tt_string partition = _tt_get_object_partition(args->objid);
1161 _Tt_db_server_db_ptr db;
1162 results.results = _tt_get_partition_db(partition, db);
1164 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
1166 if (results.results == TT_DB_OK) {
1168 _tt_get_object_properties_cache_level(db,
1171 results.cache_level);
1174 _Tt_db_property_ptr property;
1176 // Only return values if the DB cache level is higher then the
1177 // callers cache level
1178 if ((results.results == TT_DB_OK) &&
1179 (results.cache_level > args->cache_level)) {
1180 results.results = db->getObjectProperty(args->objid,
1185 _tt_set_rpc_property(property, results.property);
1190 _tt_obj_props_results *_tt_get_obj_props_1 (_tt_get_obj_props_args *args,
1191 SVCXPRT * /* transp */)
1193 static _tt_obj_props_results results;
1194 results.cache_level = -1;
1196 _Tt_string partition = _tt_get_object_partition(args->objid);
1197 _Tt_db_server_db_ptr db;
1198 results.results = _tt_get_partition_db(partition, db);
1200 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
1202 if (results.results == TT_DB_OK) {
1204 _tt_get_object_properties_cache_level(db,
1207 results.cache_level);
1210 _Tt_db_property_list_ptr properties;
1212 // Only return values if the DB cache level is higher then the
1213 // callers cache level
1214 if ((results.results == TT_DB_OK) &&
1215 (results.cache_level > args->cache_level)) {
1216 results.results = db->getObjectProperties(args->objid,
1220 _tt_set_rpc_properties(properties, results.properties);
1225 _tt_db_results *_tt_set_obj_type_1 (_tt_set_obj_type_args *args,
1226 SVCXPRT * /* transp */)
1228 static _tt_db_results results;
1230 _Tt_string partition = _tt_get_object_partition(args->objid);
1231 _Tt_db_server_db_ptr db;
1232 results = _tt_get_partition_db(partition, db);
1234 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
1236 if (results == TT_DB_OK) {
1237 _Tt_db_property_ptr property = new _Tt_db_property;
1238 property->name = TT_DB_OBJECT_TYPE_PROPERTY;
1239 property->values->append(_Tt_string(args->otype));
1241 results = db->setObjectProperty(args->objid, property, accessPtr);
1247 _tt_obj_type_results *_tt_get_obj_type_1 (_tt_get_obj_type_args *args,
1248 SVCXPRT * /* transp */)
1250 static _tt_obj_type_results results;
1252 _Tt_string partition = _tt_get_object_partition(args->objid);
1253 _Tt_db_server_db_ptr db;
1254 results.results = _tt_get_partition_db(partition, db);
1256 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
1258 if (results.results == TT_DB_OK) {
1259 _Tt_db_property_ptr property;
1260 results.results = db->getObjectProperty(args->objid,
1261 TT_DB_OBJECT_TYPE_PROPERTY,
1265 results.otype = (char *)NULL;
1266 if (results.results == TT_DB_OK) {
1267 if (!property.is_null() && !property->is_empty()) {
1268 _Tt_string otype = (*property->values) [0];
1269 int length = otype.len();
1271 results.otype = (char *)malloc(length+1);
1272 memcpy(results.otype, (char *)otype, length);
1273 results.otype [length] = '\0';
1276 else if (results.results == TT_DB_ERR_NO_SUCH_PROPERTY) {
1277 results.results = TT_DB_ERR_NO_OTYPE;
1284 _tt_db_results *_tt_set_obj_file_1 (_tt_set_obj_file_args *args,
1285 SVCXPRT * /* transp */)
1287 static _tt_db_results results;
1289 _Tt_string partition = _tt_get_object_partition(args->objid);
1290 _Tt_db_server_db_ptr db;
1291 results = _tt_get_partition_db(partition, db);
1293 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
1295 if (results == TT_DB_OK) {
1296 results = db->setObjectFile(args->objid, args->file, accessPtr);
1302 _tt_obj_file_results *_tt_get_obj_file_1 (_tt_get_obj_file_args *args,
1303 SVCXPRT * /* transp */)
1305 static _tt_obj_file_results results;
1307 _Tt_string partition = _tt_get_object_partition(args->objid);
1308 _Tt_db_server_db_ptr db;
1309 results.results = _tt_get_partition_db(partition, db);
1311 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
1313 if (results.results == TT_DB_OK) {
1315 results.results = db->getObjectFile(args->objid,
1319 results.file = (char *)NULL;
1320 if (results.results == TT_DB_OK) {
1322 results.file = strdup((char *)file);
1330 _tt_db_results *_tt_set_obj_access_1 (_tt_set_obj_access_args *args,
1331 SVCXPRT * /* transp */)
1333 static _tt_db_results results;
1335 _Tt_string partition = _tt_get_object_partition(args->objid);
1336 _Tt_db_server_db_ptr db;
1337 results = _tt_get_partition_db(partition, db);
1339 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
1341 _Tt_db_access_ptr new_access;
1342 if (results == TT_DB_OK) {
1343 _tt_get_rpc_access(args->new_access, new_access);
1345 if ((new_access->user == (uid_t)-1) ||
1346 (new_access->group == (gid_t)-1) ||
1347 (new_access->mode == (mode_t)-1)) {
1348 _Tt_db_access_ptr current_access;
1349 results = db->getObjectAccess(args->objid,
1353 if (results == TT_DB_OK) {
1354 if (new_access->user == (uid_t)-1) {
1355 new_access->user = current_access->user;
1358 if (new_access->group == (gid_t)-1) {
1359 new_access->group = current_access->group;
1362 if (new_access->mode == (mode_t)-1) {
1363 new_access->mode = current_access->mode;
1368 if (results == TT_DB_OK) {
1369 results = db->setObjectAccess(args->objid, new_access, accessPtr);
1376 _tt_obj_access_results *_tt_get_obj_access_1 (_tt_get_obj_access_args *args,
1377 SVCXPRT * /* transp */)
1379 static _tt_obj_access_results results;
1381 _Tt_string partition = _tt_get_object_partition(args->objid);
1382 _Tt_db_server_db_ptr db;
1383 results.results = _tt_get_partition_db(partition, db);
1385 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
1387 _Tt_db_access_ptr current_access;
1388 if (results.results == TT_DB_OK) {
1389 results.results = db->getObjectAccess(args->objid,
1393 _tt_set_rpc_access(current_access, results.access);
1398 _tt_is_file_in_db_results *_tt_is_file_in_db_1 (_tt_is_file_in_db_args *args,
1399 SVCXPRT * /* transp */)
1401 static _tt_is_file_in_db_results results;
1403 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
1405 _Tt_string real_file = args->file;
1406 _Tt_string partition = _tt_get_file_partition(args->file);
1407 _Tt_db_server_db_ptr db;
1408 results.results = _tt_get_partition_db(partition, db);
1410 if (results.results == TT_DB_OK) {
1411 // See if the file already exists by trying to get its access info
1412 _Tt_db_access_ptr temp_access;
1413 _Tt_db_results temp_results = db->getFileAccess(real_file,
1417 // If the file exists...
1418 if ((temp_results == TT_DB_OK) ||
1419 (temp_results == TT_DB_ERR_ACCESS_DENIED)) {
1420 results.results = TT_DB_OK;
1423 results.results = temp_results;
1426 // See if the file is a directory
1427 results.directory_flag = _tt_is_file_a_directory(real_file);
1433 _tt_is_obj_in_db_results *_tt_is_obj_in_db_1 (_tt_is_obj_in_db_args *args,
1434 SVCXPRT * /* transp */)
1436 static _tt_is_obj_in_db_results results;
1437 results.forward_pointer = (char *)NULL;
1439 _Tt_string partition = _tt_get_object_partition(args->objid);
1440 _Tt_db_server_db_ptr db;
1441 results.results = _tt_get_partition_db(partition, db);
1443 _Tt_db_access_ptr accessPtr = _tt_get_real_rpc_access(args->access);
1445 if (results.results == TT_DB_OK) {
1448 // See if the object has an entry in the file-object map
1449 results.results = db->getObjectFile(args->objid,
1453 // If no entry in the file-object map...
1454 if (results.results != TT_DB_OK) {
1455 _Tt_db_property_ptr property;
1457 // See if there is a forward pointer
1458 _Tt_db_results temp_results =
1459 db->getObjectProperty(args->objid,
1460 TT_DB_FORWARD_POINTER_PROPERTY,
1464 // If there is a forward pointer...
1465 if (temp_results == TT_DB_OK) {
1466 _Tt_string forward_pointer = (*property->values) [0];
1467 int length = forward_pointer.len();
1468 results.forward_pointer = (char *)malloc(length+1);
1470 memcpy(results.forward_pointer, (char *)forward_pointer, length);
1471 results.forward_pointer [length] = '\0';
1472 results.results = TT_DB_WRN_FORWARD_POINTER;
1480 _tt_db_results *_tt_queue_message_1 (_tt_queue_msg_args *args,
1481 SVCXPRT * /* transp */)
1483 static _tt_db_results results;
1485 bool_t property_written = FALSE;
1487 _Tt_db_server_db_ptr db;
1488 _Tt_string real_file = args->file;
1489 if (!args->message.body.body_len) {
1490 results = TT_DB_ERR_ILLEGAL_MESSAGE;
1493 _Tt_string partition = _tt_get_file_partition(args->file);
1494 results = _tt_get_partition_db(partition, db);
1497 if (results == TT_DB_OK) {
1498 _Tt_db_access_ptr accessPtr = _tt_get_unix_file_access(real_file);
1500 // Set the DB file access to be the same as the actual file. This
1501 // allows an easy method of controlled message security
1502 if (!accessPtr.is_null()) {
1503 results = db->setFileAccess(real_file, accessPtr, accessPtr);
1507 _Tt_db_access_ptr accessPtr = new _Tt_db_access;
1508 accessPtr->user = _tt_uid;
1509 accessPtr->group = _tt_gid;
1511 // Create a new message info structure for the new message
1512 _Tt_db_message_info_ptr message_info = new _Tt_db_message_info;
1513 if (results == TT_DB_OK) {
1516 // Get the current information on queued messages
1517 _Tt_db_property_ptr property;
1518 _Tt_string name = TT_DB_MESSAGE_INFO_PROPERTY;
1519 results = db->getFileProperty(real_file, name, accessPtr, property);
1521 // Default new message ID if there are none in the queue
1524 if (results == TT_DB_OK) {
1525 // Calculate the index for the last message info structure in
1527 int index = property->values->count() - 1;
1530 // Un-XDR the message info into the "last_message_info" object
1531 // and set the new message ID to the message ID in in
1532 // "last_message_info" + 1.
1533 _Tt_string message_info_bytes = (*property->values) [index];
1534 xdrmem_create(&xdrs,
1535 (char *)message_info_bytes,
1536 (u_int)message_info_bytes.len(),
1538 _Tt_db_message_info_ptr last_message_info = new _Tt_db_message_info;
1539 (void)last_message_info->xdr(&xdrs);
1540 message_id = last_message_info->messageID + 1;
1544 // It doesn't matter if there were no queued messages, as long as
1545 // there were no fatal errors
1546 if ((results == TT_DB_OK) ||
1547 (results == TT_DB_ERR_NO_SUCH_PROPERTY)) {
1550 // Put the new message info into the message info structure
1551 message_info->messageID = message_id;
1552 message_info->numParts = (args->message.body.body_len / ISMAXRECLEN) + 1;
1553 message_info->messageSize = args->message.body.body_len;
1554 _tt_get_rpc_strings(args->ptypes, message_info->ptypes);
1556 // Get the XDR size of the new message info structure
1558 _Tt_xdr_size_stream xdrsz;
1559 if (!message_info->xdr((XDR *)xdrsz)) {
1560 results = TT_DB_ERR_ILLEGAL_MESSAGE;
1562 length = (unsigned int) xdrsz.getsize();
1565 // XDR the message info structure into "temp_string"
1566 _Tt_string temp_string((int)length);
1567 if (results != TT_DB_ERR_ILLEGAL_MESSAGE) {
1568 xdrmem_create(&xdrs, (char *)temp_string, length, XDR_ENCODE);
1569 if (!message_info->xdr(&xdrs)) {
1570 results = TT_DB_ERR_ILLEGAL_MESSAGE;
1574 if (results != TT_DB_ERR_ILLEGAL_MESSAGE) {
1575 // Add the XDR'd message info to the message info property
1576 _Tt_db_property_ptr property = new _Tt_db_property;
1577 property->name = TT_DB_MESSAGE_INFO_PROPERTY;
1578 property->values->append(temp_string);
1580 results = db->addFileProperty(real_file, property, FALSE, accessPtr);
1581 property_written = TRUE;
1586 if (results == TT_DB_OK) {
1587 int length = ISMAXRECLEN;
1589 // Break up the message into ISMAXRECLEN sized parts and store
1590 // as separate properties
1592 (results == TT_DB_OK) && (i < message_info->numParts);
1594 // If this is the last part, it is probably shorter then
1595 // ISMAXRECLEN, so calculate the exact length
1596 if (i == message_info->numParts-1) {
1597 length = message_info->messageSize - (i * ISMAXRECLEN);
1600 // Copy the message part into a buffer
1601 _Tt_string message_part(length);
1602 memcpy((char *)message_part,
1603 args->message.body.body_val+i*ISMAXRECLEN,
1606 // Construct a property name of the form:
1608 // _TT_MSG_<ID#>_<PART#>
1611 sprintf(name, TT_DB_MESSAGE_PROPERTY, message_info->messageID, i);
1613 // Store the property
1614 _Tt_db_property_ptr property = new _Tt_db_property;
1615 property->name = name;
1616 property->values->append(message_part);
1618 results = db->setFileProperty(real_file, property, accessPtr);
1619 property_written = TRUE;
1623 if (property_written && (results == TT_DB_OK)) {
1625 results = _tt_increment_file_properties_cache_level(db,
1634 _tt_dequeue_msgs_results *
1635 _tt_dequeue_messages_1 (_tt_dequeue_msgs_args *args,
1636 SVCXPRT * /* transp */)
1638 static _tt_dequeue_msgs_results results;
1639 results.messages.messages_val = (_tt_message *)NULL;
1640 results.messages.messages_len = 0;
1642 bool_t property_written = FALSE;
1644 _Tt_string real_file = args->file;
1645 _Tt_string partition = _tt_get_file_partition(args->file);
1646 _Tt_db_server_db_ptr db;
1647 results.results = _tt_get_partition_db(partition, db);
1649 if (results.results == TT_DB_OK) {
1650 _Tt_db_access_ptr accessPtr = _tt_get_unix_file_access(real_file);
1652 // Set the DB file access to be the same as the actual file. This
1653 // allows an easy method of control for queued message security
1654 if (!accessPtr.is_null()) {
1655 results.results = db->setFileAccess(real_file,
1661 _Tt_db_access_ptr accessPtr = new _Tt_db_access;
1662 accessPtr->user = _tt_uid;
1663 accessPtr->group = _tt_gid;
1665 // Get the message info property
1666 _Tt_db_property_ptr property;
1667 if (results.results == TT_DB_OK) {
1668 _Tt_string name = TT_DB_MESSAGE_INFO_PROPERTY;
1669 results.results = db->getFileProperty(real_file,
1675 _Tt_db_message_info_ptr message_info = new _Tt_db_message_info;
1676 _Tt_string_list_ptr messages;
1678 if (results.results == TT_DB_ERR_NO_SUCH_PROPERTY) {
1679 results.results = TT_DB_OK;
1681 else if (results.results == TT_DB_OK) {
1682 _Tt_string_list_ptr dequeue_ptypes;
1683 _tt_get_rpc_strings(args->ptypes, dequeue_ptypes);
1685 _Tt_string_list_cursor dequeue_ptypes_cursor(dequeue_ptypes);
1687 // Loop through the message info property (effectively looping
1688 // through the message info entries)
1689 _Tt_string_list_cursor values_cursor(property->values);
1690 while (values_cursor.next()) {
1693 // Un-XDR a message info structure
1694 xdrmem_create(&xdrs,
1695 (char *)*values_cursor,
1696 (*values_cursor).len(),
1698 (void)message_info->xdr(&xdrs);
1700 // Eliminate all of the ptypes from the message info list
1701 // that match the callers ptype list.
1702 bool_t ptype_matched = FALSE;
1703 _Tt_string_list_cursor ptypes_cursor(message_info->ptypes);
1704 while (ptypes_cursor.next()) {
1705 while (dequeue_ptypes_cursor.next()) {
1706 if (*dequeue_ptypes_cursor == *ptypes_cursor) {
1707 ptypes_cursor.remove();
1708 ptype_matched = TRUE;
1714 // A ptype matched, this message is to be returned...
1715 if (ptype_matched) {
1716 if (messages.is_null()) {
1717 messages = new _Tt_string_list;
1720 // Reconstruct the message from the _TT_MSG_<ID#>_<PART#> properties
1721 _Tt_string message(message_info->messageSize);
1722 for (int i=0; (results.results == TT_DB_OK) &&
1723 (i < message_info->numParts); i++) {
1724 // Construct the property name
1726 sprintf(name, TT_DB_MESSAGE_PROPERTY, message_info->messageID, i);
1728 // Get the property value
1729 _Tt_db_property_ptr property;
1730 results.results = db->getFileProperty(real_file,
1734 if (results.results == TT_DB_OK) {
1735 _Tt_string message_bytes = (*property->values) [0];
1737 // Copy each succesive part into a large buffer
1738 memcpy((char *)message+i*ISMAXRECLEN,
1739 (char *)message_bytes,
1740 message_bytes.len());
1744 // Append the re-assembled message to the return list
1745 if (results.results == TT_DB_OK) {
1746 messages->append(message);
1750 // No more ptypes left for this message, dequeue it...
1751 if (message_info->ptypes->is_empty()) {
1752 values_cursor.remove();
1754 // Otherwise, update the property value with an updated version
1755 // of the message_info structure
1759 _Tt_xdr_size_stream xdrsz;
1761 // Get the XDR size of the updated message info structure
1762 (void)message_info->xdr((XDR *)xdrsz);
1763 length = (unsigned int) xdrsz.getsize();
1765 // XDR the message info structure into "temp_string"
1766 _Tt_string temp_string((int)length);
1767 xdrmem_create(&xdrs, (char *)temp_string, length, XDR_ENCODE);
1768 if (!message_info->xdr(&xdrs)) {
1769 // Update the property value
1770 *values_cursor = temp_string;
1775 // Put the message info property back into the DB. If all of
1776 // the message info structures have been deleted from the
1777 // property, then this should effectively delete the property.
1778 results.results = db->setFileProperty(real_file,
1781 property_written = TRUE;
1783 if (!messages.is_null()) {
1784 if ((results.results == TT_DB_OK) && !messages->is_empty()) {
1785 // Allocate enough space to transport the messages back to the
1787 results.messages.messages_val = (_tt_message *)
1788 malloc(sizeof(_tt_message)*
1790 results.messages.messages_len = messages->count();
1792 // Put the messages into the results structure
1794 _Tt_string_list_cursor messages_cursor(messages);
1795 while (messages_cursor.next()) {
1796 results.messages.messages_val [i].body.body_val =
1797 (char *)malloc((*messages_cursor).len());
1798 results.messages.messages_val [i].body.body_len =
1799 (*messages_cursor).len();
1800 memcpy(results.messages.messages_val [i].body.body_val,
1801 (char *)*messages_cursor,
1802 (*messages_cursor).len());
1809 if (property_written && (results.results == TT_DB_OK)) {
1811 results.results = _tt_increment_file_properties_cache_level(db,
1820 // Since we're calling the wrapped API calls, bringing in tt_c.h
1821 // doesn't get us the declarations we need, so we have to bring
1822 // these two in manually like this.
1824 extern char * _tt_file_netfile(const char *);
1825 extern char * _tt_netfile_file(const char *);
1826 extern Tt_status _tt_pointer_error(void *p);
1827 extern char * _tt_status_message(Tt_status s);
1830 // Call the API routine _tt_file_netfile() and return the
1832 _tt_file_netfile_results *
1833 _tt_file_netfile_1 (_tt_file_netfile_args *args, SVCXPRT * /* transp */)
1837 printf("DEBUG: SERVER: _tt_file_netfile_1: calling _tt_file_netfile(%s)\n",
1838 (char *) args->file_or_netfile);
1841 static _tt_file_netfile_results results;
1842 static char * canonical_path;
1844 // we have a netfilename, get the local file version...
1845 canonical_path = _tt_file_netfile(args->file_or_netfile);
1848 printf("DEBUG: SERVER: _tt_file_netfile_1: _tt_file_netfile(%s) returned %s\n",
1849 args->file_or_netfile, canonical_path);
1853 if (_tt_pointer_error(canonical_path) != TT_OK) {
1854 results.results = TT_DB_ERR_ILLEGAL_FILE;
1855 results.result_string = NULL;
1857 results.results = TT_DB_OK;
1858 results.result_string = canonical_path;
1860 results.tt_status = (int) _tt_pointer_error(canonical_path);
1863 printf("\t results.tt_status == %s\n",
1864 _tt_status_message(_tt_pointer_error(canonical_path)));
1871 // Call the API routine _tt_netfile_file() and return the
1873 _tt_file_netfile_results *
1874 _tt_netfile_file_1 (_tt_file_netfile_args *args, SVCXPRT * /* transp */)
1878 printf("DEBUG: SERVER: _tt_netfile_file_1: calling _tt_netfile_file(%s)\n",
1879 (char *) args->file_or_netfile);
1882 static _tt_file_netfile_results results;
1883 static char * canonical_path;
1885 // we have a netfilename, get the local file version...
1886 canonical_path = _tt_netfile_file(args->file_or_netfile);
1889 printf("DEBUG: SERVER: _tt_netfile_file_1: _tt_netfile_file(%s) returned %s\n",
1890 args->file_or_netfile, canonical_path);
1893 if (_tt_pointer_error(canonical_path) != TT_OK) {
1894 results.results = TT_DB_ERR_ILLEGAL_FILE;
1895 results.result_string = NULL;
1897 results.results = TT_DB_OK;
1898 results.result_string = canonical_path;
1900 results.tt_status = (int) _tt_pointer_error(canonical_path);
1903 printf("\t results.tt_status == %s\n",
1904 _tt_status_message(_tt_pointer_error(canonical_path)));
1912 // Delete the named session from the properties table.
1914 _tt_delete_session_results *
1915 _tt_delete_session_1(_tt_delete_session_args *args,
1916 SVCXPRT * /*NOTUSED*/)
1918 static _tt_delete_session_results results;
1919 Table_oid_prop record;
1922 int propLen = strlen(propTable);
1928 results.tt_status = TT_DB_OK;
1931 // For each property_table that we manage,
1932 // Compare the sessionID with the session that
1933 // we just found to be dead, and delete it.
1935 for (fileOffset = 0; fileOffset < _TT_MAX_ISFD; fileOffset++) {
1937 pathName = _tt_db_table[fileOffset].db_path;
1939 if (pathName && strlen(pathName) > 0) {
1940 if (_tt_db_table[fileOffset].client_has_open
1941 || _tt_db_table[fileOffset].server_has_open) {
1944 // Is the file name ".../property_table*" ?
1946 lastSlash = strrchr(pathName, '/');
1949 if (strncmp(propTable,lastSlash,propLen)==0) {
1951 // Get the FD and process the file.
1952 isfd=cached_isopen(pathName, ISINOUT);
1955 // Get the 1st record.
1958 isread(isfd, (char *)&record, ISFIRST);
1959 ((char *)(&record))[isreclen] = '\0';
1961 // Delte the named session.
1962 if (strcmp(sesProp, record.propname) == 0) {
1963 if (strcmp(args->session.value, record.propval) == 0) {
1969 // Unconditionally delete ALL _MODIFICATION_DATE's
1970 if (strcmp(modDate, record.propname) == 0) {
1979 if (isread(isfd, (char *)&record,ISNEXT) != 0) {
1983 ((char *)(&record))[isreclen] = '\0';
1984 if (strcmp(sesProp, record.propname) == 0) {
1985 if(strcmp(args->session.value,
1986 record.propval) == 0) {
1992 // Unconditionally delete ALL
1993 // _MODIFICATION_DATE's
1994 if (strcmp(modDate, record.propname) == 0) {
2000 cached_isclose(isfd);
2010 // *All* is an over statment.
2011 // It returns up to OPT_MAX_GET_SESSIONS sessions and the oidkey to use
2014 _tt_get_all_sessions_results *
2015 _tt_get_all_sessions_1(_tt_get_all_sessions_args * args,
2016 SVCXPRT * /*NOTUSED*/)
2018 static _tt_get_all_sessions_results results;
2020 static _Tt_string_list *list;
2021 list = new _Tt_string_list;
2025 int recordCount = 0;
2026 int propLen = strlen(propTable);
2031 _Tt_string propValue;
2032 Table_oid_prop record;
2035 // Empty out any existing session or key results.
2038 if (results.oidkey.oidkey_val != NULL) {
2039 free((char *)results.oidkey.oidkey_val);
2041 for (offset = 0 ; offset < list->count() ; offset++) {
2042 if (results.session_list.values_val[offset].value != NULL) {
2043 free(results.session_list.values_val[offset].value);
2046 if (results.session_list.values_val != NULL) {
2047 free((char *)results.session_list.values_val);
2048 results.session_list.values_val = NULL;
2050 memset(&results.oidkey, '\0', sizeof(results.oidkey));
2053 // For each property_table that we manage,
2054 // pull out all of the session-ids and pass them back (up
2055 // to OPT_MAX_GET_SESSIONS passed back in each call)
2057 for (offset = 0 ; offset < _TT_MAX_ISFD; offset++) {
2059 pathName = _tt_db_table[offset].db_path;
2061 if (pathName && strlen(pathName) > 0) {
2062 if (_tt_db_table[offset].client_has_open
2063 || _tt_db_table[offset].server_has_open) {
2066 // Is the file name ".../property_table*" ?
2068 lastSlash = strrchr(pathName, '/');
2071 if (strncmp(propTable, lastSlash, propLen) == 0) {
2073 // Get the FD and process the file.
2074 isfd = cached_isopen(pathName, ISINOUT);
2077 // If the user passed in a starting key,
2080 if (args->oidkey.oidkey_len > 0
2081 && args->oidkey.oidkey_val != NULL) {
2083 (char *)args->oidkey.oidkey_val);
2087 // Get the 1st record.
2089 isread(isfd, (char *)&record, ISFIRST);
2090 ((char *)(&record))[isreclen] = '\0';
2091 if (strcmp(sesProp, record.propname) == 0) {
2092 propValue = record.propval;
2094 // Append it to the list to send back.
2096 list->append(propValue);
2097 memset(&record, '\0', sizeof(record));
2100 while(isread(isfd, (char *)&record,ISNEXT) != -1) {
2101 ((char *)(&record))[isreclen] = '\0';
2102 if (strcmp(sesProp, record.propname) == 0) {
2103 propValue = record.propval;
2104 list->append(propValue);
2105 if (++recordCount > OPT_MAX_GET_SESSIONS-1) {
2106 results.oidkey.oidkey_val = NULL;
2108 (int *)&results.oidkey.oidkey_len,
2109 (char **)&results.oidkey.oidkey_val);
2114 memset(&record, '\0', sizeof(record));
2116 cached_isclose(isfd);
2117 if (recordCount > OPT_MAX_GET_SESSIONS-1) {
2125 results.session_list.values_len = list->count();
2126 if (results.session_list.values_len > 0) {
2127 results.session_list.values_val = (_tt_string *)malloc(sizeof(_tt_string *) * list->count());
2129 results.session_list.values_val = (_tt_string *)NULL;
2131 for (offset = 0 ; offset < results.session_list.values_len ; offset++) {
2132 propValue = list->top();
2133 results.session_list.values_val[offset].value = strdup(propValue);
2140 _tt_garbage_collect_results *
2141 _tt_garbage_collect_1(void * /*NOTUSED*/,
2142 SVCXPRT * /*NOTUSED*/)
2144 static _tt_garbage_collect_results results;
2147 memset(&results, '\0', sizeof(_tt_garbage_collect_results));
2149 #if defined(OPT_GARBAGE_THREADS)
2153 // Collect the garbage and delete old sessions in
2154 // a separate thread. As soon as the thread is started
2155 // this function returns and the dbserver is again
2156 // processing user requests.
2157 id = _tt_run_garbage_collect(OPT_GARBAGE_IN_PARALLEL);
2158 results.tt_status = (id >= 0) ? TT_OK : TT_ERR_INTERNAL;
2161 // Without threads, just compress (isgarbage) the
2162 // db files. The user program will check for and
2163 // delete old sessions.
2165 isgarbage_collect();
2166 results.tt_status = TT_OK;
2173 // ******* Static helper functions start here *******
2176 bool_t _tt_is_file_a_directory (const _Tt_string &file)
2178 // This is sometimes called with a network path and a non-network path.
2179 // Make sure we always give stat a non-network path.
2180 char *slash = strchr((char *)file, '/');
2181 char *path = strchr((char *)file, ':');
2182 if (path != slash-1) {
2183 path = (char *)NULL;
2185 DIR *dd = opendir(path ? path+1 : (char *)file);
2191 return (dd ? TRUE : FALSE);
2194 // Replace the old partition with the new partition in the object ID
2195 static _Tt_string _tt_make_equivalent_object_id (const _Tt_string &objid,
2196 const _Tt_string &partition)
2198 _Tt_string temp_string = (char *)objid;
2199 _Tt_string new_objid;
2201 temp_string = temp_string.rsplit (':', new_objid);
2202 new_objid = new_objid.cat(partition);
2207 static _Tt_db_results _tt_get_partition_db (const _Tt_string &partition,
2208 _Tt_db_server_db_ptr &db)
2210 _Tt_db_partition_global_map_ref db_map;
2211 _Tt_db_results results = TT_DB_OK;
2213 db = db_map.getDB(partition);
2215 results = TT_DB_ERR_DB_OPEN_FAILED;
2221 static _Tt_db_access_ptr _tt_get_real_rpc_access (const _tt_access &rpc_access)
2223 _Tt_db_access_ptr accessPtr;
2224 _tt_get_rpc_access(rpc_access, accessPtr);
2226 accessPtr->user = _tt_uid;
2227 accessPtr->group = (gid_t)-1;
2229 // Make sure the group ID is valid before using it
2230 for (int i=0; i < _tt_gidlen; i++) {
2231 if (_tt_gidlist [i] == _tt_gid) {
2232 accessPtr->group = _tt_gid;
2239 static _Tt_db_access_ptr _tt_get_file_access (const _Tt_string &file,
2240 const _tt_access &rpc_access)
2242 _Tt_db_access_ptr accessPtr = _tt_get_unix_file_access(file);
2244 if (accessPtr.is_null()) {
2245 accessPtr = _tt_get_real_rpc_access(rpc_access);
2248 accessPtr->mode = (mode_t)-1;
2254 static _Tt_db_access_ptr _tt_get_unix_file_access (const _Tt_string &file)
2256 _Tt_db_access_ptr accessPtr;
2258 struct stat stat_buf;
2260 // Make sure we always give stat a non-network path.
2261 _Tt_string local_path = file;
2263 if (_tt_is_network_path(file)) {
2264 _Tt_string temp_string;
2265 local_path = local_path.split(':', temp_string);
2268 if (!stat((char *)local_path, &stat_buf)) {
2269 accessPtr = new _Tt_db_access;
2270 accessPtr->user = stat_buf.st_uid;
2271 accessPtr->group = stat_buf.st_gid;
2272 accessPtr->mode = stat_buf.st_mode;
2278 static _Tt_string _tt_get_file_partition (const _Tt_string &file)
2280 _Tt_string temp_string;
2281 _Tt_string local_path = file;
2282 local_path = local_path.split(':', temp_string);
2285 _Tt_file_system_entry_ptr entry = fs.bestMatchToPath(local_path);
2287 return entry->getMountPoint();
2290 static _Tt_db_results
2291 _tt_increment_file_properties_cache_level
2292 (const _Tt_db_server_db_ptr &db,
2293 const _Tt_string &file,
2294 const _Tt_db_access_ptr &accessPtr,
2299 _Tt_db_property_ptr property;
2300 _Tt_db_results results =
2301 db->getFileProperty(file,
2302 TT_DB_PROPS_CACHE_LEVEL_PROPERTY,
2306 if (results == TT_DB_OK) {
2307 _Tt_string cache_level_bytes = (*property->values) [0];
2308 memcpy ((char *)&cache_level, (char *)cache_level_bytes, sizeof(int));
2311 memcpy ((char *)cache_level_bytes, (char *)&cache_level, sizeof(int));
2312 (*property->values) [0] = cache_level_bytes;
2314 results = db->setFileProperty(file,
2317 if (results != TT_DB_OK) {
2319 results = TT_DB_ERR_PROPS_CACHE_ERROR;
2322 else if (results == TT_DB_ERR_NO_SUCH_PROPERTY) {
2325 _Tt_string value(sizeof(int));
2326 memcpy((char *)value, (char *)&cache_level, sizeof(int));
2328 _Tt_db_property_ptr property = new _Tt_db_property;
2329 property->name = TT_DB_PROPS_CACHE_LEVEL_PROPERTY;
2330 property->values->append(value);
2332 results = db->setFileProperty(file,
2335 if (results != TT_DB_OK) {
2337 results = TT_DB_ERR_PROPS_CACHE_ERROR;
2341 results = TT_DB_ERR_PROPS_CACHE_ERROR;
2347 static _Tt_db_results
2348 _tt_get_file_properties_cache_level (const _Tt_db_server_db_ptr &db,
2349 const _Tt_string &file,
2350 const _Tt_db_access_ptr &accessPtr,
2355 _Tt_db_property_ptr property;
2356 _Tt_db_results results =
2357 db->getFileProperty(file,
2358 TT_DB_PROPS_CACHE_LEVEL_PROPERTY,
2361 if (results == TT_DB_OK) {
2362 _Tt_string cache_level_bytes = (*property->values) [0];
2363 memcpy ((char *)&cache_level, (char *)cache_level_bytes, sizeof(int));
2365 // The file was probably created for an object. The cache level
2366 // was never stored as a property...
2367 else if (results == TT_DB_ERR_NO_SUCH_PROPERTY) {
2368 results = _tt_increment_file_properties_cache_level(db,
2374 results = TT_DB_ERR_PROPS_CACHE_ERROR;
2380 static _Tt_string _tt_get_object_partition (const _Tt_string &objid)
2382 _Tt_string partition = (char *)objid;
2383 _Tt_string temp_string;
2385 // Get rid of file system type and hostname - the partition
2386 // is the only thing left
2387 partition = partition.split(':', temp_string);
2388 partition = partition.split(':', temp_string);
2389 partition = partition.split(':', temp_string);
2394 static _Tt_db_results
2395 _tt_increment_object_properties_cache_level
2396 (const _Tt_db_server_db_ptr &db,
2397 const _Tt_string &objid,
2398 const _Tt_db_access_ptr &accessPtr,
2403 _Tt_db_property_ptr property;
2404 _Tt_db_results results =
2405 db->getObjectProperty(objid,
2406 TT_DB_PROPS_CACHE_LEVEL_PROPERTY,
2410 if (results == TT_DB_OK) {
2411 _Tt_string cache_level_bytes = (*property->values) [0];
2412 memcpy ((char *)&cache_level, (char *)cache_level_bytes, sizeof(int));
2415 memcpy ((char *)cache_level_bytes, (char *)&cache_level, sizeof(int));
2416 (*property->values) [0] = cache_level_bytes;
2418 results = db->setObjectProperty(objid,
2421 if (results != TT_DB_OK) {
2423 results = TT_DB_ERR_PROPS_CACHE_ERROR;
2426 else if (results == TT_DB_ERR_NO_SUCH_PROPERTY) {
2429 _Tt_string value(sizeof(int));
2430 memcpy((char *)value, (char *)&cache_level, sizeof(int));
2432 _Tt_db_property_ptr property = new _Tt_db_property;
2433 property->name = TT_DB_PROPS_CACHE_LEVEL_PROPERTY;
2434 property->values->append(value);
2436 results = db->setObjectProperty(objid,
2439 if (results != TT_DB_OK) {
2441 results = TT_DB_ERR_PROPS_CACHE_ERROR;
2445 results = TT_DB_ERR_PROPS_CACHE_ERROR;
2451 static _Tt_db_results
2452 _tt_get_object_properties_cache_level (const _Tt_db_server_db_ptr &db,
2453 const _Tt_string &objid,
2454 const _Tt_db_access_ptr &accessPtr,
2459 _Tt_db_property_ptr property;
2460 _Tt_db_results results =
2461 db->getObjectProperty(objid,
2462 TT_DB_PROPS_CACHE_LEVEL_PROPERTY,
2466 if (results == TT_DB_OK) {
2467 _Tt_string cache_level_bytes = (*property->values) [0];
2468 memcpy ((char *)&cache_level, (char *)cache_level_bytes, sizeof(int));
2471 results = TT_DB_ERR_PROPS_CACHE_ERROR;
2478 _tt_screen_object_properties (_Tt_db_property_list_ptr &properties)
2480 _Tt_db_property_list_cursor properties_cursor (properties);
2481 while (properties_cursor.next ()) {
2482 if (properties_cursor->name == TT_DB_PROPS_CACHE_LEVEL_PROPERTY) {
2483 properties_cursor.remove ();
2485 else if (properties_cursor->name == TT_DB_OBJECT_TYPE_PROPERTY) {
2486 properties_cursor.remove ();
2490 if (properties->count () == 0) {
2491 properties = (_Tt_db_property_list *)NULL;
2495 static _Tt_string _tt_get_local_path (const _Tt_string &network_path,
2496 _Tt_string &hostname,
2497 _Tt_string &partition)
2499 _Tt_string temp_string = network_path;
2500 _Tt_string local_path = _tt_realpath (temp_string.split(':', hostname));
2502 _Tt_file_system file_system;
2503 _Tt_file_system_entry_ptr entry = file_system.bestMatchToPath(local_path);
2505 partition = entry->getMountPoint();
2507 _Tt_string loop_back_mount_point = entry->getLoopBackMountPoint();
2508 if (loop_back_mount_point.len()) {
2509 // Get the path info after the loop back mount point path
2510 local_path = local_path.right(local_path.len()-loop_back_mount_point.len());
2512 // Replace the loop back mount point path with the partition path
2513 local_path = partition.cat(local_path);
2520 // This is the thread that performs the garbage collection.
2521 // It is defined as a (void *) function for thr_create() compatibility.
2524 _tt_garbage_collect(void * /*NOTUSED*/)
2526 // thr_create() func returns (void *).
2527 void * results = NULL;
2529 _tt_get_all_sessions_args args;
2531 _Tt_string sessionId;
2532 _Tt_string_list *sessions;
2534 memset(&args, '\0', sizeof(args));
2536 #if defined(OPT_GARBAGE_THREADS)
2538 sigset_t new_thr_sigset;
2541 // Tell ourself (this thread only) to ignore all SIGs, or quit.
2543 if (sigfillset(&new_thr_sigset) != 0) {
2547 if (thr_sigsetmask(SIG_BLOCK, &new_thr_sigset, NULL) < 0) {
2552 isgarbage_collect(); // 1st compress the DB files.
2555 _Tt_db_client_ptr dbClient;
2557 if (!dbClient.is_null()
2558 && dbClient->getConnectionResults() == TT_DB_OK) {
2559 // Tell server to compress the files.
2560 dbClient->garbage_collect_in_server();
2563 // Get a list of all sessions.
2566 #if defined(OPT_GARBAGE_THREADS)
2567 _tt_get_all_sessions_results *sessionList;
2569 sessionList = _tt_get_all_sessions_1(&args, NULL);
2572 _Tt_string oneSession;
2574 sessions = new _Tt_string_list;
2577 ; offset < sessionList->session_list.values_len
2579 oneSession = sessionList->session_list.values_val[offset].value;
2580 sessions->append(oneSession);
2583 sessions = dbClient->get_all_sessions();
2585 if (sessions== NULL || sessions->count() == 0) {
2592 // Delete the list of sessions that are dead.
2595 #if defined(OPT_GARBAGE_THREADS)
2596 _tt_delete_session_args delsession;
2599 sessionId = sessions->top();
2600 if ((ttstatus=tt_default_session_set(sessionId)) != TT_OK) {
2602 #if defined(OPT_GARBAGE_THREADS)
2603 delsession.session.value = sessionId;
2604 _tt_delete_session_1(&delsession,NULL);
2606 dbClient->delete_session(sessionId);
2610 } while(sessions->count() > 0);
2612 #if defined(OPT_GARBAGE_THREADS)
2614 // Copy over the re-start key.
2615 // (for more than OPT_MAX_GET_SESSIONS).
2616 memcpy(&args.oidkey,
2617 &sessionList->oidkey,
2618 sizeof(args.oidkey));
2620 } while (args.oidkey.oidkey_len != 0);
2622 #if defined(OPT_GARBAGE_THREADS)
2623 mutex_unlock(&garbage_run_in_process);
2631 // Return the PID or TID of the running garbage collection function.
2634 _tt_run_garbage_collect(int in_parallel)
2636 extern FILE *errstr;
2638 /* Make sure in_parallel is used to quiet warnings */
2641 #if defined(OPT_GARBAGE_THREADS)
2642 static int mutex_inited = 0;
2644 // Error back from mutex_*() and thr_() funcs.
2647 // Times to try thr_create() if it return with EAGAIN.
2648 int create_tries = OPT_SOLARIS_THREADED_TRIES;
2650 if (!mutex_inited) {
2652 // Init the RPC syncronazation mutex lock.
2653 mutex_init(&rpc_client_busy, USYNC_THREAD, 0);
2654 mutex_init(&garbage_run_in_process, USYNC_PROCESS, 0);
2656 // Raise the priority of ourselfs to be higher
2657 // than our new thread.
2658 thr_setprio(thr_self(), 10);
2662 // See if anyone else is running, if so, then do not run
2663 // gabage collection again.
2665 if (mutex_trylock(&garbage_run_in_process) != 0) {
2666 return (_tt_garbage_id);
2672 // Start the thread and keep trying OPT_SOLARIS_THREADED_TRIES,
2673 // or until it works.
2675 while ((err = thr_create((void *)0, // stack_base - use default.
2676 (size_t)0, // stack_size - use default.
2677 _tt_garbage_collect,
2678 (void *)_TT_GARBAGE_COLLECTION_FREQUENCY,// Arg to func.
2679 THR_SUSPENDED|THR_BOUND,
2680 (thread_t *)&_tt_garbage_id)) < 0) {
2682 if (errno == EAGAIN && (--create_tries > 0)) {
2687 _tt_garbage_id = -2;
2689 // Get here only on thr_create() error.
2690 // Unable to create thread.
2692 _tt_syslog(errstr, LOG_ERR, "%s",
2693 catgets(_ttcatd, 5, 8,
2694 "Unable to start garbage collection thread. thr_create()\n"));
2699 // If we are to garbage collect in parallel, then
2700 // let the garbage thread continue at a low priority.
2702 // If we are not to garbage collect in parallel,
2703 // then let the thread run, then the main thread exits.
2705 if (in_parallel == TRUE) {
2706 if (_tt_garbage_id > 0) {
2708 // Lower the priority of garbage collection to lowest.
2709 thr_setprio(_tt_garbage_id, 0);
2712 thr_continue((thread_t)_tt_garbage_id);
2715 if (_tt_garbage_id > 0) {
2716 thr_continue((thread_t)_tt_garbage_id);
2724 #else //defined(OPT_GARBAGE_THREADS)
2726 #if defined(OPT_AUTO_GARBAG_COLLECT)
2728 // Do not start another, if one is running.
2730 if (in_parallel == TRUE) {
2731 if (_tt_garbage_id == -1) {
2733 // FORK and EXEC ourself '-G'.
2735 #if defined(OPT_BUG_AIX)
2738 switch (_tt_garbage_id = (int)vfork()) {
2741 const char *newargv[3];
2743 newargv[0] = global_argv[0];
2747 execve((const char *)newargv[0],
2748 (char *const *)newargv,
2749 (char *const *)global_envp);
2751 _tt_syslog(errstr, LOG_ERR, "%s",
2752 catgets(_ttcatd, 5, 9,
2753 "Unable to fork() for garbage collection.\n"));
2754 _tt_garbage_id = -3;
2755 _exit(1); // ERROR, so exit new child.
2760 _tt_syslog(errstr, LOG_ERR, "%s",
2761 catgets(_ttcatd, 5, 9,
2762 "Unable to fork() for garbage collection.\n"));
2763 _tt_garbage_id = -4;
2771 #endif /* OPT_AUTO_GARBAGE_COLLECT*/
2772 exit((intptr_t)_tt_garbage_collect(NULL));
2773 #if defined(OPT_AUTO_GARBAG_COLLECT)
2775 #endif /* OPT_AUTO_GARBAGE_COLLECT*/
2777 #endif // ! OPT_GARBAGE_THREADS
2778 return (_tt_garbage_id);