summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libstore/stripe.c187
1 files changed, 136 insertions, 51 deletions
diff --git a/libstore/stripe.c b/libstore/stripe.c
index 6058e9d8..485bfd6f 100644
--- a/libstore/stripe.c
+++ b/libstore/stripe.c
@@ -20,74 +20,159 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+#include <stdlib.h>
+
#include "store.h"
-
-static error_t
-ileave_read (struct store *store,
- off_t addr, size_t index, mach_msg_type_number_t amount,
- char **buf, mach_msg_type_number_t *len)
-{
- return io_read (store->port, buf, len, addr * store->block_size, amount);
-}
-static error_t
-file_write (struct store *store,
- off_t addr, size_t index, char *buf, mach_msg_type_number_t len,
- mach_msg_type_number_t *amount)
+struct stripe_info
{
- return io_write (store->port, buf, len, addr * store->block_size, amount);
-}
-
-static struct store_meths
-file_meths = {file_read, file_write};
-
+ struct store **stripes;
+ int dealloc : 1;
+};
+
static error_t
-file_byte_read (struct store *store, off_t addr, mach_msg_type_number_t amount,
- char **buf, mach_msg_type_number_t *len)
+stripe_read (struct store *store,
+ off_t addr, size_t index, mach_msg_type_number_t amount,
+ char **buf, mach_msg_type_number_t *len)
{
- return io_read (store->port, buf, len, addr, amount);
+ struct stripe_info *info = store->hook;
+ return store_read (info->stripes[index], addr, amount, buf, len);
}
static error_t
-file_byte_write (struct store *store,
- off_t addr, char *buf, mach_msg_type_number_t len,
- mach_msg_type_number_t *amount)
+stripe_write (struct store *store,
+ off_t addr, size_t index, char *buf, mach_msg_type_number_t len,
+ mach_msg_type_number_t *amount)
{
- return io_write (store->port, buf, len, addr, amount);
+ struct store **stripes = store->hook;
+ return store_write (stripes[index], addr, buf, len, amount);
}
static struct store_meths
-file_byte_meths = {file_byte_read, file_byte_write};
+stripe_meths = {stripe_read, stripe_write};
-/* Return a new store in STORE referring to the mach file FILE. Consumes
- the send right FILE. */
+/* Return a new store in STORE that interleaves all the stores in STRIPES
+ (NUM_STRIPES of them) every INTERLEAVE blocks (every store in STRIPES must
+ have the same block size). If DEALLOC is true, then the striped stores
+ are freed when this store is (in any case, the array STRIPES is copied,
+ and so should be freed by the caller). */
error_t
-store_file_create (file_t file, struct store **store)
+store_ileave_create (struct store **stripes, size_t num_stripes, int dealloc,
+ off_t interleave, struct store **store)
{
- off_t runs[2];
- struct stat stat;
- error_t err = io_stat (file, &stat);
-
- if (err)
- return err;
-
- runs[0] = 0;
- runs[1] = stat.st_size;
-
- return _store_file_create (file, 1, runs, 2, store);
+ size_t i;
+ error_t err = EINVAL; /* default error */
+ off_t block_size = 0, min_end = 0;
+ off_t runs[num_stripes * 2];
+ struct stripe_info *info = malloc (sizeof (struct stripe_info));
+
+ if (info == 0)
+ return ENOMEM;
+
+ info->stripes = malloc (sizeof (struct store *) * num_stripes);
+ info->dealloc = dealloc;
+
+ if (info->stripes == 0)
+ {
+ free (info);
+ return ENOMEM;
+ }
+
+ if (interleave == 0)
+ goto barf;
+
+ for (i = 0; i < num_stripes; i++)
+ {
+ runs[i * 2] = 0;
+ runs[i * 2 + 1] = interleave;
+ if (block_size == 0)
+ {
+ block_size = stripes[i]->block_size;
+ min_end = stripes[i]->end;
+ }
+ else
+ {
+ if (block_size != stripes[i]->block_size)
+ /* Mismatched block sizes; barf. */
+ goto barf;
+ if (min_end > stripes[i]->end)
+ /* Only use as much space as the smallest stripe has. */
+ min_end = stripes[i]->end;
+ }
+ }
+
+ *store = _make_store (0, &stripe_meths, MACH_PORT_NULL, block_size,
+ runs, num_stripes * 2, min_end);
+ if (! *store)
+ {
+ err = ENOMEM;
+ goto barf;
+ }
+
+ (*store)->hook = info;
+ bcopy (stripes, info->stripes, num_stripes * sizeof *stripes);
+
+ return 0;
+
+ barf:
+ free (info->stripes);
+ free (info);
+ return err;
}
-/* Like store_file_create, but doesn't query the file for information. */
+/* Return a new store in STORE that concatenates all the stores in STORES
+ (NUM_STORES of them) every store in STRIPES must have the same block size.
+ If DEALLOC is true, then the sub-stores are freed when this store is (in
+ any case, the array STORES is copied, and so should be freed by the
+ caller). */
error_t
-_store_file_create (file_t file, size_t block_size,
- off_t *runs, unsigned runs_len,
- struct store **store)
+store_concat_create (struct store **stores, size_t num_stores, int dealloc,
+ struct store **store)
{
- if (block_size == 1)
- *store = _make_store (STORAGE_HURD_FILE, &file_byte_meths, file, 1,
- runs, runs_len);
- else
- *store = _make_store (STORAGE_HURD_FILE, &file_meths, file, block_size,
- runs, runs_len);
- return *store ? 0 : ENOMEM;
+ size_t i;
+ error_t err = EINVAL; /* default error */
+ off_t block_size = 0;
+ off_t runs[num_stores * 2];
+ struct stripe_info *info = malloc (sizeof (struct stripe_info));
+
+ if (info == 0)
+ return ENOMEM;
+
+ info->stripes = malloc (sizeof (struct store *) * num_stores);
+ info->dealloc = dealloc;
+
+ if (info->stripes == 0)
+ {
+ free (info);
+ return ENOMEM;
+ }
+
+ for (i = 0; i < num_stores; i++)
+ {
+ runs[i * 2] = 0;
+ runs[i * 2 + 1] = stores[i]->end;
+ if (block_size == 0)
+ block_size = stores[i]->block_size;
+ else if (block_size != stores[i]->block_size)
+ /* Mismatched block sizes; barf. */
+ goto barf;
+ }
+
+ *store = _make_store (0, &stripe_meths, MACH_PORT_NULL, block_size,
+ runs, num_stores * 2, 0);
+ if (! *store)
+ {
+ err = ENOMEM;
+ goto barf;
+ }
+
+ (*store)->hook = info;
+ bcopy (stores, info->stripes, num_stores * sizeof *stores);
+
+ return 0;
+
+ barf:
+ free (info->stripes);
+ free (info);
+ return err;
}