jafs-library-20020725
[openafs.git] / src / JAVA / libjafs / Server.c
1 /*
2  * Copyright (c) 2001-2002 International Business Machines Corp.
3  * All rights reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  * 
9  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
10  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
11  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
12  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR
13  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
14  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
15  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
16  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
17  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
18  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
19  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
20  */
21
22 #include "Internal.h"
23 #include "org_openafs_jafs_Server.h"
24
25 #include <afs_clientAdmin.h>
26 #include <afs_vosAdmin.h>
27 #include <afs_bosAdmin.h>
28 #include <afs_AdminCommonErrors.h>
29 #include <rx/rxkad.h>
30 #include <bnode.h>
31
32 //// definitions in Internal.c  //////////////////
33
34 extern jclass serverCls;
35 extern jfieldID server_nameField;
36 extern jfieldID server_nameField;
37 extern jfieldID server_databaseField;
38 extern jfieldID server_fileServerField;
39 extern jfieldID server_badDatabaseField;
40 extern jfieldID server_badFileServerField;
41 extern jfieldID server_IPAddressField;
42
43 extern jclass exectimeCls;
44 extern jfieldID exectime_HourField;
45 extern jfieldID exectime_MinField;
46 extern jfieldID exectime_SecField;
47 extern jfieldID exectime_DayField;
48 extern jfieldID exectime_NowField;
49 extern jfieldID exectime_NeverField;
50
51 extern jclass partitionCls;
52 extern jfieldID partition_cachedInfoField;
53
54 extern jclass keyCls;
55 extern jfieldID key_cachedInfoField;
56
57 extern jclass processCls;
58 extern jfieldID process_cachedInfoField;
59 extern jfieldID process_nameField;
60 //extern jfieldID process_serverHandleField;
61
62 extern jclass userCls;
63 extern jfieldID user_nameField;
64 extern jfieldID user_cachedInfoField;
65 //////////////////////////////////////////////////////////
66
67 ///// definition in jafs_Partition.c /////////////////
68
69 extern void fillPartitionInfo( JNIEnv *env, jobject partition, 
70                                vos_partitionEntry_t partEntry );
71
72 ///////////////////////////////////////////////////
73
74 ///// definition in jafs_Key.c /////////////////
75
76 extern void fillKeyInfo( JNIEnv *env, jobject key, bos_KeyInfo_t keyEntry );
77
78 ///////////////////////////////////////////////////
79
80 ///// definition in jafs_Process.c /////////////////
81
82 extern void getProcessInfoChar( JNIEnv *env, void *serverHandle, 
83                                 const char *processName, jobject process );
84
85 ///////////////////////////////////////////////////
86
87 /**
88  * Extract the information from the given server entry and populate the
89  * given object
90  *
91  * env      the Java environment
92  * cellHandle    the handle of the cell to which the server belongs
93  * server      the Server object to populate with the info
94  * servEntry     the container of the server's information
95  */
96 void fillServerInfo
97   ( JNIEnv *env, jint cellHandle, jobject server, afs_serverEntry_t servEntry )
98 {
99   jstring jip;
100   jobjectArray jaddresses;
101   jstring jserver;
102   int i = 0;
103
104   // get the class fields if need be
105   if( serverCls == 0 ) {
106     internal_getServerClass( env, server );
107   }
108
109   // in case it's blank
110   jserver = (*env)->NewStringUTF(env, servEntry.serverName);
111   (*env)->SetObjectField(env, server, server_nameField, jserver);
112
113   // let's convert just the addresses in the address array into an IP
114   jaddresses = (jobjectArray) (*env)->GetObjectField( env, server, 
115                                                       server_IPAddressField );
116   for (i = 0; i < 16; i++) {
117         if (servEntry.serverAddress[i] != 0) {
118           jip = 
119             (*env)->NewStringUTF(env, (char *) 
120                                  inet_ntoa(htonl(servEntry.serverAddress[i])));
121       (*env)->SetObjectArrayElement(env, jaddresses, i, jip);
122         } else {
123           break;
124         }
125   }
126
127   // let's check if this is really a database server
128   (*env)->SetBooleanField(env, server, server_databaseField, 
129                           servEntry.serverType & DATABASE_SERVER);
130   if( servEntry.serverType & DATABASE_SERVER ) {
131     // for now, if it thinks it's a database server than it is
132     // later, add checks for database configuration, and actual 
133     // on-ness of the machine
134     (*env)->SetBooleanField(env, server, server_badDatabaseField, FALSE);
135   } else {
136     (*env)->SetBooleanField(env, server, server_badDatabaseField, FALSE);
137   }
138
139   // we should check to see if this is truly a file server or not
140   // it could just be an old remnant, left over inside the vldb that 
141   // should be removed.
142   // if it is a file server, mark it as such.  If not, mark it as faulty.
143   (*env)->SetBooleanField(env, server, server_fileServerField,  
144                           servEntry.serverType & FILE_SERVER);
145   if( servEntry.serverType & FILE_SERVER ) {
146     
147     // to see if it's really a file server, make sure the 
148     // "fs" process is running
149     void *bosHandle;
150     afs_status_t ast;
151     bos_ProcessType_t processTypeT;
152     bos_ProcessInfo_t processInfoT;
153     char *fileServerProcessName = "fs";
154
155     // set the file server to true (it thinks it's a file server)
156     (*env)->SetBooleanField(env, server, server_fileServerField, TRUE);
157
158     if( !bos_ServerOpen( (void *) cellHandle, servEntry.serverName, 
159                          &bosHandle, &ast ) ) {
160       throwAFSException( env, ast );
161       return;
162     }
163     if( !bos_ProcessInfoGet( bosHandle, fileServerProcessName, &processTypeT, 
164                              &processInfoT, &ast ) ) {
165       // if the machine does not have a fs process or is not responding 
166       // or is part of another cell
167       if( ast == BZNOENT || ast == -1 || ast == RXKADBADTICKET ) {
168         (*env)->SetBooleanField(env, server, server_badFileServerField, TRUE);
169       // otherwise
170       } else {
171         throwAFSException( env, ast );
172         return;
173       }
174     } else {
175       // it's good
176       (*env)->SetBooleanField(env, server, server_badFileServerField, FALSE);
177     }
178   } else {
179     (*env)->SetBooleanField(env, server, server_badFileServerField, FALSE);
180   }
181
182 }
183
184 /**
185  * Fills in the information fields of the provided Server. 
186  *
187  * env      the Java environment
188  * cls      the current Java class
189  * cellHandle    the handle of the cell to which the server belongs
190  * jname     the name of the server for which to get the information
191  * server     the Server object in which to fill in 
192  *                   the information
193  */
194 JNIEXPORT void JNICALL 
195 Java_org_openafs_jafs_Server_getServerInfo (JNIEnv *env, jclass cls, 
196                                                jint cellHandle, jstring jname, 
197                                                jobject server) {
198
199   const char *name;
200   afs_status_t ast;
201   afs_serverEntry_t servEntry;
202
203   if( jname != NULL ) {
204     name = (*env)->GetStringUTFChars(env, jname, 0);
205     if( !name ) {
206         throwAFSException( env, JAFSADMNOMEM );
207         return;    
208     }
209   } else {
210     name = NULL;
211   }
212
213   // get the server entry
214   if ( !afsclient_AFSServerGet( (void *) cellHandle, name, 
215                                 &servEntry, &ast ) ) {
216     if( name != NULL ) {
217       (*env)->ReleaseStringUTFChars(env, jname, name);
218     }
219     throwAFSException( env, ast );
220     return;
221   }
222
223   fillServerInfo( env, cellHandle, server, servEntry );
224
225   if( name != NULL ) {
226     (*env)->ReleaseStringUTFChars(env, jname, name);
227   }
228
229 }
230
231 /**
232  * Returns the total number of partitions hosted by the server denoted by
233  * serverHandle, if the server is a fileserver.
234  *
235  * env      the Java environment
236  * cls      the current Java class
237  * cellHandle    the handle of the cell to which the server belongs
238  * serverHandle  the vos handle of the server to which the 
239  *                      partitions belong
240  * returns total number of partitions
241  */
242 JNIEXPORT jint JNICALL 
243 Java_org_openafs_jafs_Server_getPartitionCount (JNIEnv *env, jclass cls, 
244                                                    jint cellHandle, 
245                                                    jint serverHandle) {
246
247   afs_status_t ast;
248   void *iterationId;
249   vos_partitionEntry_t partEntry;
250   int i = 0;
251
252   if( !vos_PartitionGetBegin( (void *) cellHandle, (void *) serverHandle, 
253                               NULL, &iterationId, &ast ) ) {
254     throwAFSException( env, ast );
255     return -1;
256   }
257
258   while ( vos_PartitionGetNext( (void *) iterationId, &partEntry, &ast ) ) i++;
259
260   if( ast != ADMITERATORDONE ) {
261     throwAFSException( env, ast );
262     return -1;
263   }
264
265   return i;
266 }
267
268 /**
269  * Begin the process of getting the partitions on a server.  Returns 
270  * an iteration ID to be used by subsequent calls to 
271  * getPartitionsNext and getPartitionsDone.  
272  *
273  * env      the Java environment
274  * cls      the current Java class
275  * cellHandle    the handle of the cell to which the server belongs
276  * serverHandle  the vos handle of the server to which the 
277  *                      partitions belong
278  * returns an iteration ID
279  */
280 JNIEXPORT jint JNICALL 
281 Java_org_openafs_jafs_Server_getPartitionsBegin (JNIEnv *env, jclass cls, 
282                                                     jint cellHandle, 
283                                                     jint serverHandle) {
284
285   afs_status_t ast;
286   void *iterationId;
287
288   if( !vos_PartitionGetBegin( (void *) cellHandle, (void *) serverHandle, 
289                               NULL, &iterationId, &ast ) ) {
290     throwAFSException( env, ast );
291     return;
292   }
293
294   return (jint) iterationId;
295
296 }
297
298 /**
299  * Returns the next partition of the server.  Returns null 
300  * if there are no more partitions.
301  *
302  * env      the Java environment
303  * cls      the current Java class
304  * iterationId   the iteration ID of this iteration
305  * returns the name of the next partition of the server
306  */
307 JNIEXPORT jstring JNICALL 
308 Java_org_openafs_jafs_Server_getPartitionsNextString (JNIEnv *env, 
309                                                          jclass cls, 
310                                                          jint iterationId) {
311
312   afs_status_t ast;
313   jstring jpartition;
314   vos_partitionEntry_t partEntry;
315
316   if( !vos_PartitionGetNext( (void *) iterationId, &partEntry, &ast ) ) {
317     if( ast == ADMITERATORDONE ) {
318       return NULL;
319     } else {
320       throwAFSException( env, ast );
321       return;
322     }
323   }
324
325   jpartition = (*env)->NewStringUTF(env, partEntry.name);
326   return jpartition;
327
328 }
329
330 /**
331  * Fills the next partition object of the server.  Returns 0 if there
332  * are no more partitions, != 0 otherwise
333  *
334  * env      the Java environment
335  * cls      the current Java class
336  * iterationId   the iteration ID of this iteration
337  * thePartition   the Partition object in which to fill the 
338  *                       values of the next partition
339  * returns 0 if there are no more servers, != 0 otherwise
340  */
341 JNIEXPORT jint JNICALL 
342 Java_org_openafs_jafs_Server_getPartitionsNext (JNIEnv *env, jclass cls, 
343                                                    jint iterationId, 
344                                                    jobject jpartitionObject) {
345     
346   afs_status_t ast;
347   vos_partitionEntry_t partEntry;
348
349   if( !vos_PartitionGetNext( (void *) iterationId, &partEntry, &ast ) ) {
350     if( ast == ADMITERATORDONE ) {
351       return 0;
352     } else {
353       throwAFSException( env, ast );
354       return 0;
355     }
356   }
357
358   fillPartitionInfo( env, jpartitionObject, partEntry );
359
360   // get the class fields if need be
361   if( partitionCls == 0 ) {
362     internal_getPartitionClass( env, jpartitionObject );
363   }
364   (*env)->SetBooleanField( env, jpartitionObject, partition_cachedInfoField, 
365                            TRUE );
366
367     
368   return 1;
369
370 }
371
372 /**
373  * Signals that the iteration is complete and will not be accessed anymore.
374  *
375  * env      the Java environment
376  * cls      the current Java class
377  * iterationId   the iteration ID of this iteration
378  */
379 JNIEXPORT void JNICALL 
380 Java_org_openafs_jafs_Server_getPartitionsDone (JNIEnv *env, jclass cls, 
381                                                    jint iterationId) {
382
383   afs_status_t ast;
384
385   if( !vos_PartitionGetDone( (void *) iterationId, &ast ) ) {
386     throwAFSException( env, ast );
387     return;
388   }
389
390 }
391
392 /**
393  * Adds the given to name to the list of bos administrators on that server.
394  *
395  * env      the Java environment
396  * cls      the current Java class
397  * serverHandle  the bos handle of the server to which the 
398  *                      partitions belong
399  * jnewAdmin   the name of the admin to add to the list
400  */
401 JNIEXPORT void JNICALL 
402 Java_org_openafs_jafs_Server_addBosAdmin (JNIEnv *env, jclass cls, 
403                                              jint serverHandle, 
404                                              jstring jnewAdmin) {
405
406   afs_status_t ast;
407   const char *newAdmin;
408
409   if( jnewAdmin != NULL ) {
410     newAdmin = (*env)->GetStringUTFChars(env, jnewAdmin, 0);
411     if( !newAdmin ) {
412         throwAFSException( env, JAFSADMNOMEM );
413         return;    
414     }
415   } else {
416     newAdmin = NULL;
417   }
418
419   if( !bos_AdminCreate( (void *) serverHandle, newAdmin, &ast ) ) {
420     if( newAdmin != NULL ) {
421       (*env)->ReleaseStringUTFChars(env, jnewAdmin, newAdmin);
422     }
423     throwAFSException( env, ast );
424     return;
425   }
426
427   if( newAdmin != NULL ) {
428     (*env)->ReleaseStringUTFChars(env, jnewAdmin, newAdmin);
429   }
430
431 }
432
433 /**
434  * Removes the given to name from the list of bos administrators on 
435  * that server.
436  *
437  * env      the Java environment
438  * cls      the current Java class
439  * serverHandle  the bos handle of the server to which the 
440  *                      partitions belong
441  * joldAdmin   the name of the admin to remove from the list
442  */
443 JNIEXPORT void JNICALL 
444 Java_org_openafs_jafs_Server_removeBosAdmin (JNIEnv *env, jclass cls, 
445                                                 jint serverHandle, 
446                                                 jstring joldAdmin) {
447
448   afs_status_t ast;
449   const char *oldAdmin;
450
451   if( joldAdmin != NULL ) {
452     oldAdmin = (*env)->GetStringUTFChars(env, joldAdmin, 0);
453     if( !oldAdmin ) {
454         throwAFSException( env, JAFSADMNOMEM );
455         return;    
456     }
457   } else {
458     oldAdmin = NULL;
459   }
460
461   if( !bos_AdminDelete( (void *) serverHandle, oldAdmin, &ast ) ) {
462     if( oldAdmin != NULL ) {
463       (*env)->ReleaseStringUTFChars(env, joldAdmin, oldAdmin);
464     }
465     throwAFSException( env, ast );
466     return;
467   }
468
469   if( oldAdmin != NULL ) {
470     (*env)->ReleaseStringUTFChars(env, joldAdmin, oldAdmin);
471   }
472
473 }
474
475 /**
476  * Returns the total number of BOS administrators associated with the server 
477  * denoted by serverHandle.
478  *
479  * env      the Java environment
480  * cls      the current Java class
481  * serverHandle  the vos handle of the server to which the 
482  *                      BOS admins belong
483  * returns total number of BOS administrators
484  */
485 JNIEXPORT jint JNICALL 
486 Java_org_openafs_jafs_Server_getBosAdminCount (JNIEnv *env, jclass cls, 
487                                                   jint serverHandle) {
488
489   afs_status_t ast;
490   void *iterationId;
491   char *admin;
492   jstring jadmin;
493   int i = 0;
494
495   if( !bos_AdminGetBegin( (void *) serverHandle, &iterationId, &ast ) ) {
496     throwAFSException( env, ast );
497     return -1;
498   }
499
500   admin = (char *) malloc( sizeof(char)*BOS_MAX_NAME_LEN);
501
502   if( !admin ) {
503     throwAFSException( env, JAFSADMNOMEM );
504     return -1;
505   }
506
507   while ( bos_AdminGetNext( (void *) iterationId, admin, &ast ) ) i++;
508
509   free(admin);
510
511   if( ast != ADMITERATORDONE ) {
512     throwAFSException( env, ast );
513     return -1;
514   }
515
516   return i;
517 }
518
519 /**
520  * Begin the process of getting the bos amdinistrators on a server.  Returns 
521  * an iteration ID to be used by subsequent calls to 
522  * getBosAdminsNext and getBosAdminsDone.  
523  *
524  * env      the Java environment
525  * cls      the current Java class
526  * serverHandle  the bos handle of the server to which the 
527  *                      partitions belong
528  * returns an iteration ID
529  */
530 JNIEXPORT jint JNICALL 
531 Java_org_openafs_jafs_Server_getBosAdminsBegin (JNIEnv *env, jclass cls, 
532                                                    jint serverHandle) {
533
534   afs_status_t ast;
535   void *iterationId;
536
537   if( !bos_AdminGetBegin( (void *) serverHandle, &iterationId, &ast ) ) {
538     throwAFSException( env, ast );
539     return;
540   }
541
542   return (jint) iterationId;
543
544 }
545
546 /**
547  * Returns the next bos admin of the server.  Returns null 
548  * if there are no more admins.
549  *
550  * env      the Java environment
551  * cls      the current Java class
552  * iterationId   the iteration ID of this iteration
553  * returns the name of the next admin of the server
554  */
555 JNIEXPORT jstring JNICALL 
556 Java_org_openafs_jafs_Server_getBosAdminsNextString (JNIEnv *env, 
557                                                         jclass cls, 
558                                                         jint iterationId) {
559
560   afs_status_t ast;
561   jstring jadmin;
562   char *admin = (char *) malloc( sizeof(char)*BOS_MAX_NAME_LEN );
563
564   if( !admin ) {
565     throwAFSException( env, JAFSADMNOMEM );
566     return;    
567   }
568
569   if( !bos_AdminGetNext( (void *) iterationId, admin, &ast ) ) {
570     free(admin);
571     if( ast == ADMITERATORDONE ) {
572       return NULL;
573     } else {
574       throwAFSException( env, ast );
575       return;
576     }
577   }
578
579   jadmin = (*env)->NewStringUTF(env, admin);
580   free(admin);
581   return jadmin;
582
583 }
584
585 /**
586  * Returns the next bos admin of the server.  Returns 0 if there
587  * are no more admins, != 0 otherwise.
588  *
589  * env      the Java environment
590  * cls      the current Java class
591  * cellHandle    the handle of the cell to which these admins belong
592  * iterationId   the iteration ID of this iteration
593  * juserObject   the user object in which to fill the values of this admin
594  * returns 0 if no more admins, != 0 otherwise
595  */
596 JNIEXPORT jint JNICALL 
597 Java_org_openafs_jafs_Server_getBosAdminsNext (JNIEnv *env, jclass cls, 
598                                                   jint cellHandle, 
599                                                   jint iterationId, 
600                                                   jobject juserObject ) {
601     
602   afs_status_t ast;
603   char *admin;
604   jstring jadmin;
605
606   admin = (char *) malloc( sizeof(char)*BOS_MAX_NAME_LEN);
607
608   if( !admin ) {
609     throwAFSException( env, JAFSADMNOMEM );
610     return;    
611   }
612
613   if( !bos_AdminGetNext( (void *) iterationId, admin, &ast ) ) {
614     free( admin );
615     if( ast == ADMITERATORDONE ) {
616       return 0;
617     } else {
618       throwAFSException( env, ast );
619       return 0;
620     }
621   }
622
623   jadmin = (*env)->NewStringUTF(env, admin);
624
625   if( userCls == 0 ) {
626     internal_getUserClass( env, juserObject );
627   }
628
629   (*env)->SetObjectField(env, juserObject, user_nameField, jadmin);
630
631   getUserInfoChar( env, cellHandle, admin, juserObject );
632   (*env)->SetBooleanField( env, juserObject, user_cachedInfoField, TRUE );
633
634   free( admin );
635   return 1;
636
637 }
638
639 /**
640  * Signals that the iteration is complete and will not be accessed anymore.
641  *
642  * env      the Java environment
643  * cls      the current Java class
644  * iterationId   the iteration ID of this iteration
645  */
646 JNIEXPORT void JNICALL 
647 Java_org_openafs_jafs_Server_getBosAdminsDone (JNIEnv *env, jclass cls, 
648                                                   jint iterationId) {
649
650   afs_status_t ast;
651
652   if( !bos_AdminGetDone( (void *) iterationId, &ast ) ) {
653     throwAFSException( env, ast );
654     return;
655   }
656
657 }
658
659 /**
660  * Returns the total number of keys hosted by the server denoted by
661  * serverHandle.
662  *
663  * env      the Java environment
664  * cls      the current Java class
665  * serverHandle  the vos handle of the server to which the 
666  *                      keys belong
667  * returns total number of keys
668  */
669 JNIEXPORT jint JNICALL 
670 Java_org_openafs_jafs_Server_getKeyCount (JNIEnv *env, jclass cls, 
671                                              jint serverHandle) {
672
673   afs_status_t ast;
674   void *iterationId;
675   bos_KeyInfo_t keyEntry;
676   int i = 0;
677
678   if( !bos_KeyGetBegin( (void *) serverHandle, &iterationId, &ast ) ) {
679     throwAFSException( env, ast );
680     return -1;
681   }
682
683   while ( bos_KeyGetNext( (void *) iterationId, &keyEntry, &ast ) ) i++;
684
685   if( ast != ADMITERATORDONE ) {
686     throwAFSException( env, ast );
687     return -1;
688   }
689
690   return i;
691 }
692
693 /**
694  * Begin the process of getting the keys of a server.  Returns 
695  * an iteration ID to be used by subsequent calls to 
696  * getKeysNext and getKeysDone.  
697  *
698  * env      the Java environment
699  * cls      the current Java class
700  * serverHandle  the bos handle of the server to which the keys belong
701  * returns an iteration ID
702  */
703 JNIEXPORT jint JNICALL 
704 Java_org_openafs_jafs_Server_getKeysBegin (JNIEnv *env, jclass cls, 
705                                               jint serverHandle) {
706
707   afs_status_t ast;
708   void *iterationId;
709
710   if( !bos_KeyGetBegin( (void *) serverHandle, &iterationId, &ast ) ) {
711     throwAFSException( env, ast );
712     return;
713   }
714
715   return (jint) iterationId;
716
717 }
718
719 /**
720  * Returns the next key of the server.  Returns 0 if there
721  * are no more keys, != 0 otherwise.
722  *
723  * env      the Java environment
724  * cls      the current Java class
725  * iterationId   the iteration ID of this iteration
726  * jkeyObject   a Key object, in which to fill in the
727  *                 properties of the next key.
728  * returns 0 if there are no more keys, != 0 otherwise
729  */
730 JNIEXPORT jint JNICALL 
731 Java_org_openafs_jafs_Server_getKeysNext (JNIEnv *env, jclass cls, 
732                                              jint iterationId, 
733                                              jobject jkeyObject) {
734     
735   afs_status_t ast;
736   bos_KeyInfo_t keyEntry;
737
738   if( !bos_KeyGetNext( (void *) iterationId, &keyEntry, &ast ) ) {
739     if( ast == ADMITERATORDONE ) {
740       return 0;
741     } else {
742       throwAFSException( env, ast );
743       return 0;
744     }
745   }
746
747   fillKeyInfo( env, jkeyObject, keyEntry );
748
749   // get the class fields if need be
750   if( keyCls == 0 ) {
751     internal_getKeyClass( env, jkeyObject );
752   }
753
754   (*env)->SetBooleanField( env, jkeyObject, key_cachedInfoField, TRUE );
755
756   return 1;
757
758 }
759
760 /**
761  * Signals that the iteration is complete and will not be accessed anymore.
762  *
763  * env      the Java environment
764  * cls      the current Java class
765  * iterationId   the iteration ID of this iteration
766  */
767 JNIEXPORT void JNICALL 
768 Java_org_openafs_jafs_Server_getKeysDone (JNIEnv *env, jclass cls, 
769                                              jint iterationId) {
770
771   afs_status_t ast;
772
773   if( !bos_KeyGetDone( (void *) iterationId, &ast ) ) {
774     throwAFSException( env, ast );
775     return;
776   }
777
778 }
779
780 /**
781  * Returns the total number of processes hosted by the server denoted by
782  * serverHandle.
783  *
784  * env      the Java environment
785  * cls      the current Java class
786  * serverHandle  the vos handle of the server to which the 
787  *                      processes belong
788  * returns total number of processes
789  */
790 JNIEXPORT jint JNICALL 
791 Java_org_openafs_jafs_Server_getProcessCount (JNIEnv *env, jclass cls, 
792                                                  jint serverHandle) {
793
794   afs_status_t ast;
795   void *iterationId;
796   char *process;
797   jstring jprocess;
798   int i = 0;
799
800   if( !bos_ProcessNameGetBegin( (void *) serverHandle, &iterationId, &ast ) ) {
801     throwAFSException( env, ast );
802     return -1;
803   }
804
805   process = (char *) malloc( sizeof(char)*BOS_MAX_NAME_LEN );
806
807   if( !process ) {
808     throwAFSException( env, JAFSADMNOMEM );
809     return -1;
810   }
811
812   while ( bos_ProcessNameGetNext( (void *) iterationId, process, &ast ) ) i++;
813
814   free( process );
815
816   if( ast != ADMITERATORDONE ) {
817     throwAFSException( env, ast );
818     return -1;
819   }
820
821   return i;
822 }
823
824 /**
825  * Begin the process of getting the processes on a server.  Returns 
826  * an iteration ID to be used by subsequent calls to 
827  * getProcessesNext and getProcessesDone.  
828  *
829  * env      the Java environment
830  * cls      the current Java class
831  * serverHandle  the bos handle of the server to which the 
832  *                      processes belong
833  * returns an iteration ID
834  */
835 JNIEXPORT jint JNICALL 
836 Java_org_openafs_jafs_Server_getProcessesBegin (JNIEnv *env, jclass cls, 
837                                                    jint serverHandle) {
838
839   afs_status_t ast;
840   void *iterationId;
841
842   if( !bos_ProcessNameGetBegin( (void *) serverHandle, &iterationId, &ast ) ) {
843     throwAFSException( env, ast );
844     return;
845   }
846
847   return (jint) iterationId;
848
849 }
850
851 /**
852  * Returns the next process of the server.  Returns null 
853  * if there are no more processes.
854  *
855  * env      the Java environment
856  * cls      the current Java class
857  * iterationId   the iteration ID of this iteration
858  * returns the name of the next process of the cell
859  */
860 JNIEXPORT jstring JNICALL 
861 Java_org_openafs_jafs_Server_getProcessesNextString (JNIEnv *env, 
862                                                         jclass cls, 
863                                                         jint iterationId) {
864
865   afs_status_t ast;
866   jstring jprocess;
867   char *process = (char *) malloc( sizeof(char)*BOS_MAX_NAME_LEN );
868
869   if( !process ) {
870     throwAFSException( env, JAFSADMNOMEM );
871     return;    
872   }
873
874   if( !bos_ProcessNameGetNext( (void *) iterationId, process, &ast ) ) {
875     free( process );
876     if( ast == ADMITERATORDONE ) {
877       return NULL;
878     } else {
879       throwAFSException( env, ast );
880       return;
881     }
882   }
883
884   jprocess = (*env)->NewStringUTF(env, process);
885   free( process );
886   return jprocess;
887
888 }
889
890 /**
891  * Fills the next process object of the server.  Returns 0 if there
892  * are no more processes, != 0 otherwise.
893  *
894  * env      the Java environment
895  * cls      the current Java class
896  * serverHandle    the handle of the BOS server that hosts the process
897  * iterationId   the iteration ID of this iteration
898  * jprocessObject    the Process object in which to fill the 
899  *                          values of the next process
900  * returns 0 if there are no more processes, != otherwise
901  */
902 JNIEXPORT jint JNICALL 
903 Java_org_openafs_jafs_Server_getProcessesNext (JNIEnv *env, jclass cls, 
904                                                   jint serverHandle, 
905                                                   jint iterationId, 
906                                                   jobject jprocessObject) {
907     
908   afs_status_t ast;
909   char *process = (char *) malloc( sizeof(char)*BOS_MAX_NAME_LEN );
910   jstring jprocess;
911
912   if( !process ) {
913     throwAFSException( env, JAFSADMNOMEM );
914     return;    
915   }
916
917   if( !bos_ProcessNameGetNext( (void *) iterationId, process, &ast ) ) {
918     if( ast == ADMITERATORDONE ) {
919       return 0;
920     } else {
921       free( process );
922       throwAFSException( env, ast );
923       return 0;
924     }
925   }
926
927   // get the class fields if need be
928   if( processCls == 0 ) {
929     internal_getProcessClass( env, jprocessObject );
930   }
931
932   jprocess = (*env)->NewStringUTF(env, process);
933   (*env)->SetObjectField(env, jprocessObject, process_nameField, jprocess);
934
935   getProcessInfoChar( env, (void *) serverHandle, process, jprocessObject );
936
937   (*env)->SetBooleanField( env, jprocessObject, 
938                            process_cachedInfoField, TRUE );
939
940   free( process );
941   return 1;
942
943 }
944
945 /**
946  * Signals that the iteration is complete and will not be accessed anymore.
947  *
948  * env      the Java environment
949  * cls      the current Java class
950  * iterationId   the iteration ID of this iteration
951  */
952 JNIEXPORT void JNICALL 
953 Java_org_openafs_jafs_Server_getProcessesDone (JNIEnv *env, jclass cls, 
954                                                   jint iterationId) {
955
956   afs_status_t ast;
957
958   if( !bos_ProcessNameGetDone( (void *) iterationId, &ast ) ) {
959     throwAFSException( env, ast );
960     return;
961   }
962
963 }
964
965 /**
966  * Salvages (restores consistency to) a volume, partition, or server
967  *
968  * env      the Java environment
969  * cls      the current Java class
970  * cellHandle    the handle of the cell to which the volume belongs
971  * serverHandle  the bos handle of the server on which the 
972  *                      volume resides
973  * jpartName  the name of the partition to salvage, 
974  *                   can be null only if volName is 
975  *                   null
976  * jvolName  the name of the volume to salvage, 
977  *                  can be null
978  * numSalvagers   the number of salvager processes to run in parallel
979  * jtempDir   directory to place temporary files, can be 
980  *                  null
981  * jlogFile    where salvager log will be written, can be 
982  *                   null
983  * inspectAllVolumes   whether or not to inspect all volumes, 
984  *                            not just those marked as active at crash
985  * removeBadlyDamaged   whether or not to remove a volume if it's 
986  *                             badly damaged
987  * writeInodes   whether or not to record a list of inodes modified
988  * writeRootInodes   whether or not to record a list of AFS 
989  *                          inodes owned by root
990  * forceDirectory   whether or not to salvage an entire directory 
991  *                         structure
992  * forceBlockReads   whether or not to force the salvager to read 
993  *                          the partition
994  *                          one block at a time and skip badly damaged 
995  *                          blocks.  Use if partition has disk errors
996  */
997 JNIEXPORT void JNICALL 
998 Java_org_openafs_jafs_Server_salvage (JNIEnv *env, jclass cls, 
999                                          jint cellHandle, jint serverHandle, 
1000                                          jstring jpartName, jstring jvolName, 
1001                                          jint numSalvagers, jstring jtempDir, 
1002                                          jstring jlogFile, 
1003                                          jboolean inspectAllVolumes, 
1004                                          jboolean removeBadlyDamaged, 
1005                                          jboolean writeInodes, 
1006                                          jboolean writeRootInodes, 
1007                                          jboolean forceDirectory, 
1008                                          jboolean forceBlockReads) {
1009
1010   afs_status_t ast;
1011   const char *partName;
1012   const char *volName;
1013   const char *tempDir;
1014   const char *logFile;
1015   vos_force_t force;
1016   bos_SalvageDamagedVolumes_t sdv;
1017   bos_WriteInodes_t wi;
1018   bos_WriteRootInodes_t wri;
1019   bos_ForceDirectory_t forceD;
1020   bos_ForceBlockRead_t forceBR;
1021   
1022   // convert strings
1023   if( jpartName != NULL ) {
1024     partName = (*env)->GetStringUTFChars(env, jpartName, 0);    
1025     if( !partName ) {
1026         throwAFSException( env, JAFSADMNOMEM );
1027         return;    
1028     }
1029   } else {
1030     partName = NULL;
1031   }
1032   if( jvolName != NULL ) {
1033     volName = (*env)->GetStringUTFChars(env, jvolName, 0);    
1034     if( !volName ) {
1035       if( partName != NULL ) {
1036         (*env)->ReleaseStringUTFChars(env, jpartName, partName);    
1037       }
1038       throwAFSException( env, JAFSADMNOMEM );
1039       return;    
1040     }
1041   } else {
1042     volName = NULL;
1043   }
1044   if( jtempDir != NULL ) {
1045     tempDir = (*env)->GetStringUTFChars(env, jtempDir, 0);    
1046     if( !tempDir ) {
1047       if( partName != NULL ) {
1048         (*env)->ReleaseStringUTFChars(env, jpartName, partName);    
1049       }
1050       if( volName != NULL ) {
1051         (*env)->ReleaseStringUTFChars(env, jvolName, volName);    
1052       }
1053       throwAFSException( env, JAFSADMNOMEM );
1054       return;    
1055     }
1056   } else {
1057     tempDir = NULL;
1058   }
1059   if( jlogFile != NULL ) {
1060     logFile = (*env)->GetStringUTFChars(env, jlogFile, 0);    
1061     if( !logFile ) {
1062       if( partName != NULL ) {
1063         (*env)->ReleaseStringUTFChars(env, jpartName, partName);    
1064       }
1065       if( volName != NULL ) {
1066         (*env)->ReleaseStringUTFChars(env, jvolName, volName);    
1067       }
1068       if( tempDir != NULL ) {
1069         (*env)->ReleaseStringUTFChars(env, jtempDir, tempDir);    
1070       }
1071       throwAFSException( env, JAFSADMNOMEM );
1072       return;    
1073     }
1074   } else {
1075     logFile = NULL;
1076   }
1077
1078   // deal with booleans
1079   if( inspectAllVolumes ) {
1080     force = VOS_FORCE;
1081   } else {
1082     force = VOS_NORMAL;
1083   }
1084   if( removeBadlyDamaged ) {
1085     sdv = BOS_DONT_SALVAGE_DAMAGED_VOLUMES;
1086   } else {
1087     sdv = BOS_SALVAGE_DAMAGED_VOLUMES;
1088   }
1089   if( writeInodes ) {
1090     wi = BOS_SALVAGE_WRITE_INODES;
1091   } else {
1092     wi = BOS_SALVAGE_DONT_WRITE_INODES;
1093   }
1094   if( writeRootInodes ) {
1095     wri = BOS_SALVAGE_WRITE_ROOT_INODES;
1096   } else {
1097     wri = BOS_SALVAGE_DONT_WRITE_ROOT_INODES;
1098   }
1099   if( forceDirectory ) {
1100     forceD = BOS_SALVAGE_FORCE_DIRECTORIES;
1101   } else {
1102     forceD = BOS_SALVAGE_DONT_FORCE_DIRECTORIES;
1103   }
1104   if( forceBlockReads ) {
1105     forceBR = BOS_SALVAGE_FORCE_BLOCK_READS;
1106   } else {
1107     forceBR = BOS_SALVAGE_DONT_FORCE_BLOCK_READS;
1108   }
1109
1110   //salvage!
1111   if( !bos_Salvage( (void *) cellHandle, (void *) serverHandle, partName, 
1112                     volName, (int) numSalvagers, tempDir, logFile, force, sdv, 
1113                     wi, wri, forceD, forceBR, &ast ) ) {
1114     if( partName != NULL ) {
1115       (*env)->ReleaseStringUTFChars(env, jpartName, partName);    
1116     }
1117     if( volName != NULL ) {
1118       (*env)->ReleaseStringUTFChars(env, jvolName, volName);    
1119     }
1120     if( tempDir != NULL ) {
1121       (*env)->ReleaseStringUTFChars(env, jtempDir, tempDir);    
1122     }
1123     if( logFile != NULL ) {
1124       (*env)->ReleaseStringUTFChars(env, jlogFile, logFile);    
1125     }
1126     throwAFSException( env, ast );
1127     return;
1128   }
1129
1130   // release strings
1131   if( partName != NULL ) {
1132     (*env)->ReleaseStringUTFChars(env, jpartName, partName);    
1133   }
1134   if( volName != NULL ) {
1135     (*env)->ReleaseStringUTFChars(env, jvolName, volName);    
1136   }
1137   if( tempDir != NULL ) {
1138     (*env)->ReleaseStringUTFChars(env, jtempDir, tempDir);    
1139   }
1140   if( logFile != NULL ) {
1141     (*env)->ReleaseStringUTFChars(env, jlogFile, logFile);    
1142   }
1143
1144 }
1145
1146 /**
1147  *  Fills in the restart time fields of the given Server
1148  *  object. 
1149  *
1150  * env      the Java environment
1151  * cls      the current Java class
1152  * serverHandle  the bos handle of the server to which the key belongs
1153  * jtype  whether to get the general or binary restart. 
1154  *               Acceptable values are:
1155  *               org_opemafs_jafs_Server_RESTART_BINARY
1156  *               org_opemafs_jafs_Server_RESTART_GENERAL    
1157  * execTime   the ExecutableTime object, in which 
1158  *                   to fill the restart time fields
1159  */
1160 JNIEXPORT void JNICALL 
1161 Java_org_openafs_jafs_Server_getRestartTime
1162   (JNIEnv *env, jclass cls, jint serverHandle, jint jtype, jobject exectime)
1163 {
1164   afs_status_t ast;
1165   bos_Restart_t type;
1166   bos_RestartTime_t time;
1167   jfieldID hourField;
1168   jfieldID minField;
1169   jfieldID secField;
1170   jfieldID dayField;
1171   jfieldID neverField;
1172   jfieldID nowField;
1173
1174   // get the class fields if need be
1175   if( exectimeCls == 0 ) {
1176     internal_getExecTimeClass( env, exectime );
1177   }
1178
1179   if( jtype == org_openafs_jafs_Server_RESTART_BINARY ) {
1180     type = BOS_RESTART_DAILY;
1181   } else {
1182     type = BOS_RESTART_WEEKLY;
1183   }
1184
1185   hourField  = exectime_HourField;
1186   minField   = exectime_MinField;
1187   secField   = exectime_SecField;
1188   dayField   = exectime_DayField;
1189   neverField = exectime_NeverField;
1190   nowField   = exectime_NowField;
1191
1192   if( !bos_ExecutableRestartTimeGet( (void *) serverHandle, type, 
1193                                      &time, &ast ) ) {
1194     throwAFSException( env, ast );
1195     return;
1196   }
1197   
1198   // set now
1199   (*env)->SetBooleanField(env, exectime, nowField, 
1200                           (time.mask & BOS_RESTART_TIME_NOW) );
1201   
1202   // set never
1203   (*env)->SetBooleanField(env, exectime, neverField, 
1204                           (time.mask & BOS_RESTART_TIME_NEVER) );
1205
1206   // set hour
1207   (*env)->SetShortField(env, exectime, hourField, time.hour );
1208
1209   // set minute
1210   (*env)->SetShortField(env, exectime, minField, time.min );
1211
1212   // set second
1213   (*env)->SetShortField(env, exectime, secField, time.sec );
1214
1215   // set day
1216   if( time.mask & BOS_RESTART_TIME_DAY ) {
1217     (*env)->SetShortField(env, exectime, dayField, time.day );
1218   } else {
1219     (*env)->SetShortField(env, exectime, dayField, (jshort) -1 );
1220   }
1221
1222 }
1223
1224 /**
1225  *  Sets the restart time of the bos server.
1226  *
1227  * env      the Java environment
1228  * cls      the current Java class
1229  * serverHandle  the bos handle of the server to which the key belongs
1230  * jtype  whether this is to be a general or binary restart. 
1231  *               Acceptable values are:
1232  *               org_opemafs_jafs_Server_RESTART_BINARY
1233  *               org_opemafs_jafs_Server_RESTART_GENERAL
1234  * executableTime   the ExecutableTime object containing the 
1235  *                         desired information
1236  */
1237 JNIEXPORT void JNICALL 
1238 Java_org_openafs_jafs_Server_setRestartTime (JNIEnv *env, jclass cls, 
1239                                                 jint serverHandle, jint jtype, 
1240                                                 jobject exectime ) {
1241
1242   afs_status_t ast;
1243   bos_Restart_t type;
1244   bos_RestartTime_t time;
1245   jboolean doHour;
1246   jboolean doMinute;
1247   jboolean doSecond;
1248   jboolean doDay;
1249   jboolean doNever;
1250   jboolean doNow;  
1251   jshort hour;
1252   jshort minute;
1253   jshort second;
1254   jshort day;
1255   jfieldID hourField;
1256   jfieldID minField;
1257   jfieldID secField;
1258   jfieldID dayField;
1259   jfieldID neverField;
1260   jfieldID nowField;
1261
1262   // get the class fields if need be
1263   if( exectimeCls == 0 ) {
1264     internal_getExecTimeClass( env, exectime );
1265   }
1266
1267   if( jtype == org_openafs_jafs_Server_RESTART_BINARY ) {
1268     type = BOS_RESTART_DAILY;
1269   } else {
1270     type = BOS_RESTART_WEEKLY;
1271   }
1272
1273   hourField  = exectime_HourField;
1274   minField   = exectime_MinField;
1275   secField   = exectime_SecField;
1276   dayField   = exectime_DayField;
1277   neverField = exectime_NeverField;
1278   nowField   = exectime_NowField;
1279
1280   hour = (*env)->GetShortField(env, exectime, hourField );
1281   if( hour != 0 ) {
1282     doHour = TRUE;
1283   } else {
1284     doHour = FALSE;
1285   }
1286   minute = (*env)->GetShortField(env, exectime, minField );
1287   if( minute != 0 ) {
1288     doMinute = TRUE;
1289   } else {
1290     doMinute = FALSE;
1291   }
1292   second = (*env)->GetShortField(env, exectime, secField );
1293   if( second != 0 ) {
1294     doSecond = TRUE;
1295   } else {
1296     doSecond = FALSE;
1297   }
1298   day = (*env)->GetShortField(env, exectime, dayField );
1299   if( day != -1 ) {
1300     doDay = TRUE;
1301   } else {
1302     doDay = FALSE;
1303   }
1304   doNever = (*env)->GetBooleanField(env, exectime, neverField );
1305   doNow = (*env)->GetBooleanField(env, exectime, nowField );
1306
1307   bzero(&time, sizeof(time));
1308
1309   if( jtype == org_openafs_jafs_Server_RESTART_BINARY ) {
1310     type = BOS_RESTART_DAILY;
1311   } else {
1312     type = BOS_RESTART_WEEKLY;
1313   }  
1314
1315   if( doHour ) {
1316     time.mask |= BOS_RESTART_TIME_HOUR;
1317   }
1318   if( doMinute ) {
1319     time.mask |= BOS_RESTART_TIME_MINUTE;
1320   }
1321   if( doSecond ) {
1322     time.mask |= BOS_RESTART_TIME_SECOND;
1323   }
1324   if( doDay ) {
1325     time.mask |= BOS_RESTART_TIME_DAY;
1326   }
1327   if( doNever ) {
1328     time.mask |= BOS_RESTART_TIME_NEVER;
1329   }
1330   if( doNow ) {
1331     time.mask |= BOS_RESTART_TIME_NOW;
1332   }
1333
1334   time.hour = hour;
1335   time.min = minute;
1336   time.sec = second;
1337   time.day = day;
1338
1339   if( !bos_ExecutableRestartTimeSet( (void *) serverHandle, type, 
1340                                      time, &ast ) ) {
1341     throwAFSException( env, ast );
1342     return;
1343   }
1344
1345 }
1346
1347 /**
1348  *  Synchronizes a particular server with the volume location database.
1349  *
1350  * env      the Java environment
1351  * cls      the current Java class
1352  * cellHandle    the handle of the cell to which the server belongs
1353  * serverHandle  the vos handle of the server     
1354  * partition   the id of the partition to sync, can be -1 to ignore
1355  */
1356 JNIEXPORT void JNICALL 
1357 Java_org_openafs_jafs_Server_syncServerWithVLDB (JNIEnv *env, jclass cls, 
1358                                                     jint cellHandle, 
1359                                                     jint serverHandle, 
1360                                                     jint partition) {
1361
1362   afs_status_t ast;
1363   int *part;
1364
1365   if( partition == -1 ) {
1366     part = NULL;
1367   } else {
1368     part = (int *) &partition;
1369   }
1370
1371   if( !vos_ServerSync( (void *) cellHandle, (void *) serverHandle, 
1372                        NULL, part, &ast ) ) {
1373     throwAFSException( env, ast );
1374     return;
1375   }
1376
1377 }
1378
1379 /**
1380  *  Synchronizes the volume location database with a particular server.
1381  *
1382  * env      the Java environment
1383  * cls      the current Java class
1384  * cellHandle    the handle of the cell to which the server belongs
1385  * serverHandle  the vos handle of the server     
1386  * partition   the id of the partition to sync, can be -1 to ignore
1387  * forceDeletion   whether or not to force the deletion of bad volumes
1388  */
1389 JNIEXPORT void JNICALL 
1390 Java_org_openafs_jafs_Server_syncVLDBWithServer (JNIEnv *env, jclass cls, 
1391                                                     jint cellHandle, 
1392                                                     jint serverHandle, 
1393                                                     jint partition, 
1394                                                     jboolean forceDeletion) {
1395
1396   afs_status_t ast;
1397   int *part;
1398   vos_force_t force;
1399
1400   if( partition == -1 ) {
1401     part = NULL;
1402   } else {
1403     part = (int *) &partition;
1404   }
1405   
1406   if( forceDeletion ) {
1407     force = VOS_FORCE;
1408   } else {
1409     force = VOS_NORMAL;
1410   }
1411
1412   if( !vos_VLDBSync( (void *) cellHandle, (void *) serverHandle, NULL, part, 
1413                      force, &ast ) ) {
1414     throwAFSException( env, ast );
1415     return;
1416   }
1417
1418 }
1419
1420 /**
1421  * Start all server processes.
1422  *
1423  * env      the Java environment
1424  * cls      the current Java class
1425  * serverHandle  the bos handle of the server to which the 
1426  *                      processes belong
1427  */
1428 JNIEXPORT void JNICALL 
1429 Java_org_openafs_jafs_Server_startAllProcesses (JNIEnv *env, jclass cls, 
1430                                                    jint serverHandle) {
1431
1432   afs_status_t ast;
1433
1434   if( !bos_ProcessAllStart( (void *) serverHandle, &ast ) ) {
1435     throwAFSException( env, ast );
1436     return;
1437   }
1438
1439 }
1440
1441 /**
1442  * Stop all server processes.
1443  *
1444  * env      the Java environment
1445  * cls      the current Java class
1446  * serverHandle  the bos handle of the server to which the 
1447  *                      processes belong
1448  */
1449 JNIEXPORT void JNICALL 
1450 Java_org_openafs_jafs_Server_stopAllProcesses (JNIEnv *env, jclass cls, 
1451                                                   jint serverHandle) {
1452
1453   afs_status_t ast;
1454
1455   if( !bos_ProcessAllStop( (void *) serverHandle, &ast ) ) {
1456     throwAFSException( env, ast );
1457     return;
1458   }
1459
1460 }
1461
1462 /**
1463  * Restart all server processes.
1464  *
1465  * env      the Java environment
1466  * cls      the current Java class
1467  * serverHandle  the bos handle of the server to which the 
1468  *                      processes belong
1469  * restartBosServer   whether or not to restart the bos server as well
1470  */
1471 JNIEXPORT void JNICALL 
1472 Java_org_openafs_jafs_Server_restartAllProcesses (JNIEnv *env, jclass cls, 
1473                                                      jint serverHandle, 
1474                                                    jboolean restartBosServer) {
1475
1476   afs_status_t ast;
1477   bos_RestartBosServer_t rbs;
1478   
1479   if( restartBosServer ) {
1480     rbs = BOS_RESTART_BOS_SERVER;
1481   } else {
1482     rbs = BOS_DONT_RESTART_BOS_SERVER;
1483   }
1484
1485   if( !bos_ProcessAllStopAndRestart( (void *) serverHandle, rbs, &ast ) ) {
1486     throwAFSException( env, ast );
1487     return;
1488   }
1489
1490 }
1491
1492 /**
1493  * Retrieves a specified bos log from a server.  Right now this 
1494  * method will simply return a huge String containing the log, but 
1495  * hopefully we can devise a better way to make this work more efficiently.
1496  *
1497  * env      the Java environment
1498  * cls      the current Java class
1499  * serverHandle  the bos handle of the server to which the key belongs
1500  * jlogFile   the full path and name of the desired bos log
1501  */
1502 JNIEXPORT jstring JNICALL 
1503 Java_org_openafs_jafs_Server_getLog(JNIEnv *env, jclass cls, 
1504                                        jint serverHandle, jstring jlogFile) {
1505
1506     afs_status_t ast;
1507     const char *logFile;
1508     char *logData;
1509     unsigned long currInLogSize = 1;
1510     unsigned long currOutLogSize = 0;
1511     jstring logOut;
1512
1513     if( jlogFile != NULL ) {
1514       logFile = (*env)->GetStringUTFChars(env, jlogFile, 0);
1515       if( !logFile ) {
1516           throwAFSException( env, JAFSADMNOMEM );
1517           return;    
1518       }
1519     } else {
1520       logFile = NULL;
1521     }
1522
1523     logData = (char *) malloc( sizeof(char)*currInLogSize );
1524     if( !logData ) {
1525       throwAFSException( env, JAFSADMNOMEM );
1526       return;    
1527     }
1528
1529     // check how big the log is . . .
1530     if( !bos_LogGet( (void *) serverHandle, logFile, 
1531                      &currOutLogSize, logData, &ast ) ) {
1532       // anything but not enough room in buffer
1533       if( ast != ADMMOREDATA ) {
1534         free( logData );
1535         if( logFile != NULL ) { 
1536           (*env)->ReleaseStringUTFChars(env, jlogFile, logFile);
1537         }
1538         throwAFSException( env, ast );
1539         return NULL;
1540       }
1541     }
1542
1543     free( logData );
1544
1545     // increase log size (plus one for terminator)
1546     currInLogSize = currOutLogSize + 1;
1547     // allocate buffer
1548     logData = (char *) malloc( sizeof(char)*currInLogSize );
1549     if( !logData ) {
1550       throwAFSException( env, JAFSADMNOMEM );
1551       return;    
1552     }
1553
1554     if( !logData ) {
1555       // memory exception
1556       if( logFile != NULL ) { 
1557           (*env)->ReleaseStringUTFChars(env, jlogFile, logFile);
1558       }
1559       throwAFSException( env, ast );
1560       return NULL;
1561     }
1562
1563     // get the log for real
1564     if( !bos_LogGet( (void *) serverHandle, logFile, &currOutLogSize, 
1565                      logData, &ast ) ) {
1566         free( logData );
1567         if( logFile != NULL ) { 
1568           (*env)->ReleaseStringUTFChars(env, jlogFile, logFile);
1569         }
1570         (*env)->ReleaseStringUTFChars(env, jlogFile, logFile);
1571         throwAFSException( env, ast );
1572         return NULL;
1573     }
1574     
1575     logData[currOutLogSize] == '\0';
1576
1577     logOut = (*env)->NewStringUTF(env, logData);
1578     
1579     free( logData );
1580     if( logFile != NULL ) { 
1581       (*env)->ReleaseStringUTFChars(env, jlogFile, logFile);
1582     }
1583     return logOut;
1584
1585 }
1586
1587
1588 /**
1589  * Executes any command on the specified server.
1590  *
1591  * env      the Java environment
1592  * cls      the current Java class
1593  * serverHandle  the bos handle of the server to which the key belongs
1594  * jcommand     the text of the commmand to execute
1595  */
1596 JNIEXPORT void JNICALL 
1597 Java_org_openafs_jafs_Server_executeCommand (JNIEnv *env, jclass cls, 
1598                                                 jint serverHandle, 
1599                                                 jstring jcommand) {
1600
1601   afs_status_t ast;
1602   const char *command;
1603
1604   if( jcommand != NULL ) {
1605     command = (*env)->GetStringUTFChars(env, jcommand, 0);
1606     if( !command ) {
1607         throwAFSException( env, JAFSADMNOMEM );
1608         return;    
1609     }
1610   } else {
1611     command = NULL;
1612   }
1613
1614   if( !bos_CommandExecute( (void *) serverHandle, command, &ast ) ) {
1615     if( command != NULL ) {
1616       (*env)->ReleaseStringUTFChars(env, jcommand, command);
1617     }
1618     throwAFSException( env, ast );
1619     return;
1620   }
1621
1622   if( command != NULL ) {
1623     (*env)->ReleaseStringUTFChars(env, jcommand, command);
1624   }
1625
1626 }
1627
1628 // reclaim global memory being used by this portion
1629 JNIEXPORT void JNICALL
1630 Java_org_openafs_jafs_Server_reclaimServerMemory (JNIEnv *env, jclass cls) {
1631
1632   if( serverCls ) {
1633       (*env)->DeleteGlobalRef(env, serverCls);
1634       serverCls = 0;
1635   }
1636
1637 }
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657