jafs-library-20020725
[openafs.git] / src / JAVA / classes / org / openafs / jafs / Partition.java
1 /*
2  * @(#)Partition.java   1.0 6/29/2001
3  *
4  * Copyright (c) 2001 International Business Machines Corp.
5  * All rights reserved.
6  *
7  * This software has been released under the terms of the IBM Public
8  * License.  For details, see the LICENSE file in the top-level source
9  * directory or online at http://www.openafs.org/dl/license10.html
10  * 
11  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
12  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
13  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
14  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR
15  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
16  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
17  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
18  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
19  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
20  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22  */
23
24 package org.openafs.jafs;
25
26 import java.io.Serializable;
27 import java.util.ArrayList;
28
29 /**
30  * An abstract representation of an AFS partition.  It holds information about 
31  * the partition, such as what its total space is.
32  * <BR><BR>
33  *
34  * Constructing an instance of a <code>Partition</code> does not mean 
35  * an actual AFS partition is created on a server -- on the contrary, 
36  * a <code>Partition</code> object must be a representation of an already 
37  * existing AFS partition.  There is no way to create a new AFS partition 
38  * through this API.<BR><BR>
39  *
40  * Each <code>Partition</code> object has its own individual set of
41  * <code>Volume</code>s. This represents the properties and attributes 
42  * of an actual AFS cell.<BR><BR>
43  *
44  * <!--Example of how to use class-->
45  * The following is a simple example of how to obtain and use a 
46  * <code>Partition</code> object.  In this example, a list of the 
47  * <code>Partition</code> objects of a server are obtained, and the name
48  * and number of volumes is printed out for each one.<BR><BR>
49  * 
50  * <PRE>
51  * import org.openafs.jafs.Cell;
52  * import org.openafs.jafs.AFSException;
53  * import org.openafs.jafs.Partition;
54  * import org.openafs.jafs.Server;
55  * ...
56  * public class ...
57  * {
58  *   ...
59  *   private Cell cell;
60  *   private Server server;
61  *   ...
62  *   public static void main(String[] args) throws Exception
63  *   {
64  *     String username   = arg[0];
65  *     String password   = arg[1];
66  *     String cellName   = arg[2];
67  *     String serverName = arg[3];
68  * 
69  *     token = new Token(username, password, cellName);
70  *     cell   = new Cell(token);
71  *     server = new Server(serverName, cell);
72  * 
73  *     System.out.println("Partitions in Server " + server.getName() + ":");
74  *     Partition[] partitions = server.getPartitions();
75  *     for (int i = 0; i < partitions.length; i++) {
76  *       System.out.print("Partition " + partitions[i].getName());
77  *       System.out.print("hosts " + partitions[i].getVolumeCount());
78  *       System.out.print("volumes.\n");
79  *     }
80  *   }
81  *   ...
82  * }
83  * </PRE>
84  *
85  */
86 public class Partition implements Serializable, Comparable
87 {
88   protected Cell cell;
89   protected Server server;
90
91   /* Populated by native method */
92   protected String name;
93
94   /* Populated by native method */
95   protected int id;
96
97   /* Populated by native method */
98   protected String deviceName;
99
100   /* Populated by native method */
101   protected int lockFileDescriptor;
102
103   /* Populated by native method */
104   protected int totalSpace;
105
106   /* Populated by native method */
107   protected int totalFreeSpace;
108
109   protected int totalQuota;
110
111   protected ArrayList volumes;
112   protected ArrayList volumeNames;
113
114   protected boolean cachedInfo;
115
116   /**
117    * Constructs a new <code>Partition</code> object instance given the 
118    * name of the AFS partition and the AFS server, represented by 
119    * <CODE>server</CODE>, to which it belongs.   This does not actually
120    * create a new AFS partition, it just represents an existing one.
121    * If <code>name</code> is not an actual AFS partition, exceptions
122    * will be thrown during subsequent method invocations on this 
123    * object.
124    *
125    * @param name      the name of the partition to represent 
126    * @param server    the server on which the partition resides
127    * @exception AFSException      If an error occurs in the native code
128    */
129   public Partition( String name, Server server ) throws AFSException
130   {
131     this.name = name;
132     this.server = server;
133     this.cell = server.getCell();
134     
135     id = -1;
136     
137     volumes = null;
138     volumeNames = null;
139     
140     cachedInfo = false;
141   }
142   
143   /**
144    * Constructs a new <CODE>Partition</CODE> object instance given the name 
145    * of the AFS partition and the AFS server, represented by 
146    * <CODE>server</CODE>, to which it belongs.   This does not actually
147    * create a new AFS partition, it just represents an existing one.
148    * If <code>name</code> is not an actual AFS partition, exceptions
149    * will be thrown during subsequent method invocations on this 
150    * object.
151    *
152    * <P> This constructor is ideal for point-in-time representation and 
153    * transient applications.  It ensures all data member values are set and 
154    * available without calling back to the filesystem at the first request 
155    * for them.  Use the {@link #refresh()} method to address any coherency 
156    * concerns.
157    *
158    * @param name               the name of the partition to represent 
159    * @param server             the server to which the partition belongs.
160    * @param preloadAllMembers  true will ensure all object members are 
161    *                           set upon construction;
162    *                           otherwise members will be set upon access, 
163    *                           which is the default behavior.
164    * @exception AFSException      If an error occurs in the native code
165    * @see #refresh
166    */
167   public Partition( String name, Server server, boolean preloadAllMembers ) 
168       throws AFSException
169   {
170     this(name, server);
171     if (preloadAllMembers) refresh(true);
172   }
173   
174   /**
175    * Creates a blank <code>Server</code> given the cell to which the partition
176    * belongs and the server on which the partition resides.  This blank 
177    * object can then be passed into other methods to fill out its properties.
178    *
179    * @exception AFSException      If an error occurs in the native code
180    * @param cell       the cell to which the partition belongs.
181    * @param server     the server on which the partition resides
182    */
183   Partition( Server server ) throws AFSException
184   {
185     this( null, server );
186   }
187
188   /*-------------------------------------------------------------------------*/
189
190   /**
191    * Refreshes the properties of this Partition object instance with values 
192    * from the AFS partition
193    * it represents.  All properties that have been initialized and/or 
194    * accessed will be renewed according to the values of the AFS partition 
195    * this Partition object instance represents.
196    *
197    * <P>Since in most environments administrative changes can be administered
198    * from an AFS command-line program or an alternate GUI application, this
199    * method provides a means to refresh the Java object representation and
200    * thereby ascertain any possible modifications that may have been made
201    * from such alternate administrative programs.  Using this method before
202    * an associated instance accessor will ensure the highest level of 
203    * representative accuracy, accommodating changes made external to the
204    * Java application space.  If administrative changes to the underlying AFS 
205    * system are only allowed via this API, then the use of this method is 
206    * unnecessary.
207    * 
208    * @exception AFSException  If an error occurs in the native code
209    */
210   public void refresh() throws AFSException
211   {
212     refresh(false);
213   }
214
215   /**
216    * Refreshes the properties of this Partition object instance with values 
217    * from the AFS partition it represents.  If <CODE>all</CODE> is 
218    * <CODE>true</CODE> then <U>all</U> of the properties of this Partition 
219    * object instance will be set, or renewed, according to the values of the 
220    * AFS partition it represents, disregarding any previously set properties.
221    *
222    * <P> Thus, if <CODE>all</CODE> is <CODE>false</CODE> then properties 
223    * that are currently set will be refreshed and properties that are not 
224    * set will remain uninitialized. See {@link #refresh()} for more 
225    * information.
226    *
227    * @param all   if true set or renew all object properties; otherwise 
228    * renew all set properties
229    * @exception AFSException  If an error occurs in the native code
230    * @see #refresh()
231    */
232   protected void refresh(boolean all) throws AFSException
233   {
234     if (all || volumes != null) {
235       refreshVolumes();
236     }
237     if (all || volumeNames != null) {
238       refreshVolumeNames();
239     }
240     if (all || cachedInfo) {
241       refreshInfo();
242     }
243   }
244
245   /**
246    * Refreshes the information fields of this <code>Partition</code> to 
247    * reflect the current state of the AFS partition. These include total
248    * free space, id, etc.
249    *
250    * @exception AFSException      If an error occurs in the native code
251    */
252   protected void refreshInfo() throws AFSException
253   {
254     getPartitionInfo( cell.getCellHandle(), server.getVosHandle(), getID(), 
255                       this );
256     cachedInfo = true;
257   }
258
259   /**
260    * Obtains the most current list of <code>Volume</code> objects of this 
261    * partition.
262    *
263    * @exception AFSException  If an error occurs in the native code
264    */
265   protected void refreshVolumes() throws AFSException
266   {
267     Volume currVolume;
268
269     int iterationID = getVolumesBegin( cell.getCellHandle(), 
270                                        server.getVosHandle(), getID() );
271
272     volumes = new ArrayList();
273         
274     currVolume = new Volume( this );
275     while( getVolumesNext( iterationID, currVolume ) != 0 ) {
276       volumes.add( currVolume );
277       currVolume = new Volume( this );
278     } 
279     getVolumesDone( iterationID );
280   }
281
282   /**
283    * Obtains the most current list of volume names of this partition.
284    *
285    * @exception AFSException  If an error occurs in the native code
286    */
287   protected void refreshVolumeNames() throws AFSException
288   {
289     String currName;
290
291     int iterationID = getVolumesBegin( cell.getCellHandle(), 
292                                        server.getVosHandle(), getID() );
293         
294     volumeNames = new ArrayList();
295         
296     while( ( currName = getVolumesNextString( iterationID ) ) != null ) {
297       volumeNames.add( currName );
298     } 
299     getVolumesDone( iterationID );
300   }
301
302   /**
303    * Syncs this partition to the VLDB.
304    *
305    * @exception AFSException  If an error occurs in the native code
306    */
307   public void syncPartition() throws AFSException
308   {
309     server.syncServerWithVLDB( cell.getCellHandle(), server.getVosHandle(), 
310                                getID() );
311   }
312
313   /**
314    * Syncs the VLDB to this partition.
315    *
316    * @exception AFSException  If an error occurs in the native code
317    */
318   public void syncVLDB() throws AFSException
319   {
320     server.syncVLDBWithServer( cell.getCellHandle(), server.getVosHandle(), 
321                                getID(), false );
322   }
323
324   /**
325    * Salvages (restores consistency to) this partition. Uses default values for
326    * most salvager options in order to simplify the API.
327    *
328    * @exception AFSException  If an error occurs in the native code
329    */ 
330   public void salvage() throws AFSException
331   {
332     server.salvage( cell.getCellHandle(), server.getBosHandle(), name, null, 
333                     4, null, null, false, false, false, false, false, false );
334   }
335
336   //////////////// accessors:  ////////////////////////
337
338   /**
339    * Returns the name of this partition.
340    *
341    * @return the name of this partition
342    */
343   public String getName()
344   {
345     return name;
346   }
347
348   /**
349    * Returns this partition's hosting server.
350    *
351    * @return this partition's server
352    */
353   public Server getServer()
354   {
355     return server;
356   }
357
358   /**
359    * Returns the number of volumes contained in this partition.
360    *
361    * <P>If the total list of volumes or volume names have already been
362    * collected (see {@link #getVolumes()}), then the returning value will
363    * be calculated based upon the current list.  Otherwise, AFS will be
364    * explicitly queried for the information.
365    *
366    * <P> The product of this method is not saved, and is recalculated
367    * with every call.
368    *
369    * @return the number of volumes contained in this partition.
370    * @exception AFSException  If an error occurs in any 
371    *                               of the associated native methods
372    */
373   public int getVolumeCount() throws AFSException
374   {
375     if (volumes != null) {
376       return volumes.size();
377     } else if (volumeNames != null) {
378       return volumeNames.size();
379     } else {
380       return getVolumeCount( cell.getCellHandle(), 
381                                        server.getVosHandle(), getID() );
382     }
383   }
384
385   /**
386    * Retrieves the <CODE>Volume</CODE> object (which is an abstract 
387    * representation of an actual AFS volume of this partition) designated 
388    * by <code>name</code> (i.e. "root.afs", etc.).  If a volume by 
389    * that name does not actually exist in AFS on the partition
390    * represented by this object, an {@link AFSException} will be
391    * thrown.
392    *
393    * @exception AFSException  If an error occurs in the native code
394    * @exception NullPointerException  If <CODE>name</CODE> is 
395    *                                  <CODE>null</CODE>.
396    * @param name the name of the volume to retrieve
397    * @return <CODE>Volume</CODE> designated by <code>name</code>.
398    */
399   public Volume getVolume(String name) throws AFSException
400   {
401     if (name == null) throw new NullPointerException();
402     Volume volume = new Volume(name, this);
403     return volume;
404   }
405
406   /**
407    * Retrieves an array containing all of the <code>Volume</code> objects 
408    * associated with this <code>Partition</code>, each of which is an 
409    * abstract representation of an actual AFS volume of the AFS partition.
410    * After this method is called once, it saves the array of 
411    * <code>Volume</code>s and returns that saved array on subsequent calls, 
412    * until the {@link #refresh()} method is called and a more current list 
413    * is obtained.
414    *
415    * @exception AFSException  If an error occurs in the native code
416    * @return a <code>Volume</code> array of the <code>Volume</code> 
417    *         objects of the partition.
418    * @see #refresh()
419    */
420   public Volume[] getVolumes() throws AFSException
421   {
422     if (volumes == null) refreshVolumes();
423     return (Volume[]) volumes.toArray( new Volume[volumes.size()] );
424   }
425
426   /**
427    * Returns an array containing a subset of the <code>Volume</code> objects
428    * associated with this <code>Partition</code>, each of which is an abstract
429    * representation of an actual AFS volume of the AFS partition.  The subset
430    * is a point-in-time list of volumes (<code>Volume</code> objects
431    * representing AFS volumes) starting at the complete array's index of
432    * <code>startIndex</code> and containing up to <code>length</code>
433    * elements.
434    *
435    * If <code>length</code> is larger than the number of remaining elements, 
436    * respective to <code>startIndex</code>, then this method will
437    * ignore the remaining positions requested by <code>length</code> and 
438    * return an array that contains the remaining number of elements found in 
439    * this partition's complete array of volumes.
440    *
441    * <P>This method is especially useful when managing iterations of very
442    * large lists.  {@link #getVolumeCount()} can be used to determine if
443    * iteration management is practical.
444    *
445    * <P>This method does not save the resulting data and therefore 
446    * queries AFS for each call.
447    *
448    * <P><B>Example:</B> If there are more than 50,000 volumes within this partition
449    * then only render them in increments of 10,000.
450    * <PRE>
451    * ...
452    *   Volume[] volumes;
453    *   if (partition.getVolumeCount() > 50000) {
454    *     int index = 0;
455    *     int length = 10000;
456    *     while (index < partition.getVolumeCount()) {
457    *       volumes = partition.<B>getVolumes</B>(index, length);
458    *       for (int i = 0; i < volumes.length; i++) {
459    *         ...
460    *       }
461    *       index += length;
462    *       ...
463    *     }
464    *   } else {
465    *     volumes = partition.getVolumes();
466    *     for (int i = 0; i < volumes.length; i++) {
467    *       ...
468    *     }
469    *   }
470    * ...
471    * </PRE>
472    *
473    * @param startIndex  the base zero index position at which the subset array 
474    *                    should start from, relative to the complete list of 
475    *                    elements present in AFS.
476    * @param length      the number of elements that the subset should contain
477    * @return a subset array of volumes hosted by this partition
478    * @exception AFSException  If an error occurs in the native code
479    * @see #getVolumeCount()
480    * @see #getVolumeNames(int, int)
481    * @see #getVolumes()
482    */
483   public Volume[] getVolumes(int startIndex, int length) throws AFSException
484   {
485     Volume[] volumes  = new Volume[length];
486     Volume currVolume = new Volume( this );
487     int i = 0;
488
489     int iterationID = getVolumesBeginAt( cell.getCellHandle(), 
490                                        server.getVosHandle(), getID(), startIndex );
491
492     while( getVolumesNext( iterationID, currVolume ) != 0 && i < length ) {
493       volumes[i] = currVolume;
494       currVolume = new Volume( this );
495       i++;
496     } 
497     getVolumesDone( iterationID );
498     if (i < length) {
499       Volume[] v = new Volume[i];
500       System.arraycopy(volumes, 0, v, 0, i);
501       return v;
502     } else {
503       return volumes;
504     }
505   }
506
507   /**
508    * Retrieves an array containing all of the names of volumes
509    * associated with this <code>Partition</code>. 
510    * After this method is called once, it saves the array of 
511    * <code>String</code>s and returns that saved array on subsequent calls, 
512    * until the {@link #refresh()} method is called and a more current 
513    * list is obtained.
514    *
515    * @return a <code>String</code> array of the volumes of the partition.
516    * @exception AFSException  If an error occurs in the native code
517    * @see #refresh()
518    */
519   public String[] getVolumeNames() throws AFSException
520   {
521     if (volumeNames == null) refreshVolumeNames();
522     return (String []) volumeNames.toArray( new String[volumeNames.size() ] );
523   }
524
525   /**
526    * Returns an array containing a subset of the names of volumes
527    * associated with this <code>Partition</code>.  The subset is a 
528    * point-in-time list of volume names starting at the complete array's 
529    * index of <code>startIndex</code> and containing up to <code>length</code>
530    * elements.
531    *
532    * If <code>length</code> is larger than the number of remaining elements, 
533    * respective to <code>startIndex</code>, then this method will
534    * ignore the remaining positions requested by <code>length</code> and 
535    * return an array that contains the remaining number of elements found in 
536    * this partition's complete array of volume names.
537    *
538    * <P>This method is especially useful when managing iterations of very
539    * large lists.  {@link #getVolumeCount()} can be used to determine if
540    * iteration management is practical.
541    *
542    * <P>This method does not save the resulting data and therefore 
543    * queries AFS for each call.
544    *
545    * <P><B>Example:</B> If there are more than 50,000 volumes within this partition
546    * then only render them in increments of 10,000.
547    * <PRE>
548    * ...
549    *   String[] volumes;
550    *   if (partition.getVolumeCount() > 50000) {
551    *     int index = 0;
552    *     int length = 10000;
553    *     while (index < partition.getVolumeCount()) {
554    *       volumes = partition.<B>getVolumeNames</B>(index, length);
555    *       for (int i = 0; i < volumes.length; i++) {
556    *         ...
557    *       }
558    *       index += length;
559    *       ...
560    *     }
561    *   } else {
562    *     volumes = partition.getVolumeNames();
563    *     for (int i = 0; i < volumes.length; i++) {
564    *       ...
565    *     }
566    *   }
567    * ...
568    * </PRE>
569    *
570    * @param startIndex  the base zero index position at which the subset array 
571    *                    should start from, relative to the complete list of 
572    *                    elements present in AFS.
573    * @param length      the number of elements that the subset should contain
574    * @return a subset array of volume names hosted by this partition
575    * @exception AFSException  If an error occurs in the native code
576    * @see #getVolumeCount()
577    * @see #getVolumes(int, int)
578    * @see #getVolumes()
579    */
580   public String[] getVolumeNames(int startIndex, int length) throws AFSException
581   {
582     String[] volumes  = new String[length];
583     String currName;
584     int i = 0;
585
586     int iterationID = getVolumesBeginAt( cell.getCellHandle(), 
587                                        server.getVosHandle(), getID(), startIndex );
588
589     while( ( currName = getVolumesNextString( iterationID ) ) != null && i < length ) {
590       volumes[i] = currName;
591       i++;
592     } 
593     getVolumesDone( iterationID );
594     if (i < length) {
595       String[] v = new String[i];
596       System.arraycopy(volumes, 0, v, 0, i);
597       return v;
598     } else {
599       return volumes;
600     }
601   }
602
603   /**
604    * Returns the id of this partition (i.e. "vicepa" = 0, etc.)
605    *
606    * @exception AFSException  If an error occurs in the native code
607    * @return the id of this partition
608    */
609   public int getID() throws AFSException
610   {
611     if (id == -1) id = translateNameToID( name );
612     return id;
613   }
614
615   /**
616    * Returns the device name of this partition (i.e. "hda5", etc.)
617    *
618    * @exception AFSException  If an error occurs in the native code
619    * @return the device name of this partition
620    * @see #refresh()
621    */
622   public String getDeviceName() throws AFSException
623   {
624     if (!cachedInfo) refreshInfo();
625     return deviceName;
626   }
627
628   /**
629    * Returns the lock file descriptor of this partition
630    *
631    * @exception AFSException  If an error occurs in the native code
632    * @return the lock file descriptor of this partition
633    * @see #refresh()
634    */
635   public int getLockFileDescriptor() throws AFSException
636   {
637     if (!cachedInfo) refreshInfo();
638     return lockFileDescriptor;
639   }
640
641   /**
642    * Returns the total space on this partition.
643    *
644    * @exception AFSException  If an error occurs in the native code
645    * @return the total space on this partition
646    * @see #refresh()
647    */
648   public int getTotalSpace() throws AFSException
649   {
650     if (!cachedInfo) refreshInfo();
651     return totalSpace;
652   }
653
654   /**
655    * Returns the total free space on this partition.
656    * After this method is called once, it saves the total free space 
657    * and returns that value on subsequent calls, 
658    * until the {@link #refresh()} method is called and a more current 
659    * value is obtained.
660    *
661    * @exception AFSException  If an error occurs in the native code
662    * @return the total free space on this partition
663    * @see #refresh()
664    */
665   public int getTotalFreeSpace() throws AFSException
666   {
667     if (!cachedInfo) refreshInfo();
668     return totalFreeSpace;
669   }
670
671   /**
672    * Returns the total used space on this partition.
673    * After this method is called once, it saves the total used space 
674    * and returns that value on subsequent calls, 
675    * until the {@link #refresh()} method is called and a more current 
676    * value is obtained.
677    *
678    * @exception AFSException  If an error occurs in the native code
679    * @return the total used space on this partition
680    * @see #refresh()
681    */
682   public int getUsedSpace() throws AFSException
683   {
684     if (!cachedInfo) refreshInfo();
685     return (totalSpace - totalFreeSpace);
686   }
687
688   /**
689    * Returns the total combined quota of all volumes on this partition,
690    * unless a volume has configured an unlimited quota at which case an
691    * {@link AFSException} is thrown.
692    *
693    * <P>After this method is called once, it saves the value and returns 
694    * that value on subsequent calls, until the {@link #refresh()} 
695    * method is called and a more current value is obtained.
696    *
697    * @exception AFSException  If an error occurs while retrieving and 
698    *                               calculating, or a volume has an 
699    *                               unlimited quota.
700    * @return the total combined quota of all volumes on this partition
701    * @see #getTotalQuota(boolean)
702    * @see #hasVolumeWithUnlimitedQuota()
703    * @see Volume#getQuota()
704    */
705   public int getTotalQuota() throws AFSException
706   {
707     return getTotalQuota(false);
708   }
709
710   /**
711    * Returns the total combined quota of all volumes on this partition,
712    * ignoring volumes with unlimited quotas, if <CODE>
713    * ignoreUnlimitedQuotas</CODE> is <CODE>true</CODE>; otherwise an
714    * {@link AFSException} is thrown if a volume has an unlimited quota.
715    *
716    * <P>After this method is called once, it saves the value and returns 
717    * that value on subsequent calls, until the {@link #refresh()} 
718    * method is called and a more current value is obtained.
719    *
720    * @exception AFSException  If an error occurs while retrieving and 
721    *                               calculating, or a volume has an 
722    *                               unlimited quota.
723    * @return the total combined quota of all volumes on this partition
724    * @see #getTotalQuota()
725    * @see #hasVolumeWithUnlimitedQuota()
726    * @see Volume#getQuota()
727    * @see #refresh()
728    */
729   public int getTotalQuota(boolean ignoreUnlimitedQuotas) 
730     throws AFSException
731   {
732     if (volumes == null) refreshVolumes();
733     if (totalQuota == 0 || !ignoreUnlimitedQuotas) {
734       Volume[] volumes = getVolumes();
735       for (int i = 0; i < volumes.length; i++) {
736         try {
737           totalQuota += volumes[i].getQuota();
738         } catch (AFSException e) {
739           if (!ignoreUnlimitedQuotas) {
740             totalQuota = 0;
741             throw e;
742           }
743         }
744       }
745     }
746     return totalQuota;
747   }
748
749   /**
750    * Tests whether this partition contains a volume that has an unlimited
751    * quota configured.
752    *
753    * @exception AFSException  If an error occurs in the native code
754    * @return <CODE>true</CODE> if a contained volume's quota is configured
755    *         as unlimited; otherwise <CODE>false</CODE>.
756    * @see #getTotalQuota()
757    * @see #getTotalQuota(boolean)
758    * @see Volume#isQuotaUnlimited()
759    * @see Volume#getQuota()
760    * @see #refresh()
761    */
762   public boolean hasVolumeWithUnlimitedQuota() throws AFSException
763   {
764     if (volumes == null) refreshVolumes();
765     Volume[] volumes = getVolumes();
766     for (int i = 0; i < volumes.length; i++) {
767       if (volumes[i].isQuotaUnlimited()) return true;
768     }
769     return false;
770   }
771
772   /////////////// custom information methods ////////////////////
773
774   /**
775    * Returns a <code>String</code> representation of this 
776    * <code>Partition</code>.  Contains the information fields and a list of 
777    * volumes.
778    *
779    * @return a <code>String</code> representation of the <code>Partition</code>
780    */
781   protected String getInfo()
782   {
783     String r;
784     
785     try {
786         
787         r = "Partition: " + name + "\tid: " + getID() + "\n";
788         
789         r += "\tDevice name: " + getDeviceName() + "\n";
790         r += "\tLock file descriptor: " + getLockFileDescriptor() + "\n";
791         r += "\tTotal free space: " + getTotalFreeSpace() + " K\n";
792         r += "\tTotal space: " + getTotalSpace() + " K\n";
793
794         r += "\tVolumes:\n";
795
796         String vols[] = getVolumeNames();
797
798         for( int i = 0; i < vols.length; i++ ) {
799             r += "\t\t" + vols[i] + "\n";
800         }
801
802     } catch( Exception e ) {
803         return e.toString();
804     }
805     return r;
806   }
807
808   /**
809    * Returns a <code>String</code> containing the <code>String</code> 
810    * representations of all the volumes of this <code>Partition</code>.
811    *
812    * @return    a <code>String</code> representation of the volumes
813    * @see       Volume#getInfo
814    */
815   protected String getInfoVolumes() throws AFSException
816   {
817         String r;
818
819         r = "Partition: " + name + "\n\n";
820         r += "--Volumes--\n";
821
822         Volume vols[] = getVolumes();
823         for( int i = 0; i < vols.length; i++ ) {
824             r += vols[i].getInfo() + "\n";
825         }
826         return r;
827   }
828
829   /////////////// custom override methods ////////////////////
830
831   /**
832    * Compares two Partition objects respective to their names and does not
833    * factor any other attribute.    Alphabetic case is significant in 
834    * comparing names.
835    *
836    * @param     partition    The Partition object to be compared to 
837    *                         this Partition instance
838    * 
839    * @return    Zero if the argument is equal to this Partition's name, a
840    *            value less than zero if this Partition's name is
841    *            lexicographically less than the argument, or a value greater
842    *            than zero if this Partition's name is lexicographically
843    *            greater than the argument
844    */
845   public int compareTo(Partition partition)
846   {
847     return this.getName().compareTo(partition.getName());
848   }
849
850   /**
851    * Comparable interface method.
852    *
853    * @see #compareTo(Partition)
854    */
855   public int compareTo(Object obj)
856   {
857     return compareTo((Partition)obj);
858   }
859
860   /**
861    * Tests whether two <code>Partition</code> objects are equal, 
862    * based on their names and hosting server.
863    *
864    * @param otherPartition   the Partition to test
865    * @return whether the specifed Partition is the same as this Partition
866    */
867   public boolean equals( Partition otherPartition )
868   {
869     return ( name.equals(otherPartition.getName()) ) &&
870            ( getServer().equals(otherPartition.getServer()) );
871   }
872
873   /**
874    * Returns the name of this <CODE>Partition</CODE>
875    *
876    * @return the name of this <CODE>Partition</CODE>
877    */
878   public String toString()
879   {
880     return getName();
881   }
882
883   /////////////// native methods ////////////////////
884
885   /**
886    * Fills in the information fields of the provided <code>Partition</code>.
887    *
888    * @param cellHandle    the handle of the cell to which the partition belongs
889    * @see Cell#getCellHandle
890    * @param serverHandle  the vos handle of the server on which the 
891    *                      partition resides
892    * @see Server#getVosServerHandle
893    * @param partition   the numeric id of the partition for which to get the 
894    *                    info
895    * @param thePartition   the {@link Partition Partition} object in which to 
896    *                       fill in the information
897    * @exception AFSException   If an error occurs in the native code
898    */
899   protected static native void getPartitionInfo( int cellHandle, 
900                                                  int serverHandle, 
901                                                  int partition, 
902                                                  Partition thePartition ) 
903     throws AFSException;
904
905   /**
906    * Returns the total number of volumes hosted by this partition.
907    *
908    * @param cellHandle    the handle of the cell to which the partition belongs
909    * @param serverHandle  the vos handle of the server to which the partition 
910    *                      belongs
911    * @param partition   the numeric id of the partition on which the volumes 
912    *                    reside
913    * @return total number of volumes hosted by this partition
914    * @exception AFSException  If an error occurs in the native code
915    * @see Cell#getCellHandle
916    * @see Server#getVosServerHandle
917    */
918   protected static native int getVolumeCount( int cellHandle, 
919                                                int serverHandle, 
920                                                int partition )
921     throws AFSException;
922
923   /**
924    * Begin the process of getting the volumes on a partition.  Returns 
925    * an iteration ID to be used by subsequent calls to 
926    * <code>getVolumesNext</code> and <code>getVolumesDone</code>.  
927    *
928    * @param cellHandle    the handle of the cell to which the partition belongs
929    * @see Cell#getCellHandle
930    * @param serverHandle  the vos handle of the server to which the partition 
931    *                      belongs
932    * @see Server#getVosServerHandle
933    * @param partition   the numeric id of the partition on which the volumes 
934    *                    reside
935    * @return an iteration ID
936    * @exception AFSException  If an error occurs in the native code
937    */
938   protected static native int getVolumesBegin( int cellHandle, 
939                                                int serverHandle, 
940                                                int partition )
941     throws AFSException;
942
943   /**
944    * Begin the process of getting the volumes on a partition.  Returns 
945    * an iteration ID to be used by subsequent calls to 
946    * <code>getVolumesNext</code> and <code>getVolumesDone</code>.  
947    *
948    * @param cellHandle    the handle of the cell to which the partition belongs
949    * @see Cell#getCellHandle
950    * @param serverHandle  the vos handle of the server to which the partition 
951    *                      belongs
952    * @see Server#getVosServerHandle
953    * @param partition   the numeric id of the partition on which the volumes 
954    *                    reside
955    * @return an iteration ID
956    * @exception AFSException  If an error occurs in the native code
957    */
958   protected static native int getVolumesBeginAt( int cellHandle, 
959                                                  int serverHandle, 
960                                                  int partition, int index )
961     throws AFSException;
962
963   /**
964    * Returns the next volume of the partition.  Returns <code>null</code> 
965    * if there are no more volumes.
966    *
967    * @param iterationId   the iteration ID of this iteration
968    * @see #getVolumesBegin
969    * @return the name of the next volume of the server
970    * @exception AFSException  If an error occurs in the native code
971    */
972   protected static native String getVolumesNextString( int iterationId )
973     throws AFSException;
974
975   /**
976    * Fills the next volume object of the partition.  Returns 0 if there
977    * are no more volumes, != 0 otherwise.
978    *
979    * @param iterationId   the iteration ID of this iteration
980    * @param theVolume    the Volume object in which to fill the values 
981    *                     of the next volume
982    * @see #getVolumesBegin
983    * @return 0 if there are no more volumes, != 0 otherwise
984    * @exception AFSException  If an error occurs in the native code
985    */
986   protected static native int getVolumesNext( int iterationId, 
987                                               Volume theVolume )
988     throws AFSException;
989
990   /**
991    * Fills the next volume object of the partition.  Returns 0 if there
992    * are no more volumes, != 0 otherwise.
993    *
994    * @param iterationId   the iteration ID of this iteration
995    * @param theVolume    the Volume object in which to fill the values of the 
996    *                     next volume
997    * @see #getVolumesBegin
998    * @return 0 if there are no more volumes, != 0 otherwise
999    * @exception AFSException  If an error occurs in the native code
1000    */
1001   protected static native int getVolumesAdvanceTo( int iterationId, 
1002                                                    Volume theVolume, 
1003                                                    int advanceCount )
1004     throws AFSException;
1005
1006   /**
1007    * Signals that the iteration is complete and will not be accessed anymore.
1008    *
1009    * @param iterationId   the iteration ID of this iteration
1010    * @see #getVolumesBegin
1011    * @exception AFSException  If an error occurs in the native code
1012    */
1013   protected static native void getVolumesDone( int iterationId )
1014     throws AFSException;
1015
1016   /**
1017    * Translates a partition name into a partition id
1018    *
1019    * @param name  the name of the partition in question
1020    * @return   the id of the partition in question
1021    * @exception AFSException  If an error occurs in the native code
1022    */
1023   protected static native int translateNameToID( String name )
1024     throws AFSException;
1025
1026   /**
1027    * Translates a partition id into a partition name
1028    *
1029    * @param id  the id of the partition in question
1030    * @return   the name of the partition in question
1031    * @exception AFSException  If an error occurs in the native code
1032    */
1033   protected static native String translateIDToName( int id )
1034     throws AFSException;
1035
1036   /**
1037    * Reclaims all memory being saved by the partition portion of the native 
1038    * library. This method should be called when no more <code>Partition</code> 
1039    * objects are expected to be
1040    * used.
1041    */
1042   protected static native void reclaimPartitionMemory();
1043 }
1044
1045
1046
1047
1048
1049
1050
1051
1052