mirror of
https://github.com/netsurf-browser/netsurf
synced 2024-11-28 09:13:08 +03:00
implement block read and write operations.
This commit is contained in:
parent
4cc4a47237
commit
83fa13b315
@ -116,6 +116,14 @@ typedef uint16_t entry_index_t;
|
|||||||
*/
|
*/
|
||||||
typedef uint32_t entry_ident_t;
|
typedef uint32_t entry_ident_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type used to store block file index values. If this is changed
|
||||||
|
* it will affect the entry storage/alignment and BLOCK_ADDR_LEN must
|
||||||
|
* also be updated.
|
||||||
|
*/
|
||||||
|
typedef uint16_t block_index_t;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entry element index values.
|
* Entry element index values.
|
||||||
*/
|
*/
|
||||||
@ -162,7 +170,7 @@ enum store_entry_flags {
|
|||||||
struct store_entry_element {
|
struct store_entry_element {
|
||||||
uint8_t* data; /**< data allocated */
|
uint8_t* data; /**< data allocated */
|
||||||
uint32_t size; /**< size of entry element on disc */
|
uint32_t size; /**< size of entry element on disc */
|
||||||
uint16_t block; /**< small object data block */
|
block_index_t block; /**< small object data block */
|
||||||
uint8_t ref; /**< element data reference count */
|
uint8_t ref; /**< element data reference count */
|
||||||
uint8_t flags; /**< entry flags */
|
uint8_t flags; /**< entry flags */
|
||||||
};
|
};
|
||||||
@ -319,6 +327,7 @@ remove_store_entry(struct store_state *state, struct store_entry **bse)
|
|||||||
* - path elements no longer than 8 characters
|
* - path elements no longer than 8 characters
|
||||||
* - acceptable characters are A-Z, 0-9
|
* - acceptable characters are A-Z, 0-9
|
||||||
* - short total path lengths (255 or less)
|
* - short total path lengths (255 or less)
|
||||||
|
* - no more than 77 entries per directory (6bits worth)
|
||||||
*
|
*
|
||||||
* The short total path lengths mean the encoding must represent as
|
* The short total path lengths mean the encoding must represent as
|
||||||
* much data as possible in the least number of characters.
|
* much data as possible in the least number of characters.
|
||||||
@ -361,63 +370,75 @@ store_fname(struct store_state *state,
|
|||||||
b32u_i[4] = b32u_d[4][0] = encoding_table[(ident >> 20) & 0x1f];
|
b32u_i[4] = b32u_d[4][0] = encoding_table[(ident >> 20) & 0x1f];
|
||||||
b32u_i[5] = b32u_d[5][0] = encoding_table[(ident >> 25) & 0x1f];
|
b32u_i[5] = b32u_d[5][0] = encoding_table[(ident >> 25) & 0x1f];
|
||||||
b32u_i[6] = encoding_table[(ident >> 30) & 0x1f];
|
b32u_i[6] = encoding_table[(ident >> 30) & 0x1f];
|
||||||
|
|
||||||
/* null terminate strings */
|
/* null terminate strings */
|
||||||
b32u_i[7] = b32u_d[0][1] = b32u_d[1][1] = b32u_d[2][1] =
|
b32u_i[7] = b32u_d[0][1] = b32u_d[1][1] = b32u_d[2][1] =
|
||||||
b32u_d[3][1] = b32u_d[4][1] = b32u_d[5][1] = 0;
|
b32u_d[3][1] = b32u_d[4][1] = b32u_d[5][1] = 0;
|
||||||
|
|
||||||
if (elem_idx == ENTRY_ELEM_META) {
|
if (elem_idx == (ENTRY_ELEM_COUNT + ENTRY_ELEM_META)) {
|
||||||
dat = "m"; /* metadata */
|
netsurf_mkpath(&fname, NULL, 3, state->path, "mblk", b32u_d[0]);
|
||||||
|
|
||||||
|
} else if (elem_idx == (ENTRY_ELEM_COUNT + ENTRY_ELEM_DATA)) {
|
||||||
|
netsurf_mkpath(&fname, NULL, 3, state->path, "dblk", b32u_d[0]);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
dat = "d"; /* data */
|
/* Normal file in the backing store */
|
||||||
}
|
|
||||||
|
|
||||||
/* number of chars with usefully encoded data in base 32 */
|
if (elem_idx == ENTRY_ELEM_META) {
|
||||||
switch(((state->ident_bits + 4) / 5)) {
|
dat = "m"; /* metadata */
|
||||||
case 1:
|
} else {
|
||||||
netsurf_mkpath(&fname, NULL, 3, state->path, dat,
|
dat = "d"; /* data */
|
||||||
b32u_i);
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
/* number of chars with usefully encoded data in base 32 */
|
||||||
netsurf_mkpath(&fname, NULL, 4, state->path, dat,
|
switch(((state->ident_bits + 4) / 5)) {
|
||||||
b32u_d[0],
|
case 1:
|
||||||
b32u_i);
|
netsurf_mkpath(&fname, NULL, 3, state->path, dat,
|
||||||
break;
|
b32u_i);
|
||||||
|
break;
|
||||||
|
|
||||||
case 3:
|
case 2:
|
||||||
netsurf_mkpath(&fname, NULL, 5, state->path, dat,
|
netsurf_mkpath(&fname, NULL, 4, state->path, dat,
|
||||||
b32u_d[0], b32u_d[1],
|
b32u_d[0],
|
||||||
b32u_i);
|
b32u_i);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 3:
|
||||||
netsurf_mkpath(&fname, NULL, 6, state->path, dat,
|
netsurf_mkpath(&fname, NULL, 5, state->path, dat,
|
||||||
b32u_d[0], b32u_d[1], b32u_d[2],
|
b32u_d[0], b32u_d[1],
|
||||||
b32u_i);
|
b32u_i);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5:
|
case 4:
|
||||||
netsurf_mkpath(&fname, NULL, 7, state->path, dat,
|
netsurf_mkpath(&fname, NULL, 6, state->path, dat,
|
||||||
b32u_d[0], b32u_d[1], b32u_d[2], b32u_d[3],
|
b32u_d[0], b32u_d[1], b32u_d[2],
|
||||||
b32u_i);
|
b32u_i);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 6:
|
case 5:
|
||||||
netsurf_mkpath(&fname, NULL, 8, state->path, dat,
|
netsurf_mkpath(&fname, NULL, 7, state->path, dat,
|
||||||
b32u_d[0], b32u_d[1], b32u_d[2], b32u_d[3],
|
b32u_d[0], b32u_d[1], b32u_d[2],
|
||||||
b32u_d[4],
|
b32u_d[3],
|
||||||
b32u_i);
|
b32u_i);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 7:
|
case 6:
|
||||||
netsurf_mkpath(&fname, NULL, 9, state->path, dat,
|
netsurf_mkpath(&fname, NULL, 8, state->path, dat,
|
||||||
b32u_d[0], b32u_d[1], b32u_d[2], b32u_d[3],
|
b32u_d[0], b32u_d[1], b32u_d[2],
|
||||||
b32u_d[4], b32u_d[5],
|
b32u_d[3], b32u_d[4],
|
||||||
b32u_i);
|
b32u_i);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
case 7:
|
||||||
assert("Invalid path depth in store_fname()" == NULL);
|
netsurf_mkpath(&fname, NULL, 9, state->path, dat,
|
||||||
|
b32u_d[0], b32u_d[1], b32u_d[2],
|
||||||
|
b32u_d[3], b32u_d[4], b32u_d[5],
|
||||||
|
b32u_i);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert("Invalid path depth in store_fname()" == NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return fname;
|
return fname;
|
||||||
@ -924,14 +945,18 @@ set_store_entry(struct store_state *state,
|
|||||||
* Open a file using a store ident.
|
* Open a file using a store ident.
|
||||||
*
|
*
|
||||||
* @param state The store state to use.
|
* @param state The store state to use.
|
||||||
* @param bse The store entry of the file to open.
|
* @param ident The identifier to open file for.
|
||||||
* @param elem_idx The element within the store entry to open.
|
* @param elem_idx The element within the store entry to open. The
|
||||||
|
* value should be be one of the values in the
|
||||||
|
* store_entry_elem_idx enum. Additionally it may have
|
||||||
|
* ENTRY_ELEM_COUNT added to it to indicate block file
|
||||||
|
* names.
|
||||||
* @param openflags The flags used with the open call.
|
* @param openflags The flags used with the open call.
|
||||||
* @return An fd from the open call or -1 on error.
|
* @return An fd from the open call or -1 on error.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
store_open(struct store_state *state,
|
store_open(struct store_state *state,
|
||||||
struct store_entry *bse,
|
entry_ident_t ident,
|
||||||
int elem_idx,
|
int elem_idx,
|
||||||
int openflags)
|
int openflags)
|
||||||
{
|
{
|
||||||
@ -939,7 +964,7 @@ store_open(struct store_state *state,
|
|||||||
nserror ret;
|
nserror ret;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
fname = store_fname(state, bse->ident, elem_idx);
|
fname = store_fname(state, ident, elem_idx);
|
||||||
if (fname == NULL) {
|
if (fname == NULL) {
|
||||||
LOG(("filename error"));
|
LOG(("filename error"));
|
||||||
return -1;
|
return -1;
|
||||||
@ -1467,12 +1492,37 @@ static nserror store_write_block(struct store_state *state,
|
|||||||
struct store_entry *bse,
|
struct store_entry *bse,
|
||||||
int elem_idx)
|
int elem_idx)
|
||||||
{
|
{
|
||||||
int bf = (bse->elem[elem_idx].block >> BLOCK_ENTRY_COUNT) &
|
block_index_t bf = (bse->elem[elem_idx].block >> BLOCK_ENTRY_COUNT) &
|
||||||
((1 << BLOCK_FILE_COUNT) - 1); /* block file block resides in */
|
((1 << BLOCK_FILE_COUNT) - 1); /* block file block resides in */
|
||||||
|
block_index_t bi = bse->elem[elem_idx].block & ((1 << BLOCK_ENTRY_COUNT) -1); /* block index in file */
|
||||||
|
ssize_t wr;
|
||||||
|
off_t offst;
|
||||||
|
|
||||||
|
/* ensure the block file fd is good */
|
||||||
|
if (state->blocks[elem_idx][bf].fd == -1) {
|
||||||
|
state->blocks[elem_idx][bf].fd = store_open(state, bf,
|
||||||
|
elem_idx + ENTRY_ELEM_COUNT, O_CREAT | O_RDWR);
|
||||||
|
}
|
||||||
|
if (state->blocks[elem_idx][bf].fd == -1) {
|
||||||
|
return NSERROR_SAVE_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elem_idx == ENTRY_ELEM_META) {
|
||||||
|
offst = bi << BLOCK_META_SIZE;
|
||||||
|
} else {
|
||||||
|
offst = bi << BLOCK_DATA_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
return NSERROR_SAVE_FAILED;
|
wr = pwrite(state->blocks[elem_idx][bf].fd,
|
||||||
|
bse->elem[elem_idx].data,
|
||||||
|
bse->elem[elem_idx].size,
|
||||||
|
offst);
|
||||||
|
|
||||||
|
if (wr != bse->elem[elem_idx].size) {
|
||||||
|
return NSERROR_SAVE_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NSERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1490,7 +1540,7 @@ static nserror store_write_file(struct store_state *state,
|
|||||||
ssize_t written;
|
ssize_t written;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
fd = store_open(state, bse, elem_idx, O_CREAT | O_WRONLY);
|
fd = store_open(state, bse->ident, elem_idx, O_CREAT | O_WRONLY);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
perror("");
|
perror("");
|
||||||
LOG(("Open failed %d", fd));
|
LOG(("Open failed %d", fd));
|
||||||
@ -1591,7 +1641,36 @@ static nserror store_read_block(struct store_state *state,
|
|||||||
struct store_entry *bse,
|
struct store_entry *bse,
|
||||||
int elem_idx)
|
int elem_idx)
|
||||||
{
|
{
|
||||||
return NSERROR_NOT_FOUND;
|
block_index_t bf = (bse->elem[elem_idx].block >> BLOCK_ENTRY_COUNT) &
|
||||||
|
((1 << BLOCK_FILE_COUNT) - 1); /* block file block resides in */
|
||||||
|
block_index_t bi = bse->elem[elem_idx].block & ((1 << BLOCK_ENTRY_COUNT) -1); /* block index in file */
|
||||||
|
ssize_t rd;
|
||||||
|
off_t offst;
|
||||||
|
|
||||||
|
/* ensure the block file fd is good */
|
||||||
|
if (state->blocks[elem_idx][bf].fd == -1) {
|
||||||
|
state->blocks[elem_idx][bf].fd = store_open(state, bf, elem_idx + ENTRY_ELEM_COUNT, O_CREAT | O_RDWR);
|
||||||
|
}
|
||||||
|
if (state->blocks[elem_idx][bf].fd == -1) {
|
||||||
|
return NSERROR_SAVE_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elem_idx == ENTRY_ELEM_META) {
|
||||||
|
offst = bi << BLOCK_META_SIZE;
|
||||||
|
} else {
|
||||||
|
offst = bi << BLOCK_DATA_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
rd = pread(state->blocks[elem_idx][bf].fd,
|
||||||
|
bse->elem[elem_idx].data,
|
||||||
|
bse->elem[elem_idx].size,
|
||||||
|
offst);
|
||||||
|
|
||||||
|
if (rd != bse->elem[elem_idx].size) {
|
||||||
|
return NSERROR_SAVE_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NSERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1612,7 +1691,7 @@ static nserror store_read_file(struct store_state *state,
|
|||||||
size_t tot = 0; /* total size */
|
size_t tot = 0; /* total size */
|
||||||
|
|
||||||
/* separate file in backing store */
|
/* separate file in backing store */
|
||||||
fd = store_open(storestate, bse, elem_idx, O_RDONLY);
|
fd = store_open(storestate, bse->ident, elem_idx, O_RDONLY);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
LOG(("Open failed"));
|
LOG(("Open failed"));
|
||||||
/** @todo should this invalidate the entry? */
|
/** @todo should this invalidate the entry? */
|
||||||
|
Loading…
Reference in New Issue
Block a user