#include <stdio.h>
#include <stdlib.h>
#include "nfs_iio.h"
#include "nfs_nt.h"
static int node_get(nfs_nt_NT* nt, int node, nfs_nt_Node* node_info) {
nfs_iio_seek(nt->file, nt->channel, node * sizeof(nfs_nt_Node));
return nfs_iio_read(nt->file, nt->channel, node_info, sizeof(nfs_nt_Node));
}
static int node_set(nfs_nt_NT* nt, int node, nfs_nt_Node* node_info) {
nfs_iio_seek(nt->file, nt->channel, node * sizeof(nfs_nt_Node));
return nfs_iio_write(nt->file, nt->channel, node_info, sizeof(nfs_nt_Node));
}
static int node_recover(nfs_nt_NT* nt, int node) {
nfs_nt_Node ni;
#ifdef PURIFY
memset(&ni, 0, sizeof(ni));
#endif
ni.refcount = 0;
ni.size = 0;
ni.chain = 0;
node_set(nt, node, &ni);
if (node < nt->unallocated)
nt->unallocated = node;
return 0;
}
static int find_first_free(nfs_nt_NT* nt, int start) {
nfs_nt_Node ni;
int node = start;
node_get(nt, node, &ni);
while (ni.refcount > 0)
node_get(nt, ++node, &ni);
return node;
}
nfs_nt_NT* nfs_nt_create(nfs_iio_File* file, int blocks_per_channel) {
nfs_nt_NT* nt;
int chn;
if (file == NULL)
return NULL;
if (blocks_per_channel == 0)
blocks_per_channel = nfs_nt_DEF_CHANNEL_SIZE;
chn = nfs_iio_allocate_channel(file, blocks_per_channel);
nt = (nfs_nt_NT*)malloc(sizeof(nfs_nt_NT));
nt->file = file;
nt->channel = chn;
nt->unallocated = 0;
return nt;
}
nfs_nt_NT* nfs_nt_open(nfs_iio_File* file, int channel) {
nfs_nt_NT* nt;
nt = (nfs_nt_NT*)malloc(sizeof(nfs_nt_NT));
nt->file = file;
nt->channel = channel;
nt->unallocated = find_first_free(nt, 0);
return nt;
}
void nfs_nt_close(nfs_nt_NT* nt) {
if (nt != NULL)
free(nt);
}
void nfs_nt_destroy(nfs_nt_NT* nt) {
nfs_nt_close(nt);
}
int nfs_nt_get_node(nfs_nt_NT* nt, int node, nfs_nt_Node* node_ptr) {
if (nt == NULL)
return -1;
return node_get(nt, node, node_ptr);
}
int nfs_nt_allocate_node(nfs_nt_NT* nt) {
int node;
nfs_nt_Node ni;
if (nt == NULL)
return -1;
node = nt->unallocated;
nfs_nt_get_node(nt, node, &ni);
ni.refcount = 1;
ni.size = 0;
ni.chain = 0;
nfs_nt_set_node(nt, node, &ni);
nt->unallocated = find_first_free(nt, nt->unallocated);
return node;
}
int nfs_nt_refcount_decr(nfs_nt_NT* nt, int node) {
nfs_nt_Node ni;
int must_delete = 0;
nfs_nt_get_node(nt, node, &ni);
ni.refcount--;
if (ni.refcount <= 0)
must_delete = 1;
nfs_nt_set_node(nt, node, &ni);
if (must_delete)
node_recover(nt, node);
return must_delete;
}
void nfs_nt_refcount_incr(nfs_nt_NT* nt, int node) {
nfs_nt_Node ni;
nfs_nt_get_node(nt, node, &ni);
ni.refcount++;
nfs_nt_set_node(nt, node, &ni);
}
int nfs_nt_set_node(nfs_nt_NT* nt, int node, nfs_nt_Node* node_info) {
return node_set(nt, node, node_info);
}
int nfs_nt_node_get_size(nfs_nt_NT* nt, int node) {
nfs_nt_Node ni;
nfs_nt_get_node(nt, node, &ni);
return ni.size;
}
void nfs_nt_node_set_size(nfs_nt_NT* nt, int node, int size) {
nfs_nt_Node ni;
nfs_nt_get_node(nt, node, &ni);
ni.size = size;
nfs_nt_set_node(nt, node, &ni);
}
int nfs_nt_node_get_chain(nfs_nt_NT* nt, int node) {
nfs_nt_Node ni;
nfs_nt_get_node(nt, node, &ni);
return ni.chain;
}
void nfs_nt_node_set_chain(nfs_nt_NT* nt, int node, int chain) {
nfs_nt_Node ni;
nfs_nt_get_node(nt, node, &ni);
ni.chain = chain;
nfs_nt_set_node(nt, node, &ni);
}