Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / lib / tt / lib / db / tt_db_file.C
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 //%%  (c) Copyright 1993, 1994 Hewlett-Packard Company                  
24 //%%  (c) Copyright 1993, 1994 International Business Machines Corp.    
25 //%%  (c) Copyright 1993, 1994 Sun Microsystems, Inc.                   
26 //%%  (c) Copyright 1993, 1994 Novell, Inc.                             
27 //%%  $XConsortium: tt_db_file.C /main/3 1995/10/23 10:01:59 rswiston $                                                         
28 /*
29  * tt_db_file.cc - Implement the TT DB server file class.
30  *
31  * Copyright (c) 1992 by Sun Microsystems, Inc.
32  *
33  * NOTE: Caching is not implemented.  Therefore all of the cache levels
34  *       are always set to -1 to force a full read from the database.
35  */
36
37 #include "util/tt_path.h"
38 #include "db/tt_db_client_consts.h"
39 #include "db/tt_db_file_utils.h"
40 #include "db/tt_db_network_path.h"
41 #include "db/tt_db_object_utils.h"
42 #include "db/tt_db_access.h"
43 #include "db/tt_db_property.h"
44
45 _Tt_db_file::
46 _Tt_db_file()
47 {
48 }
49
50 _Tt_db_file::_Tt_db_file (const _Tt_string &file)
51 {
52   if (!file.len()) {
53     dbResults = TT_DB_ERR_ILLEGAL_FILE;
54   }
55   else {
56     _Tt_db_property_list_ptr properties;
57     _Tt_db_access_ptr access;
58     dbResults = setTtDBFileDefaults(file, properties, access);
59   }
60 }
61
62 _Tt_db_file::_Tt_db_file (const _Tt_string               &file,
63                           const _Tt_db_property_list_ptr &properties,
64                           const _Tt_db_access_ptr        &access)
65 {
66   if (!file.len()) {
67     dbResults = TT_DB_ERR_ILLEGAL_FILE;
68   }
69   else {
70     dbResults = setTtDBFileDefaults(file, properties, access);
71   }
72 }
73
74 _Tt_db_results
75 _Tt_db_file::setTtDBFileDefaults (const _Tt_string               &file,
76                                   const _Tt_db_property_list_ptr &properties,
77                                   const _Tt_db_access_ptr        &access)
78 {
79   checkedDatabase = FALSE;
80   directoryFlag = FALSE;
81   dbFileCurrentAccess = new _Tt_db_access;
82   dbFileObjects = new _Tt_string_list;
83   dbFileObjectsCacheLevel = -1;
84   dbFilePropertiesCacheLevel = -1;
85   dbFilePtypes = new _Tt_string_list;
86   dbResults = TT_DB_OK;
87
88   if (access.is_null()) {
89     dbFileAccess = new _Tt_db_access;
90   }
91   else {
92     dbFileAccess = access;
93   }
94
95   if (properties.is_null()) {
96     dbFileProperties = new _Tt_db_property_list;
97   }
98   else {
99     dbFileProperties = properties;
100   }
101
102   if (file.len()) {
103     _Tt_string local_path;
104
105     if (_tt_is_network_path(file)) {
106       dbFile = _tt_network_path_to_local_path(file);
107       dbFileNetworkPath = file;
108       (void)dbFileNetworkPath.split(':', dbFileHostname);
109     }
110     else {
111       // Get the absoulte network information for the path
112       _Tt_string temp_string;
113       dbResults = _tt_db_network_path (file,
114                                        dbFile,
115                                        dbFileHostname,
116                                        dbFilePartition,
117                                        dbFileNetworkPath);
118     }
119
120     if ((dbResults == TT_DB_OK)) {
121       if (!isFileInDatabase()) {
122         if (dbResults != TT_DB_ERR_DB_OPEN_FAILED) {
123           dbResults = createDBFile();
124         }
125       }
126     }
127   }
128
129   return dbResults;
130 }
131
132 _Tt_db_file::~_Tt_db_file ()
133 {
134 }
135
136 void _Tt_db_file::setCurrentAccess (const _Tt_db_access_ptr &access)
137 {
138   dbFileCurrentAccess = access;
139 }
140
141 _Tt_db_access_ptr _Tt_db_file::getCurrentAccess () const
142 {
143   return dbFileCurrentAccess;
144 }
145
146 _Tt_db_results _Tt_db_file::remove ()
147 {
148   if (dbFileNetworkPath.len()) {
149     setCurrentDBAccess ();
150     dbResults = dbFileDatabase->removeFile(dbFileNetworkPath);
151     
152     if (dbResults == TT_DB_OK) {
153       dbFile = (char *)NULL;
154       dbFileNetworkPath = (char *)NULL;
155       dbFileProperties = (_Tt_db_property_list *)NULL;
156       dbFileAccess = (_Tt_db_access *)NULL;
157     }
158   }
159   else {
160     dbResults = TT_DB_ERR_ILLEGAL_FILE;
161   }
162
163   return processDBResults();
164 }
165
166 _Tt_db_results _Tt_db_file::copy (const _Tt_string &new_file)
167 {
168   if (!new_file.len()) {
169     return (dbResults = TT_DB_ERR_ILLEGAL_FILE);
170   }
171
172   if (isFileInDatabase()) {
173     _Tt_string new_local_path;
174     _Tt_string new_hostname;
175     _Tt_string new_partition;
176     _Tt_string new_network_path;
177     dbResults = _tt_db_network_path(new_file,
178                                     new_local_path,
179                                     new_hostname,
180                                     new_partition,
181                                     new_network_path);
182
183     if (dbResults == TT_DB_OK) {
184       // If we're not copying to the exact same file
185       if (dbFileNetworkPath != new_network_path) {
186         setCurrentDBAccess();
187         _Tt_db_property_list_ptr properties = getProperties();
188         _Tt_db_access_ptr        access = getAccess ();
189         _Tt_string_list_ptr      objids = getObjects();
190
191         if (dbResults == TT_DB_OK) {
192           _Tt_db_file_ptr new_db_file = new _Tt_db_file(new_network_path,
193                                                         properties,
194                                                         access);
195
196           _Tt_string_list_cursor objids_cursor(objids);
197           while (objids_cursor.next()) {
198             _Tt_db_object_ptr object = new _Tt_db_object(*objids_cursor);
199             (void)object->copy(new_file);
200           }
201         }
202       }
203       else {
204         dbResults = TT_DB_ERR_SAME_FILE;
205       }
206     }
207   }
208   else {
209     dbResults = TT_DB_ERR_ILLEGAL_FILE;
210   }
211
212   return dbResults;
213 }
214
215 _Tt_db_results _Tt_db_file::move (const _Tt_string &new_file)
216 {
217   if (!new_file.len()) {
218     return (dbResults = TT_DB_ERR_ILLEGAL_FILE);
219   }
220
221   if (isFileInDatabase()) {
222     // Get the hostname and remote path of the new file
223     _Tt_string new_local_path;
224     _Tt_string new_hostname;
225     _Tt_string new_partition;
226     _Tt_string new_network_path;
227     dbResults = _tt_db_network_path(new_file,
228                                     new_local_path,
229                                     new_hostname,
230                                     new_partition,
231                                     new_network_path);
232
233     if (dbResults == TT_DB_OK) {
234       // If we're not moving to the exact same file
235       if (dbFileNetworkPath != new_network_path) {
236         setCurrentDBAccess();
237       
238         if (dbResults == TT_DB_OK) {
239           // If is the new file is on the same machine...
240           if (dbFileHostname == new_hostname)  {
241             // We're not allowed to move directories across partitions
242             if (directoryFlag && (dbFilePartition != new_partition)) {
243               dbResults = TT_DB_ERR_ILLEGAL_FILE;
244             }
245             else {
246               dbResults = dbFileDatabase->moveFile(dbFileNetworkPath,
247                                                    new_network_path);
248         
249               if (dbResults == TT_DB_OK) {
250                 // Change the official file of this object
251                 _Tt_db_property_list_ptr properties;
252                 _Tt_db_access_ptr access;
253                 dbResults = setTtDBFileDefaults(new_network_path,
254                                                 properties,
255                                                 access);
256               }
257             }
258           }
259           // Else, the move is between different hosts...
260           else {
261             // We're not allowed to move directories across machines
262             if (directoryFlag) {
263               dbResults = TT_DB_ERR_ILLEGAL_FILE;
264             }
265             // Not a directory, move it...
266             else {
267               _Tt_db_property_list_ptr properties = getProperties();
268               _Tt_db_access_ptr        access = getAccess ();
269               _Tt_string_list_ptr      objids = getObjects();
270               
271               if (dbResults == TT_DB_OK) {
272                 _Tt_db_file_ptr new_db_file = new _Tt_db_file(new_network_path,
273                                                               properties,
274                                                               access);
275                 
276                 _Tt_string_list_cursor objids_cursor(objids);
277                 while (objids_cursor.next()) {
278                   _Tt_db_object_ptr object = new _Tt_db_object(*objids_cursor);
279                   (void)object->move(new_network_path);
280                 }
281               }
282             }
283             
284             if (dbResults == TT_DB_OK) {
285               dbResults = dbFileDatabase->removeFile(dbFileNetworkPath);
286             }
287           
288             if (dbResults == TT_DB_OK) {
289               // Change the official file of this object
290               _Tt_db_property_list_ptr properties;
291               _Tt_db_access_ptr access;
292               dbResults = setTtDBFileDefaults(new_network_path,
293                                               properties,
294                                               access);
295             }
296           }
297         }
298       }
299       else {
300         dbResults = TT_DB_ERR_SAME_FILE;
301       }
302     }
303   }
304   else {
305     dbResults = TT_DB_ERR_ILLEGAL_FILE;
306   }
307   
308   return dbResults;
309 }
310
311 _Tt_string _Tt_db_file::getHostname ()
312 {
313   return dbFileHostname;
314 }
315
316 _Tt_db_results
317 _Tt_db_file::setProperty (const _Tt_db_property_ptr &property)
318 {
319   if (isFileInDatabase()) {
320     setCurrentDBAccess();
321     dbResults = dbFileDatabase->setFileProperty(dbFileNetworkPath,
322                                                 property,
323                                                 dbFilePropertiesCacheLevel);
324   }
325   else {
326     dbResults = TT_DB_ERR_ILLEGAL_FILE;
327   }
328
329   return processDBResults();
330 }
331
332 _Tt_db_results
333 _Tt_db_file::setProperties (const _Tt_db_property_list_ptr &properties)
334 {
335   if (isFileInDatabase()) {
336     setCurrentDBAccess();
337     dbResults =
338       dbFileDatabase->setFileProperties(dbFileNetworkPath,
339                                         properties,
340                                         dbFilePropertiesCacheLevel);
341   }
342   else {
343     dbResults = TT_DB_ERR_ILLEGAL_FILE;
344   }
345
346   return processDBResults();
347 }
348
349 _Tt_db_results
350 _Tt_db_file::addProperty (const _Tt_db_property_ptr &property,
351                           bool_t                     unique)
352 {
353   if (isFileInDatabase()) {
354     setCurrentDBAccess();
355     dbResults = dbFileDatabase->addFileProperty(dbFileNetworkPath,
356                                                 property,
357                                                 unique,
358                                                 dbFilePropertiesCacheLevel);
359   }
360   else {
361     dbResults = TT_DB_ERR_ILLEGAL_FILE;
362   }
363
364   return processDBResults();
365 }
366
367 _Tt_db_results
368 _Tt_db_file::deleteProperty (const _Tt_db_property_ptr &property)
369 {
370   if (isFileInDatabase()) {
371     setCurrentDBAccess();
372     dbResults =
373       dbFileDatabase->deleteFileProperty(dbFileNetworkPath,
374                                          property,
375                                          dbFilePropertiesCacheLevel);
376   }
377   else {
378     dbResults = TT_DB_ERR_ILLEGAL_FILE;
379   }
380
381   return processDBResults();
382 }
383
384 _Tt_db_property_ptr _Tt_db_file::getProperty (const _Tt_string &name)
385 {
386   _Tt_db_property_ptr property;
387
388   if (isFileInDatabase()) {
389     setCurrentDBAccess();
390     dbFilePropertiesCacheLevel = -1;
391     dbResults = dbFileDatabase->getFileProperty(dbFileNetworkPath,
392                                                 name,
393                                                 dbFilePropertiesCacheLevel,
394                                                 property);
395   }
396   else {
397     dbResults = TT_DB_ERR_ILLEGAL_FILE;
398   }
399
400   dbResults = processDBResults();
401   return property;
402 }
403
404 _Tt_db_property_list_ptr _Tt_db_file::getProperties ()
405 {
406   _Tt_db_property_list_ptr properties;
407
408   if (isFileInDatabase()) {
409     setCurrentDBAccess();
410     dbFilePropertiesCacheLevel = -1;
411     dbResults = dbFileDatabase->getFileProperties(dbFileNetworkPath,
412                                                   dbFilePropertiesCacheLevel,
413                                                   properties);
414   }
415   else {
416     dbResults = TT_DB_ERR_ILLEGAL_FILE;
417   }
418
419   dbResults = processDBResults();
420   return properties;
421 }
422
423 _Tt_string_list_ptr _Tt_db_file::getObjects ()
424 {
425   _Tt_string_list_ptr objids;
426
427   if (isFileInDatabase()) {
428     setCurrentDBAccess();
429     dbFileObjectsCacheLevel = -1;
430     dbResults = dbFileDatabase->getFileObjects(dbFileNetworkPath,
431                                                dbFileObjectsCacheLevel,
432                                                objids);
433   }
434   else {
435     dbResults = TT_DB_ERR_ILLEGAL_FILE;
436   }
437
438   dbResults = processDBResults();
439   return objids;
440 }
441
442 _Tt_db_results _Tt_db_file::setAccess (const _Tt_db_access_ptr &access)
443 {
444   if (isFileInDatabase()) {
445     setCurrentDBAccess();
446     dbResults = dbFileDatabase->setFileAccess(dbFileNetworkPath, access);
447   }
448   else {
449     dbResults = TT_DB_ERR_ILLEGAL_FILE;
450   }
451
452   return processDBResults();
453 }
454
455 _Tt_db_access_ptr _Tt_db_file::getAccess ()
456 {
457   _Tt_db_access_ptr access;
458
459   if (isFileInDatabase()) {
460     setCurrentDBAccess();
461     dbResults = dbFileDatabase->getFileAccess(dbFileNetworkPath, access);
462   }
463   else {
464     dbResults = TT_DB_ERR_ILLEGAL_FILE;
465   }
466
467   dbResults = processDBResults();
468   return access;
469 }
470
471 _Tt_db_results _Tt_db_file::addSession (const _Tt_string &session)
472 {
473   _Tt_db_property_ptr property = new _Tt_db_property;
474   property->name = TT_DB_SESSION_PROPERTY;
475
476   _Tt_string value = session;
477   (void)property->values->append(value);
478
479   return addProperty(property, TRUE);
480 }
481
482 _Tt_db_results _Tt_db_file::deleteSession (const _Tt_string &session)
483 {
484   _Tt_db_property_ptr property = new _Tt_db_property;
485   property->name = TT_DB_SESSION_PROPERTY;
486
487   _Tt_string value = session;
488   property->values->append(value);
489
490   return deleteProperty(property);
491 }
492
493 _Tt_string_list_ptr _Tt_db_file::getSessions ()
494 {
495   _Tt_db_property_ptr property;
496   _Tt_string_list_ptr sessions;
497   
498   if (isFileInDatabase()) {
499     _Tt_string name(TT_DB_SESSION_PROPERTY);
500     property = getProperty(name);
501     if (dbResults == TT_DB_ERR_NO_SUCH_PROPERTY) {
502       dbResults = TT_DB_OK;
503     }
504     
505     if (!property.is_null()) {
506       if (!property->is_empty()) {
507         sessions = new _Tt_string_list;
508       
509         _Tt_string_list_cursor values_cursor(property->values);
510         while (values_cursor.next()) { 
511           sessions->append(*values_cursor);
512         }
513       }
514     }
515   }
516   
517   return sessions;
518 }
519
520 _Tt_db_results
521 _Tt_db_file::queueMessage (const _Tt_string_list_ptr &ptypes,
522                            const _Tt_message_ptr     &message)
523 {
524   if (isFileInDatabase()) {
525     dbResults = dbFileDatabase->queueMessage(dbFileNetworkPath,
526                                              ptypes,
527                                              message);
528   }
529   else {
530     dbResults = TT_DB_ERR_ILLEGAL_FILE;
531   }
532
533   return dbResults;
534 }
535                              
536 _Tt_db_results
537 _Tt_db_file::dequeueMessages (const _Tt_string_list_ptr &ptypes,
538                               _Tt_message_list_ptr      &messages)
539 {
540   if (isFileInDatabase()) {
541     dbResults = dbFileDatabase->dequeueMessages(dbFileNetworkPath,
542                                                 ptypes,
543                                                 messages);
544   }
545   else {
546     dbResults = TT_DB_ERR_ILLEGAL_FILE;
547   }
548
549   return dbResults;
550 }
551
552 _Tt_string _Tt_db_file::getNetworkPath (const _Tt_string &file)
553 {
554   _Tt_string network_path;
555
556   if (file.len()) {
557     if (_tt_is_network_path(file)) {
558       network_path = file;
559     }
560     else {
561       _Tt_string local_path;
562       _Tt_string hostname;
563       _Tt_string partition;
564
565       _Tt_db_results results = _tt_db_network_path(file,
566                                                    local_path,
567                                                    hostname,
568                                                    partition,
569                                                    network_path);
570     }
571   }
572
573   return network_path;
574 }
575
576 _Tt_db_results _Tt_db_file::createDBFile ()
577 {
578   if (!isFileInDatabase()) {
579     dbFileDatabase = dbHostnameGlobalMapRef.getDB(dbFileHostname,
580                                                   dbFileHostname,
581                                                   dbResults);
582     if (dbFileDatabase.is_null()) {
583       return dbResults;
584     }
585
586     int cache_level = -1;
587
588     setCurrentDBAccess ();
589     dbResults = dbFileDatabase->createFile(dbFileNetworkPath,
590                                            dbFileProperties,
591                                            dbFileAccess,
592                                            cache_level);
593
594     dbFileObjectsCacheLevel = cache_level;
595     dbFilePropertiesCacheLevel = cache_level;
596   }
597   else {
598     dbResults = TT_DB_ERR_FILE_EXISTS;
599   }
600
601   return processDBResults();
602 }
603
604 bool_t _Tt_db_file::isFileInDatabase ()
605 {
606         // Property caching is not currently implemented in _Tt_db_file,
607         // so this function does not read the properties from the database
608         // if the file exists.  If caching is added, this is where the
609         // cache should be initially filled from.
610
611         if (!checkedDatabase) {
612                 checkedDatabase = TRUE;
613
614                 dbFileDatabase = dbHostnameGlobalMapRef.getDB(dbFileHostname,
615                                                               dbFileHostname,
616                                                               dbResults);
617                 if (dbFileDatabase.is_null() || dbResults != TT_DB_OK) {
618                         return FALSE;
619                 }
620                 _Tt_db_access_ptr access;
621                 dbResults = dbFileDatabase->isFileInDatabase(dbFileNetworkPath,
622                                                              directoryFlag);
623
624                 if (dbResults != TT_DB_OK) {
625                         dbHostnameGlobalMapRef.removeDB(dbFileHostname);
626                         dbFileDatabase = (_Tt_db_client *)NULL;
627                 }
628         }
629
630         return (dbFileDatabase.is_null() ? FALSE : TRUE);
631 }
632
633 _Tt_db_results _Tt_db_file::processDBResults ()
634 {
635   // If an RPC fails, assume the DB server went down and attempt to
636   // reconnect to it
637   if ((dbResults == TT_DB_ERR_DB_CONNECTION_FAILED) ||
638       (dbResults == TT_DB_ERR_RPC_CONNECTION_FAILED) ||
639       (dbResults == TT_DB_ERR_RPC_FAILED) ||
640       (dbResults == TT_DB_ERR_DB_OPEN_FAILED)) {
641     if (!dbFileDatabase.is_null()) {
642       dbHostnameGlobalMapRef.removeDB(dbFileHostname);
643       dbFileDatabase = dbHostnameGlobalMapRef.getDB(dbFileHostname,
644                                                     dbFileHostname,
645                                                     dbResults);
646
647     }
648   }
649
650   return dbResults;
651 }