summaryrefslogtreecommitdiffstats
path: root/tests/winWm.test
blob: 95b71cb7146af9292ce92a8b36e3da0ae7186c80 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
# This file tests  is a Tcl script to test the procedures in the file
# tkWinWm.c.  It is organized in the standard fashion for Tcl tests.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1996 by Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# All rights reserved.
#
# RCS: @(#) $Id: winWm.test,v 1.16 2005/02/17 00:06:08 mdejong Exp $

package require tcltest 2.1
eval tcltest::configure $argv
tcltest::loadTestedCommands

# Measure the height of a single menu line

toplevel .t
frame .t.f -width 100 -height 50
pack .t.f
menu .t.m
.t.m add command -label "thisisreallylong"
.t conf -menu .t.m
wm geom .t -0-0
update
set menuheight [winfo y .t]
.t.m add command -label "thisisreallylong"
wm geom .t -0-0
update
set menuheight [expr $menuheight - [winfo y .t]]
destroy .t

test winWm-1.1 {TkWmMapWindow} win {
    toplevel .t
    wm override .t 1
    wm geometry .t +0+0
    update
    set result [list [winfo rootx .t] [winfo rooty .t]]
    destroy .t
    set result
} {0 0}
test winWm-1.2 {TkWmMapWindow} win {
    toplevel .t
    wm transient .t .
    update
    wm iconify .
    update
    wm deiconify .
    update
    catch {wm iconify .t} msg
    destroy .t
    set msg
} {can't iconify ".t": it is a transient}
test winWm-1.3 {TkWmMapWindow} win {
    toplevel .t
    update
    toplevel .t2
    update
    set result [expr [winfo x .t] != [winfo x .t2]]
    destroy .t .t2
    set result
} 1
test winWm-1.4 {TkWmMapWindow} win {
    toplevel .t
    wm geometry .t +10+10
    update
    toplevel .t2
    wm geometry .t2 +40+10
    update
    set result [list [winfo x .t] [winfo x .t2]]
    destroy .t .t2
    set result
} {10 40}
test winWm-1.5 {TkWmMapWindow} win {
    toplevel .t
    wm iconify .t
    update
    set result [wm state .t]
    destroy .t
    set result
} iconic

test winWm-2.1 {TkpWmSetState} win {
    toplevel .t
    wm geometry .t 150x50+10+10
    update
    set result [wm state .t]
    wm iconify .t
    update
    lappend result [wm state .t]
    wm deiconify .t
    update
    lappend result [wm state .t]
    destroy .t
    set result
} {normal iconic normal}
test winWm-2.2 {TkpWmSetState} win {
    toplevel .t
    wm geometry .t 150x50+10+10
    update
    set result [wm state .t]
    wm withdraw .t
    update
    lappend result [wm state .t]
    wm iconify .t
    update
    lappend result [wm state .t]
    wm deiconify .t
    update 
    lappend result [wm state .t]
    destroy .t
    set result
} {normal withdrawn iconic normal}
test winWm-2.3 {TkpWmSetState} win {
    toplevel .t
    wm geometry .t 150x50+10+10
    update
    set result [wm state .t]
    wm state .t withdrawn
    update
    lappend result [wm state .t]
    wm state .t iconic
    update
    lappend result [wm state .t]
    wm state .t normal
    update 
    lappend result [wm state .t]
    destroy .t
    set result
} {normal withdrawn iconic normal}
test winWm-2.4 {TkpWmSetState} win {
    set result {}
    toplevel .t
    wm geometry .t 150x50+10+10
    update
    lappend result [list [wm state .t] [wm geometry .t]]
    wm iconify .t
    update
    lappend result [list [wm state .t] [wm geometry .t]]
    wm geometry .t 200x50+10+10
    update
    lappend result [list [wm state .t] [wm geometry .t]]
    wm deiconify .t
    update
    lappend result [list [wm state .t] [wm geometry .t]]
    destroy .t
    set result
} {{normal 150x50+10+10} {iconic 150x50+10+10} {iconic 150x50+10+10} {normal 200x50+10+10}}

test winWm-3.1 {ConfigureTopLevel: window geometry propagation} win {
    toplevel .t
    wm geometry .t +0+0
    button .t.b
    pack .t.b
    update
    set x [winfo x .t.b]
    destroy .t
    toplevel .t
    wm geometry .t +0+0
    button .t.b
    update
    pack .t.b
    update
    set x [expr $x == [winfo x .t.b]]
    destroy .t
    set x
} 1

test winWm-4.1 {ConfigureTopLevel: menu resizing} win {
    set result {}
    toplevel .t
    frame .t.f -width 150 -height 50 -bg red
    pack .t.f
    wm geometry .t -0-0
    update
    set y [winfo y .t]
    menu .t.m
    .t.m add command -label foo
    .t conf -menu .t.m
    update
    set result [expr $y - [winfo y .t]]
    destroy .t
    set result
} [expr $menuheight + 1]

test winWm-5.1 {UpdateGeometryInfo: menu resizing} win {
    set result {}
    toplevel .t
    frame .t.f -width 150 -height 50 -bg red
    pack .t.f
    update
    set result [winfo height .t]
    menu .t.m
    .t.m add command -label foo
    .t conf -menu .t.m
    update
    lappend result [winfo height .t]
    .t.m add command -label "thisisreallylong"
    .t.m add command -label "thisisreallylong"
    update
    lappend result [winfo height .t]
    destroy .t
    set result
} {50 50 50}
test winWm-5.2 {UpdateGeometryInfo: menu resizing} win {
    set result {}
    toplevel .t
    frame .t.f -width 150 -height 50 -bg red
    pack .t.f
    wm geom .t -0-0
    update
    set y [winfo rooty .t]
    lappend result [winfo height .t]
    menu .t.m
    .t conf -menu .t.m
    .t.m add command -label foo
    .t.m add command -label "thisisreallylong"
    .t.m add command -label "thisisreallylong"
    update
    lappend result [winfo height .t]
    lappend result [expr $y - [winfo rooty .t]]
    destroy .t
    set result
} {50 50 0}

test winWm-6.1 {wm attributes} win {
    destroy .t
    toplevel .t
    wm attributes .t
} {-alpha 1.0 -disabled 0 -fullscreen 0 -toolwindow 0 -topmost 0}
test winWm-6.2 {wm attributes} win {
    destroy .t
    toplevel .t
    wm attributes .t -disabled
} {0}
test winWm-6.3 {wm attributes} win {
    # This isn't quite the correct error message yet, but it works.
    destroy .t
    toplevel .t
    list [catch {wm attributes .t -foo} msg] $msg
} {1 {wrong # args: should be "wm attributes window ?-alpha ?double?? ?-disabled ?bool?? ?-fullscreen ?bool?? ?-toolwindow ?bool?? ?-topmost ?bool??"}}

test winWm-6.4 {wm attributes -alpha} win {
    # Expect this to return all 1.0 {} on pre-2K/XP
    destroy .t
    toplevel .t
    set res [wm attributes .t -alpha]
    # we don't return on set yet
    lappend res [wm attributes .t -alpha 0.5]
    lappend res [wm attributes .t -alpha]
    lappend res [wm attributes .t -alpha -100]
    lappend res [wm attributes .t -alpha]
    lappend res [wm attributes .t -alpha 100]
    lappend res [wm attributes .t -alpha]
    set res
} {1.0 {} 0.5 {} 0.0 {} 1.0}

test winWm-6.5 {wm attributes -alpha} win {
    destroy .t
    toplevel .t
    list [catch {wm attributes .t -alpha foo} msg] $msg
} {1 {expected floating-point number but got "foo"}}

test winWm-6.6 {wm attributes -alpha} win {
    # This test is just to show off -alpha
    destroy .t
    toplevel .t
    wm attributes .t -alpha 0.2
    pack [label .t.l -text "Alpha Toplevel" -font "Helvetica 18 bold"]
    tk::PlaceWindow .t center
    update
    if {$::tcl_platform(osVersion) >= 5.0} {
	for {set i 0.2} {$i < 0.99} {set i [expr {$i+0.02}]} {
	    wm attributes .t -alpha $i
	    update idle
	    after 20
	}
	for {set i 0.99} {$i > 0.2} {set i [expr {$i-0.02}]} {
	    wm attributes .t -alpha $i
	    update idle
	    after 20
	}
    }
} {}

test winWm-7.1 {deiconify on an unmapped toplevel\
        will raise the window and set the focus} win {
    destroy .t
    toplevel .t
    lower .t
    focus -force .
    wm deiconify .t
    update
    list [wm stackorder .t isabove .] [focus]
} {1 .t}

test winWm-7.2 {deiconify on an already mapped toplevel\
        will raise the window and set the focus} win {
    destroy .t
    toplevel .t
    lower .t
    update
    focus -force .
    wm deiconify .t
    update
    list [wm stackorder .t isabove .] [focus]
} {1 .t}

test winWm-7.3 {UpdateWrapper must maintain Z order} win {
    destroy .t
    toplevel .t
    lower .t
    update
    set res [wm stackorder .t isbelow .]
    wm resizable .t 0 0
    update
    list $res [wm stackorder .t isbelow .]
} {1 1}

test winWm-7.4 {UpdateWrapper must maintain focus} win {
    destroy .t
    toplevel .t
    focus -force .t
    update
    set res [focus]
    wm resizable .t 0 0
    update
    list $res [focus]
} {.t .t}

test winWm-8.1 {Tk_WmCmd procedure, "iconphoto" option} win {
    list [catch {wm iconph .} msg] $msg
} {1 {wrong # args: should be "wm iconphoto window ?-default? image1 ?image2 ...?"}}
test winWm-8.2 {Tk_WmCmd procedure, "iconphoto" option} win {
    destroy .t
    toplevel .t
    image create photo blank16 -width 16 -height 16
    image create photo blank32 -width 32 -height 32
    # This should just make blank icons for the window
    wm iconphoto .t blank16 blank32
    image delete blank16 blank32
} {}

destroy .t

# cleanup
cleanupTests
return
1000' href='#n1000'>1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Copyright by The HDF Group.                                               *
 * Copyright by the Board of Trustees of the University of Illinois.         *
 * All rights reserved.                                                      *
 *                                                                           *
 * This file is part of HDF5.  The full HDF5 copyright notice, including     *
 * terms governing use, modification, and redistribution, is contained in    *
 * the files COPYING and Copyright.html.  COPYING can be found at the root   *
 * of the source code distribution tree; Copyright.html can be found at the  *
 * root level of an installed copy of the electronic HDF5 document set and   *
 * is linked from the top-level documents page.  It can also be found at     *
 * http://hdfgroup.org/HDF5/doc/Copyright.html.  If you do not have          *
 * access to either file, you may request a copy from help@hdfgroup.org.     *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

/*
 * Programmer:	Robb Matzke <matzke@llnl.gov>
 *		Monday, November 10, 1997
 *
 * Purpose:	Implements a family of files that acts as a single hdf5
 *		file.  The purpose is to be able to split a huge file on a
 *		64-bit platform, transfer all the <2GB members to a 32-bit
 *		platform, and then access the entire huge file on the 32-bit
 *		platform.
 *
 *		All family members are logically the same size although their
 *		physical sizes may vary.  The logical member size is
 *		determined by looking at the physical size of the first member
 *		when the file is opened.  When creating a file family, the
 *		first member is created with a predefined physical size
 *		(actually, this happens when the file family is flushed, and
 *		can be quite time consuming on file systems that don't
 *		implement holes, like nfs).
 *
 */

#include "H5FDdrvr_module.h" /* This source code file is part of the H5FD driver module */


#include "H5private.h"		/* Generic Functions			*/
#include "H5Eprivate.h"		/* Error handling		  	*/
#include "H5Fprivate.h"		/* File access				*/
#include "H5FDprivate.h"	/* File drivers				*/
#include "H5FDfamily.h"         /* Family file driver 			*/
#include "H5Iprivate.h"		/* IDs			  		*/
#include "H5MMprivate.h"	/* Memory management			*/
#include "H5Pprivate.h"		/* Property lists			*/

/* The size of the member name buffers */
#define H5FD_FAM_MEMB_NAME_BUF_SIZE 4096

/* The driver identification number, initialized at runtime */
static hid_t H5FD_FAMILY_g = 0;

/* The description of a file belonging to this driver. */
typedef struct H5FD_family_t {
    H5FD_t	pub;		/*public stuff, must be first		*/
    hid_t	memb_fapl_id;	/*file access property list for members	*/
    hsize_t	memb_size;	/*actual size of each member file	*/
    hsize_t	pmem_size;	/*member size passed in from property	*/
    unsigned	nmembs;		/*number of family members		*/
    unsigned	amembs;		/*number of member slots allocated	*/
    H5FD_t	**memb;		/*dynamic array of member pointers	*/
    haddr_t	eoa;		/*end of allocated addresses		*/
    char	*name;		/*name generator printf format		*/
    unsigned	flags;		/*flags for opening additional members	*/

    /* Information from properties set by 'h5repart' tool */
    hsize_t	mem_newsize;	/*new member size passed in as private
                                 * property. It's used only by h5repart */
    hbool_t     repart_members; /* Whether to mark the superblock dirty
                                 * when it is loaded, so that the family
                                 * member sizes can be re-encoded       */
} H5FD_family_t;

/* Driver-specific file access properties */
typedef struct H5FD_family_fapl_t {
    hsize_t	memb_size;	/*size of each member			*/
    hid_t	memb_fapl_id;	/*file access property list of each memb*/
} H5FD_family_fapl_t;

/* Callback prototypes */
static herr_t H5FD_family_term(void);
static void *H5FD_family_fapl_get(H5FD_t *_file);
static void *H5FD_family_fapl_copy(const void *_old_fa);
static herr_t H5FD_family_fapl_free(void *_fa);
static hsize_t H5FD_family_sb_size(H5FD_t *_file);
static herr_t H5FD_family_sb_encode(H5FD_t *_file, char *name/*out*/,
		     unsigned char *buf/*out*/);
static herr_t H5FD_family_sb_decode(H5FD_t *_file, const char *name,
                    const unsigned char *buf);
static H5FD_t *H5FD_family_open(const char *name, unsigned flags,
				hid_t fapl_id, haddr_t maxaddr);
static herr_t H5FD_family_close(H5FD_t *_file);
static int H5FD_family_cmp(const H5FD_t *_f1, const H5FD_t *_f2);
static herr_t H5FD_family_query(const H5FD_t *_f1, unsigned long *flags);
static haddr_t H5FD_family_get_eoa(const H5FD_t *_file, H5FD_mem_t type);
static herr_t H5FD_family_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t eoa);
static haddr_t H5FD_family_get_eof(const H5FD_t *_file, H5FD_mem_t type);
static herr_t  H5FD_family_get_handle(H5FD_t *_file, hid_t fapl, void** file_handle);
static herr_t H5FD_family_read(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr,
			       size_t size, void *_buf/*out*/);
static herr_t H5FD_family_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr,
				size_t size, const void *_buf);
static herr_t H5FD_family_flush(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
static herr_t H5FD_family_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
static herr_t H5FD_family_lock(H5FD_t *_file, hbool_t rw);
static herr_t H5FD_family_unlock(H5FD_t *_file);

/* The class struct */
static const H5FD_class_t H5FD_family_g = {
    "family",					/*name			*/
    HADDR_MAX,					/*maxaddr		*/
    H5F_CLOSE_WEAK,				/*fc_degree		*/
    H5FD_family_term,                           /*terminate             */
    H5FD_family_sb_size,			/*sb_size		*/
    H5FD_family_sb_encode,			/*sb_encode		*/
    H5FD_family_sb_decode,			/*sb_decode		*/
    sizeof(H5FD_family_fapl_t),			/*fapl_size		*/
    H5FD_family_fapl_get,			/*fapl_get		*/
    H5FD_family_fapl_copy,			/*fapl_copy		*/
    H5FD_family_fapl_free,			/*fapl_free		*/
    0,						/*dxpl_size		*/
    NULL,					/*dxpl_copy		*/
    NULL,					/*dxpl_free		*/
    H5FD_family_open,				/*open			*/
    H5FD_family_close,				/*close			*/
    H5FD_family_cmp,				/*cmp			*/
    H5FD_family_query,		                /*query			*/
    NULL,					/*get_type_map		*/
    NULL,					/*alloc			*/
    NULL,					/*free			*/
    H5FD_family_get_eoa,			/*get_eoa		*/
    H5FD_family_set_eoa,			/*set_eoa		*/
    H5FD_family_get_eof,			/*get_eof		*/
    H5FD_family_get_handle,                     /*get_handle            */
    H5FD_family_read,				/*read			*/
    H5FD_family_write,				/*write			*/
    H5FD_family_flush,				/*flush			*/
    H5FD_family_truncate,			/*truncate		*/
    H5FD_family_lock,                           /*lock                  */
    H5FD_family_unlock,                         /*unlock                */
    H5FD_FLMAP_DICHOTOMY                        /*fl_map                */
};


/*--------------------------------------------------------------------------
NAME
   H5FD__init_package -- Initialize interface-specific information
USAGE
    herr_t H5FD__init_package()
RETURNS
    Non-negative on success/Negative on failure
DESCRIPTION
    Initializes any interface-specific data or routines.  (Just calls
    H5FD_family_init currently).

--------------------------------------------------------------------------*/
static herr_t
H5FD__init_package(void)
{
    herr_t ret_value = SUCCEED;

    FUNC_ENTER_STATIC

    if(H5FD_family_init() < 0)
        HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "unable to initialize family VFD")

done:
    FUNC_LEAVE_NOAPI(ret_value)
} /* H5FD__init_package() */


/*-------------------------------------------------------------------------
 * Function:	H5FD_family_init
 *
 * Purpose:	Initialize this driver by registering the driver with the
 *		library.
 *
 * Return:	Success:	The driver ID for the family driver.
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *              Wednesday, August  4, 1999
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
hid_t
H5FD_family_init(void)
{
    hid_t ret_value = H5FD_FAMILY_g;   /* Return value */

    FUNC_ENTER_NOAPI(FAIL)

    if(H5I_VFL != H5I_get_type(H5FD_FAMILY_g))
        H5FD_FAMILY_g = H5FD_register(&H5FD_family_g, sizeof(H5FD_class_t), FALSE);

    /* Set return value */
    ret_value = H5FD_FAMILY_g;

done:
    FUNC_LEAVE_NOAPI(ret_value)
} /* H5FD_family_init() */


/*---------------------------------------------------------------------------
 * Function:	H5FD_family_term
 *
 * Purpose:	Shut down the VFD
 *
 * Returns:     Non-negative on success or negative on failure
 *
 * Programmer:  Quincey Koziol
 *              Friday, Jan 30, 2004
 *
 *---------------------------------------------------------------------------
 */
static herr_t
H5FD_family_term(void)
{
    FUNC_ENTER_NOAPI_NOINIT_NOERR

    /* Reset VFL ID */
    H5FD_FAMILY_g=0;

    FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5FD_family_term() */


/*-------------------------------------------------------------------------
 * Function:	H5Pset_fapl_family
 *
 * Purpose:	Sets the file access property list FAPL_ID to use the family
 *		driver. The MEMB_SIZE is the size in bytes of each file
 *		member (used only when creating a new file) and the
 *		MEMB_FAPL_ID is a file access property list to be used for
 *		each family member.
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *              Wednesday, August  4, 1999
 *
 * Modifications:
 *
 *		Raymond Lu
 * 		Tuesday, Oct 23, 2001
 *		Changed the file access list to the new generic property
 *		list.
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5Pset_fapl_family(hid_t fapl_id, hsize_t msize, hid_t memb_fapl_id)
{
    herr_t ret_value;
    H5FD_family_fapl_t	fa={0, -1};
    H5P_genplist_t *plist;      /* Property list pointer */

    FUNC_ENTER_API(FAIL)
    H5TRACE3("e", "ihi", fapl_id, msize, memb_fapl_id);

    /* Check arguments */
    if(TRUE != H5P_isa_class(fapl_id, H5P_FILE_ACCESS))
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list")
    if(H5P_DEFAULT == memb_fapl_id)
        memb_fapl_id = H5P_FILE_ACCESS_DEFAULT;
    else
        if(TRUE != H5P_isa_class(memb_fapl_id, H5P_FILE_ACCESS))
            HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access list")

    /* Initialize driver specific information. */
    fa.memb_size = msize;
    fa.memb_fapl_id = memb_fapl_id;

    if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id)))
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list")
    ret_value = H5P_set_driver(plist, H5FD_FAMILY, &fa);

done:
    FUNC_LEAVE_API(ret_value)
}


/*-------------------------------------------------------------------------
 * Function:	H5Pget_fapl_family
 *
 * Purpose:	Returns information about the family file access property
 *		list though the function arguments.
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *              Wednesday, August  4, 1999
 *
 * Modifications:
 *
 *		Raymond Lu
 * 		Tuesday, Oct 23, 2001
 *		Changed the file access list to the new generic property
 *		list.
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5Pget_fapl_family(hid_t fapl_id, hsize_t *msize/*out*/, hid_t *memb_fapl_id/*out*/)
{
    H5P_genplist_t *plist;      /* Property list pointer */
    const H5FD_family_fapl_t	*fa;
    herr_t      ret_value = SUCCEED;       /* Return value */

    FUNC_ENTER_API(FAIL)
    H5TRACE3("e", "ixx", fapl_id, msize, memb_fapl_id);

    if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS)))
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access list")
    if(H5FD_FAMILY != H5P_peek_driver(plist))
        HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "incorrect VFL driver")
    if(NULL == (fa = (const H5FD_family_fapl_t *)H5P_peek_driver_info(plist)))
        HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "bad VFL driver info")
    if(msize)
        *msize = fa->memb_size;
    if(memb_fapl_id) {
        if(NULL == (plist = (H5P_genplist_t *)H5I_object(fa->memb_fapl_id)))
            HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access list")
        *memb_fapl_id = H5P_copy_plist(plist, TRUE);
    } /* end if */

done:
    FUNC_LEAVE_API(ret_value)
}


/*-------------------------------------------------------------------------
 * Function:	H5FD_family_fapl_get
 *
 * Purpose:	Gets a file access property list which could be used to
 *		create an identical file.
 *
 * Return:	Success:	Ptr to new file access property list.
 *
 *		Failure:	NULL
 *
 * Programmer:	Robb Matzke
 *              Friday, August 13, 1999
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
static void *
H5FD_family_fapl_get(H5FD_t *_file)
{
    H5FD_family_t	*file = (H5FD_family_t*)_file;
    H5FD_family_fapl_t	*fa = NULL;
    H5P_genplist_t *plist;      /* Property list pointer */
    void *ret_value = NULL;     /* Return value */

    FUNC_ENTER_NOAPI_NOINIT

    if(NULL == (fa = (H5FD_family_fapl_t *)H5MM_calloc(sizeof(H5FD_family_fapl_t))))
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")

    fa->memb_size = file->memb_size;
    if(NULL == (plist = (H5P_genplist_t *)H5I_object(file->memb_fapl_id)))
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list")
    fa->memb_fapl_id = H5P_copy_plist(plist, FALSE);

    /* Set return value */
    ret_value=fa;

done:
    if(ret_value==NULL) {
        if(fa!=NULL)
            H5MM_xfree(fa);
    } /* end if */
    FUNC_LEAVE_NOAPI(ret_value)
}


/*-------------------------------------------------------------------------
 * Function:	H5FD_family_fapl_copy
 *
 * Purpose:	Copies the family-specific file access properties.
 *
 * Return:	Success:	Ptr to a new property list
 *
 *		Failure:	NULL
 *
 * Programmer:	Robb Matzke
 *              Wednesday, August  4, 1999
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
static void *
H5FD_family_fapl_copy(const void *_old_fa)
{
    const H5FD_family_fapl_t *old_fa = (const H5FD_family_fapl_t*)_old_fa;
    H5FD_family_fapl_t *new_fa = NULL;
    H5P_genplist_t *plist;      /* Property list pointer */
    void *ret_value = NULL;     /* Return value */

    FUNC_ENTER_NOAPI_NOINIT

    if(NULL == (new_fa = (H5FD_family_fapl_t *)H5MM_malloc(sizeof(H5FD_family_fapl_t))))
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")

    /* Copy the fields of the structure */
    HDmemcpy(new_fa, old_fa, sizeof(H5FD_family_fapl_t));

    /* Deep copy the property list objects in the structure */
    if(old_fa->memb_fapl_id==H5P_FILE_ACCESS_DEFAULT) {
        if(H5I_inc_ref(new_fa->memb_fapl_id, FALSE)<0)
            HGOTO_ERROR(H5E_VFL, H5E_CANTINC, NULL, "unable to increment ref count on VFL driver")
    } /* end if */
    else {
        if(NULL == (plist = (H5P_genplist_t *)H5I_object(old_fa->memb_fapl_id)))
            HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list")
        new_fa->memb_fapl_id = H5P_copy_plist(plist, FALSE);
    } /* end else */

    /* Set return value */
    ret_value=new_fa;

done:
    if(ret_value==NULL) {
        if(new_fa!=NULL)
            H5MM_xfree(new_fa);
    } /* end if */
    FUNC_LEAVE_NOAPI(ret_value)
}


/*-------------------------------------------------------------------------
 * Function:	H5FD_family_fapl_free
 *
 * Purpose:	Frees the family-specific file access properties.
 *
 * Return:	Success:	0
 *
 *		Failure:	-1
 *
 * Programmer:	Robb Matzke
 *              Wednesday, August  4, 1999
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
static herr_t
H5FD_family_fapl_free(void *_fa)
{
    H5FD_family_fapl_t	*fa = (H5FD_family_fapl_t*)_fa;
    herr_t ret_value = SUCCEED;   /* Return value */

    FUNC_ENTER_NOAPI_NOINIT

    if(H5I_dec_ref(fa->memb_fapl_id) < 0)
        HGOTO_ERROR(H5E_VFL, H5E_CANTDEC, FAIL, "can't close driver ID")
    H5MM_xfree(fa);

done:
    FUNC_LEAVE_NOAPI(ret_value)
}


/*-------------------------------------------------------------------------
 * Function:	H5FD_family_sb_size
 *
 * Purpose:	Returns the size of the private information to be stored in
 *		the superblock.
 *
 * Return:	Success:	The super block driver data size.
 *
 *		Failure:	never fails
 *
 * Programmer:	Raymond Lu
 *              Tuesday, May 10, 2005
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
static hsize_t
H5FD_family_sb_size(H5FD_t H5_ATTR_UNUSED *_file)
{
    FUNC_ENTER_NOAPI_NOINIT_NOERR

    /* 8 bytes field for the size of member file size field should be
     * enough for now. */
    FUNC_LEAVE_NOAPI(8)
}


/*-------------------------------------------------------------------------
 * Function:	H5FD_family_sb_encode
 *
 * Purpose:	Encode driver information for the superblock. The NAME
 *		argument is a nine-byte buffer which will be initialized with
 *		an eight-character name/version number and null termination.
 *
 *		The encoding is the member file size and name template.
 *
 * Return:	Success:	0
 *
 *		Failure:	-1
 *
 * Programmer:	Raymond Lu
 *              Tuesday, May 10, 2005
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
static herr_t
H5FD_family_sb_encode(H5FD_t *_file, char *name/*out*/, unsigned char *buf/*out*/)
{
    H5FD_family_t	*file = (H5FD_family_t*)_file;

    FUNC_ENTER_NOAPI_NOINIT_NOERR

    /* Name and version number */
    HDstrncpy(name, "NCSAfami", (size_t)9);
    name[8] = '\0';

    /* Store member file size.  Use the member file size from the property here.
     * This is to guarantee backward compatibility.  If a file is created with
     * v1.6 library and the driver info isn't saved in the superblock.  We open
     * it with v1.8, the FILE->MEMB_SIZE will be the actual size of the first
     * member file (see H5FD_family_open).  So it isn't safe to use FILE->MEMB_SIZE.
     * If the file is created with v1.8, the correctness of FILE->PMEM_SIZE is
     * checked in H5FD_family_sb_decode. SLU - 2009/3/21
     */
    UINT64ENCODE(buf, (uint64_t)file->pmem_size);

    FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5FD_family_sb_encode() */


/*-------------------------------------------------------------------------
 * Function:	H5FD_family_sb_decode
 *
 * Purpose:	This function has 2 seperate purpose.  One is to decodes the
 *              superblock information for this driver. The NAME argument is
 *              the eight-character (plus null termination) name stored in i
 *              the file.  The FILE argument is updated according to the
 *              information in the superblock.
 *
 * Return:	Success:	0
 *
 *		Failure:	-1
 *
 * Programmer:	Raymond Lu
 *              Tuesday, May 10, 2005
 *
 *-------------------------------------------------------------------------
 */
static herr_t
H5FD_family_sb_decode(H5FD_t *_file, const char H5_ATTR_UNUSED *name, const unsigned char *buf)
{
    H5FD_family_t	*file = (H5FD_family_t*)_file;
    uint64_t            msize;
    herr_t ret_value = SUCCEED;   /* Return value */

    FUNC_ENTER_NOAPI_NOINIT

    /* Read member file size. Skip name template for now although it's saved. */
    UINT64DECODE(buf, msize);

    /* For h5repart only. Private property of new member size is used to signal
     * h5repart is being used to change member file size.  h5repart will open
     * files for read and write.  When the files are closed, metadata will be
     * flushed to the files and updated to this new size */
    if(file->mem_newsize)
        file->memb_size = file->pmem_size = file->mem_newsize;
    else {
        /* Default - use the saved member size */
        if(file->pmem_size == H5F_FAMILY_DEFAULT)
           file->pmem_size = msize;

        /* Check if member size from file access property is correct */
        if(msize != file->pmem_size)
            HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "Family member size should be %lu.  But the size from file access property is %lu", (unsigned long)msize, (unsigned long)file->pmem_size)

        /* Update member file size to the size saved in the superblock.
         * That's the size intended to be. */
        file->memb_size = msize;
    } /* end else */

done:
    FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FD_family_sb_decode() */


/*-------------------------------------------------------------------------
 * Function:	H5FD_family_open
 *
 * Purpose:	Creates and/or opens a family of files as an HDF5 file.
 *
 * Return:	Success:	A pointer to a new file dat structure. The
 *				public fields will be initialized by the
 *				caller, which is always H5FD_open().
 *
 *		Failure:	NULL
 *
 * Programmer:	Robb Matzke
 *              Wednesday, August  4, 1999
 *
 *-------------------------------------------------------------------------
 */
static H5FD_t *
H5FD_family_open(const char *name, unsigned flags, hid_t fapl_id,
		 haddr_t maxaddr)
{
    H5FD_family_t	*file = NULL;
    char		*memb_name = NULL, *temp = NULL;
    hsize_t		eof = HADDR_UNDEF;
    unsigned		t_flags = flags & ~H5F_ACC_CREAT;
    H5FD_t     		*ret_value = NULL;

    FUNC_ENTER_NOAPI_NOINIT

    /* Check arguments */
    if(!name || !*name)
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid file name")
    if(0 == maxaddr || HADDR_UNDEF == maxaddr)
        HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL, "bogus maxaddr")

    /* Initialize file from file access properties */
    if(NULL == (file = (H5FD_family_t *)H5MM_calloc(sizeof(H5FD_family_t))))
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to allocate file struct")
    if(H5P_FILE_ACCESS_DEFAULT == fapl_id) {
        file->memb_fapl_id = H5P_FILE_ACCESS_DEFAULT;
        if(H5I_inc_ref(file->memb_fapl_id, FALSE) < 0)
            HGOTO_ERROR(H5E_VFL, H5E_CANTINC, NULL, "unable to increment ref count on VFL driver")
        file->memb_size = 1024 * 1024 * 1024; /*1GB. Actual member size to be updated later */
        file->pmem_size = 1024 * 1024 * 1024; /*1GB. Member size passed in through property */
        file->mem_newsize = 0;            /*New member size used by h5repart only       */
    } /* end if */
    else {
        H5P_genplist_t      *plist;      /* Property list pointer */
        const H5FD_family_fapl_t *fa;

        if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id)))
            HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list")
        if(NULL == (fa = (const H5FD_family_fapl_t *)H5P_peek_driver_info(plist)))
            HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, NULL, "bad VFL driver info")

        /* Check for new family file size. It's used by h5repart only. */
        if(H5P_exist_plist(plist, H5F_ACS_FAMILY_NEWSIZE_NAME) > 0) {
            /* Get the new family file size */
            if(H5P_get(plist, H5F_ACS_FAMILY_NEWSIZE_NAME, &file->mem_newsize) < 0)
                HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get new family member size")

            /* Set flag for later */
            file->repart_members = TRUE;
        } /* end if */

        if(fa->memb_fapl_id == H5P_FILE_ACCESS_DEFAULT) {
            if(H5I_inc_ref(fa->memb_fapl_id, FALSE) < 0)
                HGOTO_ERROR(H5E_VFL, H5E_CANTINC, NULL, "unable to increment ref count on VFL driver")
            file->memb_fapl_id = fa->memb_fapl_id;
        } /* end if */
        else {
            if(NULL == (plist = (H5P_genplist_t *)H5I_object(fa->memb_fapl_id)))
                HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list")
            file->memb_fapl_id = H5P_copy_plist(plist, FALSE);
        } /* end else */
        file->memb_size = fa->memb_size; /* Actual member size to be updated later */
        file->pmem_size = fa->memb_size; /* Member size passed in through property */
    } /* end else */
    file->name = H5MM_strdup(name);
    file->flags = flags;

    /* Allocate space for the string buffers */
    if(NULL == (memb_name = (char *)H5MM_malloc(H5FD_FAM_MEMB_NAME_BUF_SIZE)))
        HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL, "unable to allocate member name")
    if(NULL == (temp = (char *)H5MM_malloc(H5FD_FAM_MEMB_NAME_BUF_SIZE)))
        HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL, "unable to allocate temporary member name")

    /* Check that names are unique */
    HDsnprintf(memb_name, H5FD_FAM_MEMB_NAME_BUF_SIZE, name, 0);
    HDsnprintf(temp, H5FD_FAM_MEMB_NAME_BUF_SIZE, name, 1);
    if(!HDstrcmp(memb_name, temp))
        HGOTO_ERROR(H5E_FILE, H5E_FILEEXISTS, NULL, "file names not unique")

    /* Open all the family members */
    while(1) {
        HDsnprintf(memb_name, H5FD_FAM_MEMB_NAME_BUF_SIZE, name, file->nmembs);

        /* Enlarge member array */
        if(file->nmembs >= file->amembs) {
            unsigned n = MAX(64, 2 * file->amembs);
            H5FD_t **x;

            HDassert(n > 0);
            if(NULL == (x = (H5FD_t **)H5MM_realloc(file->memb, n * sizeof(H5FD_t *))))
                HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to reallocate members")
            file->amembs = n;
            file->memb = x;
        } /* end if */

        /*
         * Attempt to open file. If the first file cannot be opened then fail;
         * otherwise an open failure means that we've reached the last member.
         * Allow H5F_ACC_CREAT only on the first family member.
         */
        H5E_BEGIN_TRY {
            file->memb[file->nmembs] = H5FDopen(memb_name,
                (0==file->nmembs ? flags : t_flags), file->memb_fapl_id, HADDR_UNDEF);
        } H5E_END_TRY;
        if (!file->memb[file->nmembs]) {
            if (0==file->nmembs)
                HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open member file")
            H5E_clear_stack(NULL);
            break;
        }
        file->nmembs++;
    }

    /* If the file is reopened and there's only one member file existing, this file maybe
     * smaller than the size specified through H5Pset_fapl_family().  Update the actual
     * member size.
     */
    if ((eof=H5FDget_eof(file->memb[0], H5FD_MEM_DEFAULT))) file->memb_size = eof;

    ret_value=(H5FD_t *)file;

done:
    /* Release resources */
    if(memb_name)
        H5MM_xfree(memb_name);
    if(temp)
        H5MM_xfree(temp);

    /* Cleanup and fail */
    if(ret_value == NULL && file != NULL) {
        unsigned nerrors = 0;   /* Number of errors closing member files */
        unsigned u;             /* Local index variable */

        /* Close as many members as possible. Use private function here to avoid clearing
         * the error stack. We need the error message to indicate wrong member file size. */
        for(u = 0; u < file->nmembs; u++)
            if(file->memb[u])
                if(H5FD_close(file->memb[u]) < 0)
                    nerrors++;
        if(nerrors)
            HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, NULL, "unable to close member files")

        if(file->memb)
            H5MM_xfree(file->memb);
        if(H5I_dec_ref(file->memb_fapl_id) < 0)
            HDONE_ERROR(H5E_VFL, H5E_CANTDEC, NULL, "can't close driver ID")
        if(file->name)
            H5MM_xfree(file->name);
        H5MM_xfree(file);
    } /* end if */

    FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FD_family_open() */


/*-------------------------------------------------------------------------
 * Function:	H5FD_family_close
 *
 * Purpose:	Closes a family of files.
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative with as many members closed as
 *				possible. The only subsequent operation
 *				permitted on the file is a close operation.
 *
 * Programmer:	Robb Matzke
 *              Wednesday, August  4, 1999
 *
 *-------------------------------------------------------------------------
 */
static herr_t
H5FD_family_close(H5FD_t *_file)
{
    H5FD_family_t *file = (H5FD_family_t*)_file;
    unsigned	nerrors = 0;    /* Number of errors while closing member files */
    unsigned	u;              /* Local index variable */
    herr_t      ret_value = SUCCEED;       /* Return value */

    FUNC_ENTER_NOAPI_NOINIT

    /* Close as many members as possible. Use private function here to avoid clearing
     * the error stack. We need the error message to indicate wrong member file size. */
    for(u = 0; u < file->nmembs; u++) {
        if(file->memb[u]) {
            if(H5FD_close(file->memb[u]) < 0)
                nerrors++;
            else
                file->memb[u] = NULL;
        } /* end if */
    } /* end for */
    if(nerrors)
        /* Push error, but keep going*/
        HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close member files")

    /* Clean up other stuff */
    if(H5I_dec_ref(file->memb_fapl_id) < 0)
        /* Push error, but keep going*/
        HDONE_ERROR(H5E_VFL, H5E_CANTDEC, FAIL, "can't close driver ID")
    H5MM_xfree(file->memb);
    H5MM_xfree(file->name);
    H5MM_xfree(file);

    FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FD_family_close() */


/*-------------------------------------------------------------------------
 * Function:	H5FD_family_cmp
 *
 * Purpose:	Compares two file families to see if they are the same. It
 *		does this by comparing the first member of the two families.
 *
 * Return:	Success:	like strcmp()
 *
 *		Failure:	never fails (arguments were checked by the
 *				caller).
 *
 * Programmer:	Robb Matzke
 *              Wednesday, August  4, 1999
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
static int
H5FD_family_cmp(const H5FD_t *_f1, const H5FD_t *_f2)
{
    const H5FD_family_t	*f1 = (const H5FD_family_t*)_f1;
    const H5FD_family_t	*f2 = (const H5FD_family_t*)_f2;
    int ret_value = 0;

    FUNC_ENTER_NOAPI_NOINIT_NOERR

    HDassert(f1->nmembs >= 1 && f1->memb[0]);
    HDassert(f2->nmembs >= 1 && f2->memb[0]);

    ret_value = H5FDcmp(f1->memb[0], f2->memb[0]);

    FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FD_family_cmp() */


/*-------------------------------------------------------------------------
 * Function:	H5FD_family_query
 *
 * Purpose:	Set the flags that this VFL driver is capable of supporting.
 *              (listed in H5FDpublic.h)
 *
 * Return:	Success:	non-negative
 *		Failure:	negative
 *
 * Programmer:	Quincey Koziol
 *              Friday, August 25, 2000
 *
 *-------------------------------------------------------------------------
 */
static herr_t
H5FD_family_query(const H5FD_t * _file, unsigned long *flags /* out */)
{
    const H5FD_family_t	*file = (const H5FD_family_t*)_file;    /* Family VFD info */

    FUNC_ENTER_NOAPI_NOINIT_NOERR

    /* Set the VFL feature flags that this driver supports */
    if(flags) {
        *flags = 0;
        *flags |= H5FD_FEAT_AGGREGATE_METADATA; /* OK to aggregate metadata allocations */
        *flags |= H5FD_FEAT_ACCUMULATE_METADATA; /* OK to accumulate metadata for faster writes. */
        *flags |= H5FD_FEAT_DATA_SIEVE;       /* OK to perform data sieving for faster raw data reads & writes */
        *flags |= H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */

        /* Check for flags that are set by h5repart */
        if(file && file->repart_members)
            *flags |= H5FD_FEAT_DIRTY_DRVRINFO_LOAD; /* Mark the superblock dirty when it is loaded (so the family member sizes are rewritten) */
    } /* end if */

    FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5FD_family_query() */


/*-------------------------------------------------------------------------
 * Function:	H5FD_family_get_eoa
 *
 * Purpose:	Returns the end-of-address marker for the file. The EOA
 *		marker is the first address past the last byte allocated in
 *		the format address space.
 *
 * Return:	Success:	The end-of-address-marker
 *
 *		Failure:	HADDR_UNDEF
 *
 * Programmer:	Robb Matzke
 *              Wednesday, August  4, 1999
 *
 * Modifications:
 *              Raymond Lu
 *              21 Dec. 2006
 *              Added the parameter TYPE.  It's only used for MULTI driver.
 *
 *-------------------------------------------------------------------------
 */
static haddr_t
H5FD_family_get_eoa(const H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type)
{
    const H5FD_family_t	*file = (const H5FD_family_t*)_file;

    FUNC_ENTER_NOAPI_NOINIT_NOERR

    FUNC_LEAVE_NOAPI(file->eoa)
}


/*-------------------------------------------------------------------------
 * Function:	H5FD_family_set_eoa
 *
 * Purpose:	Set the end-of-address marker for the file.
 *
 * Return:	Success:	0
 *
 *		Failure:	-1
 *
 * Programmer:	Robb Matzke
 *              Wednesday, August  4, 1999
 *
 * Modifications:
 *              Raymond Lu
 *              21 Dec. 2006
 *              Added the parameter TYPE.  It's only used for MULTI driver.
 *
 *-------------------------------------------------------------------------
 */
static herr_t
H5FD_family_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t abs_eoa)
{
    H5FD_family_t	*file = (H5FD_family_t*)_file;
    haddr_t		addr = abs_eoa;
    char		*memb_name = NULL;
    unsigned		u;                      /* Local index variable */
    herr_t              ret_value = SUCCEED;    /* Return value */

    FUNC_ENTER_NOAPI_NOINIT

    /* Allocate space for the member name buffer */
    if(NULL == (memb_name = (char *)H5MM_malloc(H5FD_FAM_MEMB_NAME_BUF_SIZE)))
        HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "unable to allocate member name")

    for(u = 0; addr || u < file->nmembs; u++) {

        /* Enlarge member array */
        if(u >= file->amembs) {
            unsigned n = MAX(64, 2 * file->amembs);
            H5FD_t **x = (H5FD_t **)H5MM_realloc(file->memb, n * sizeof(H5FD_t *));

            if(!x)
                HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory block")
            file->amembs = n;
            file->memb = x;
            file->nmembs = u;
        } /* end if */

        /* Create another file if necessary */
        if(u >= file->nmembs || !file->memb[u]) {
            file->nmembs = MAX(file->nmembs, u+1);
            HDsnprintf(memb_name, H5FD_FAM_MEMB_NAME_BUF_SIZE, file->name, u);
            H5E_BEGIN_TRY {
                H5_CHECK_OVERFLOW(file->memb_size, hsize_t, haddr_t);
                file->memb[u] = H5FDopen(memb_name, file->flags | H5F_ACC_CREAT,
                             file->memb_fapl_id, (haddr_t)file->memb_size);
            } H5E_END_TRY;
            if(NULL == file->memb[u])
                HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to open member file")
        } /* end if */

        /* Set the EOA marker for the member */
        /* (Note compensating for base address addition in internal routine) */
        H5_CHECK_OVERFLOW(file->memb_size, hsize_t, haddr_t);
        if(addr > (haddr_t)file->memb_size) {
            if(H5FD_set_eoa(file->memb[u], type, ((haddr_t)file->memb_size - file->pub.base_addr)) < 0)
                HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to set file eoa")
            addr -= file->memb_size;
        } /* end if */
        else {
            if(H5FD_set_eoa(file->memb[u], type, (addr - file->pub.base_addr)) < 0)
                HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to set file eoa")
            addr = 0;
        } /* end else */
    } /* end for */

    file->eoa = abs_eoa;

done:
    /* Release resources */
    if(memb_name)
        H5MM_xfree(memb_name);

    FUNC_LEAVE_NOAPI(ret_value)
}


/*-------------------------------------------------------------------------
 * Function:	H5FD_family_get_eof
 *
 * Purpose:	Returns the end-of-file marker, which is the greater of
 *		either the total family size or the current EOA marker.
 *
 * Return:	Success:	End of file address, the first address past
 *				the end of the family of files or the current
 *				EOA, whichever is larger.
 *
 *		Failure:      	HADDR_UNDEF
 *
 * Programmer:	Robb Matzke
 *              Wednesday, August  4, 1999
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
static haddr_t
H5FD_family_get_eof(const H5FD_t *_file, H5FD_mem_t type)
{
    const H5FD_family_t	*file = (const H5FD_family_t*)_file;
    haddr_t		eof=0;
    int			i;      /* Local index variable */
    haddr_t ret_value = HADDR_UNDEF;   /* Return value */

    FUNC_ENTER_NOAPI_NOINIT_NOERR

    /*
     * Find the last member that has a non-zero EOF and break out of the loop
     * with `i' equal to that member. If all members have zero EOF then exit
     * loop with i==0.
     */
    HDassert(file->nmembs > 0);
    for(i = (int)file->nmembs - 1; i >= 0; --i) {
        if((eof = H5FD_get_eof(file->memb[i], type)) != 0)
            break;
        if(0 == i)
            break;
    } /* end for */

    /* Adjust for base address for file */
    eof += file->pub.base_addr;

    /*
     * The file size is the number of members before the i'th member plus the
     * size of the i'th member.
     */
    eof += ((unsigned)i)*file->memb_size;

    /* Set return value */
    ret_value = eof;

    FUNC_LEAVE_NOAPI(ret_value)
}


/*-------------------------------------------------------------------------
 * Function:       H5FD_family_get_handle
 *
 * Purpose:        Returns the file handle of FAMILY file driver.
 *
 * Returns:        Non-negative if succeed or negative if fails.
 *
 * Programmer:     Raymond Lu
 *                 Sept. 16, 2002
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
static herr_t
H5FD_family_get_handle(H5FD_t *_file, hid_t fapl, void** file_handle)
{
    H5FD_family_t       *file = (H5FD_family_t *)_file;
    H5P_genplist_t      *plist;
    hsize_t             offset;
    int                 memb;
    herr_t              ret_value = FAIL;       /* Return value */

    FUNC_ENTER_NOAPI_NOINIT

    /* Get the plist structure and family offset */
    if(NULL == (plist = H5P_object_verify(fapl, H5P_FILE_ACCESS)))
        HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
    if(H5P_get(plist, H5F_ACS_FAMILY_OFFSET_NAME, &offset) < 0)
        HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get offset for family driver")

    if(offset > (file->memb_size * file->nmembs))
        HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "offset is bigger than file size")
    memb = (int)(offset/file->memb_size);

    ret_value = H5FD_get_vfd_handle(file->memb[memb], fapl, file_handle);

done:
    FUNC_LEAVE_NOAPI(ret_value)
}


/*-------------------------------------------------------------------------
 * Function:	H5FD_family_read
 *
 * Purpose:	Reads SIZE bytes of data from FILE beginning at address ADDR
 *		into buffer BUF according to data transfer properties in
 *		DXPL_ID.
 *
 * Return:	Success:	Zero. Result is stored in caller-supplied
 *				buffer BUF.
 *
 *		Failure:	-1, contents of buffer BUF are undefined.
 *
 * Programmer:	Robb Matzke
 *              Wednesday, August  4, 1999
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
static herr_t
H5FD_family_read(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size,
		 void *_buf/*out*/)
{
    H5FD_family_t	*file = (H5FD_family_t*)_file;
    unsigned char	*buf = (unsigned char*)_buf;
    haddr_t		sub;
    size_t		req;
    hsize_t             tempreq;
    unsigned		u;              /* Local index variable */
    H5P_genplist_t      *plist;      /* Property list pointer */
    herr_t              ret_value=SUCCEED;       /* Return value */

    FUNC_ENTER_NOAPI_NOINIT

    /*
     * Get the member data transfer property list. If the transfer property
     * list does not belong to this driver then assume defaults
     */
    if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id)))
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list")

    /* Read from each member */
    while(size > 0) {
        H5_CHECKED_ASSIGN(u, unsigned, addr / file->memb_size, hsize_t);

        sub = addr % file->memb_size;

	/* This check is for mainly for IA32 architecture whose size_t's size
	 * is 4 bytes, to prevent overflow when user application is trying to
	 * write files bigger than 4GB. */
        tempreq = file->memb_size-sub;
  	if(tempreq > SIZET_MAX)
	    tempreq = SIZET_MAX;
        req = MIN(size, (size_t)tempreq);

        HDassert(u<file->nmembs);

        if (H5FDread(file->memb[u], type, dxpl_id, sub, req, buf)<0)
            HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "member file read failed")

        addr += req;
        buf += req;
        size -= req;
    }

done:
    FUNC_LEAVE_NOAPI(ret_value)
}


/*-------------------------------------------------------------------------
 * Function:	H5FD_family_write
 *
 * Purpose:	Writes SIZE bytes of data to FILE beginning at address ADDR
 *		from buffer BUF according to data transfer properties in
 *		DXPL_ID.
 *
 * Return:	Success:	Zero
 *
 *		Failure:	-1
 *
 * Programmer:	Robb Matzke
 *              Wednesday, August  4, 1999
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
static herr_t
H5FD_family_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size,
		  const void *_buf)
{
    H5FD_family_t	*file = (H5FD_family_t*)_file;
    const unsigned char	*buf = (const unsigned char*)_buf;
    haddr_t		sub;
    size_t		req;
    hsize_t             tempreq;
    unsigned		u;      /* Local index variable */
    H5P_genplist_t *plist;      /* Property list pointer */
    herr_t      ret_value = SUCCEED;       /* Return value */

    FUNC_ENTER_NOAPI_NOINIT

    /*
     * Get the member data transfer property list. If the transfer property
     * list does not belong to this driver then assume defaults.
     */
    if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id)))
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list")

    /* Write to each member */
    while (size>0) {
        H5_CHECKED_ASSIGN(u, unsigned, addr / file->memb_size, hsize_t);

        sub = addr % file->memb_size;

        /* This check is for mainly for IA32 architecture whose size_t's size
         * is 4 bytes, to prevent overflow when user application is trying to
         * write files bigger than 4GB. */
        tempreq = file->memb_size-sub;
	if(tempreq > SIZET_MAX)
	    tempreq = SIZET_MAX;
        req = MIN(size, (size_t)tempreq);

        HDassert(u<file->nmembs);

        if (H5FDwrite(file->memb[u], type, dxpl_id, sub, req, buf)<0)
            HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "member file write failed")

        addr += req;
        buf += req;
        size -= req;
    }

done:
    FUNC_LEAVE_NOAPI(ret_value)
}


/*-------------------------------------------------------------------------
 * Function:	H5FD_family_flush
 *
 * Purpose:	Flushes all family members.
 *
 * Return:	Success:	0
 *		Failure:	-1, as many files flushed as possible.
 *
 * Programmer:	Robb Matzke
 *              Wednesday, August  4, 1999
 *
 *-------------------------------------------------------------------------
 */
static herr_t
H5FD_family_flush(H5FD_t *_file, hid_t dxpl_id, hbool_t closing)
{
    H5FD_family_t	*file = (H5FD_family_t*)_file;
    unsigned		u, nerrors = 0;
    herr_t      ret_value = SUCCEED;       /* Return value */

    FUNC_ENTER_NOAPI_NOINIT

    for(u = 0; u < file->nmembs; u++)
        if(file->memb[u] && H5FD_flush(file->memb[u], dxpl_id, closing) < 0)
            nerrors++;

    if(nerrors)
        HGOTO_ERROR(H5E_IO, H5E_BADVALUE, FAIL, "unable to flush member files")

done:
    FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FD_family_flush() */


/*-------------------------------------------------------------------------
 * Function:	H5FD_family_truncate
 *
 * Purpose:	Truncates all family members.
 *
 * Return:	Success:	0
 *
 *		Failure:	-1, as many files truncated as possible.
 *
 * Programmer:	Quincey Koziol
 *              Saturday, February 23, 2008
 *
 *-------------------------------------------------------------------------
 */
static herr_t
H5FD_family_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing)
{
    H5FD_family_t	*file = (H5FD_family_t*)_file;
    unsigned		u, nerrors = 0;
    herr_t      	ret_value = SUCCEED;       /* Return value */

    FUNC_ENTER_NOAPI_NOINIT

    for(u = 0; u < file->nmembs; u++)
        if(file->memb[u] && H5FD_truncate(file->memb[u], dxpl_id, closing) < 0)
            nerrors++;

    if(nerrors)