add pcg, break mersenne, change state structs.

This commit is contained in:
chris t 2020-09-20 11:18:33 -07:00
parent 80327f0b25
commit 4ce12b1472
5 changed files with 292 additions and 32 deletions

View File

@ -1,8 +1,8 @@
CC = gcc CC = gcc
CFLAGS = -g `pkg-config fuse --cflags --libs` CFLAGS = -g `pkg-config fuse --cflags --libs` -L/usr/local/lib -lpcg_random
DEPS = noisebox.h DEPS = noisebox.h
OBJ = fuse.o zeroes.o mersenne.o OBJ = fuse.o zeroes.o mersenne.o pcg.o
%.o: %.c $(DEPS) %.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS) $(CC) -c -o $@ $< $(CFLAGS)

149
fuse.c
View File

@ -1,5 +1,5 @@
#define FUSE_USE_VERSION 30 #define FUSE_USE_VERSION 30
#define NOISER_COUNT 2 #define NOISER_COUNT 3
#include <errno.h> #include <errno.h>
#include <fuse.h> #include <fuse.h>
@ -12,22 +12,30 @@
#include "noisebox.h" #include "noisebox.h"
static void* do_init(struct fuse_conn_info *conn) { static void* do_init(struct fuse_conn_info *conn) {
struct nb_context *c = malloc(sizeof(struct nb_context));
Noiser** noisers = malloc(sizeof(Noiser*) * NOISER_COUNT); Noiser** noisers = malloc(sizeof(Noiser*) * NOISER_COUNT);
noisers[0] = zero_init(); noisers[0] = zero_init();
noisers[1] = mersenne_init(); noisers[1] = mersenne_init();
noisers[2] = pcg_init();
c->noisers = noisers;
c->state_head = NULL;
return noisers; return c;
} }
static int getattr_root(struct stat *st) { static int getattr_root(struct stat *st) {
st->st_mode = S_IFDIR | 0755; st->st_mode = S_IFDIR | 0755;
st->st_nlink = 2 + NOISER_COUNT; st->st_nlink = 2 + NOISER_COUNT;
printf("got attr?\n");
return 0; return 0;
} }
static int lookup_path(const char *path, Noiser **n, NoiseFile **nf) { static int lookup_path(const char *path, Noiser **n, NoiseFile **nf) {
struct fuse_context* c = fuse_get_context(); struct fuse_context* c = fuse_get_context();
Noiser** noisers = c->private_data; struct nb_context *nbc = c->private_data;
Noiser** noisers = nbc->noisers;
char* buf = strdup(path); char* buf = strdup(path);
char *mod = strtok(buf, "/"); char *mod = strtok(buf, "/");
@ -61,7 +69,6 @@ static int lookup_path(const char *path, Noiser **n, NoiseFile **nf) {
} }
} }
static int getattr_leaf(const char *path, struct stat *st) { static int getattr_leaf(const char *path, struct stat *st) {
Noiser *n = NULL; Noiser *n = NULL;
NoiseFile *nf = NULL; NoiseFile *nf = NULL;
@ -107,14 +114,76 @@ static int do_getattr(const char *path, struct stat *st) {
if(strcmp(path, "/") == 0) { if(strcmp(path, "/") == 0) {
ret = getattr_root(st); ret = getattr_root(st);
printf("got attr: root %i\n", ret);
} else { } else {
ret = getattr_leaf(path, st); ret = getattr_leaf(path, st);
}; };
return ret; return ret;
} }
static void get_file_state(const char* path, struct fuse_file_info *fi) {
struct fuse_context *c = fuse_get_context();
struct nb_context *nbc = c->private_data;
struct file_state *fs = nbc->state_head;
if(!fs) {
printf("no state, it's fine.\n");
fi->fh = (uint64_t)NULL;
return;
}
while(fs->next) {
if(path == fs->name) {
fi->fh = (uint64_t)fs;
return;
}
fs = fs->next;
}
fi->fh = (uint64_t)NULL;
return;
}
static void append_file_state(struct file_state *add) {
struct fuse_context *c = fuse_get_context();
struct nb_context *nbc = c->private_data;
struct file_state *fs = nbc->state_head;
if(!fs) {
nbc->state_head = add;
return;
}
while(fs->next) {
fs = fs->next;
}
fs->next = add;
return;
}
// deletes from list, but does not free.
static void delete_file_state(struct file_state *del) {
struct fuse_context *c = fuse_get_context();
struct nb_context *nbc = c->private_data;
struct file_state *fs = nbc->state_head;
if(fs == del) {
printf("head = del\n");
if(del->next) {
fs = del->next;
} else {
fs = NULL;
}
return;
}
while(fs->next) {
if(del == fs->next) {
if(del->next) {
fs->next = del->next;
} else {
fs->next = NULL;
}
return;
}
fs = fs->next;
}
}
static int do_open(const char* path, struct fuse_file_info* fi) { static int do_open(const char* path, struct fuse_file_info* fi) {
Noiser *n = NULL; Noiser *n = NULL;
NoiseFile *nf = NULL; NoiseFile *nf = NULL;
@ -122,10 +191,43 @@ static int do_open(const char* path, struct fuse_file_info* fi) {
ret = lookup_path(path, &n, &nf); ret = lookup_path(path, &n, &nf);
if(ret !=0) { if(ret !=0) {
printf("lookup_path() error");
return ret; return ret;
} }
ret = n->do_open(path, fi); // check if file is already opened.
get_file_state(path, fi);
if(fi->fh) {
return 0;
}
if(n->do_open) {
ret = n->do_open(path, fi);
append_file_state((struct file_state *)fi->fh);
}
return ret;
}
static int do_release(const char *path, struct fuse_file_info *fi) {
Noiser *n = NULL;
NoiseFile *nf = NULL;
int ret;
ret = lookup_path(path, &n, &nf);
if(ret !=0) {
printf("lookup_path() error");
return ret;
}
if(fi->fh) {
printf("clearing from statelist\n");
delete_file_state((struct file_state *)fi->fh);
}
if(n->do_release) {
printf("noiser-specific cleanup\n");
ret = n->do_release(path, fi);
}
return ret; return ret;
} }
@ -145,9 +247,11 @@ static int do_read(const char* path, char* buf, size_t sz, off_t offset,
static int readdir_root(void *buffer, fuse_fill_dir_t filler) { static int readdir_root(void *buffer, fuse_fill_dir_t filler) {
struct fuse_context* c = fuse_get_context(); struct fuse_context* c = fuse_get_context();
Noiser** noiser = c->private_data; struct nb_context *nbc = c->private_data;
Noiser** noiser = nbc->noisers;
int ret = 0; int ret = 0;
for(int i=0; i<NOISER_COUNT; i++) { for(int i=0; i<NOISER_COUNT; i++) {
printf("filling noiser %i\n", i);
ret = filler(buffer, noiser[i]->name, NULL, 0); ret = filler(buffer, noiser[i]->name, NULL, 0);
if(ret != 0) { if(ret != 0) {
printf("failed to fill %s, dying\n", noiser[i]->name); printf("failed to fill %s, dying\n", noiser[i]->name);
@ -178,25 +282,23 @@ static int do_readdir(const char *path, void *buffer,
int ret; int ret;
if(strcmp(path, "/") == 0) { printf("doing readdir\n");
ret = readdir_root(buffer, filler);
} else {
// find noiser, generate appropriate files
struct fuse_context* c = fuse_get_context();
Noiser** noiser = c->private_data;
char * pathbuf = strdup(path); if(strcmp(path, "/") == 0) {
char * toplevel = strtok(pathbuf, "/"); printf("calling readdir_root\n");
for(int i=0; i<NOISER_COUNT; i++) { return readdir_root(buffer, filler);
if(strcmp(noiser[i]->name, toplevel) == 0) {
printf("found noiser: %s\n", noiser[i]->name);
ret = do_noiser_readdir(noiser[i], path, buffer, filler,
offset, fi);
}
}
} }
return ret; // find noiser, generate appropriate files
Noiser *n = NULL;
NoiseFile *nf = NULL;
ret = lookup_path(path, &n, &nf);
if(ret !=0) {
printf("lookup_path() error");
return ret;
}
return do_noiser_readdir(n, path, buffer, filler, offset, fi);
} }
static struct fuse_operations ops = { static struct fuse_operations ops = {
@ -225,6 +327,7 @@ static struct fuse_operations ops = {
// int (*statfs) (const char *, struct statvfs *); // int (*statfs) (const char *, struct statvfs *);
// int (*flush) (const char *, struct fuse_file_info *); // int (*flush) (const char *, struct fuse_file_info *);
// int (*release) (const char *, struct fuse_file_info *); // int (*release) (const char *, struct fuse_file_info *);
.release = do_release,
// int (*fsync) (const char *, int, struct fuse_file_info *); // int (*fsync) (const char *, int, struct fuse_file_info *);
// int (*setxattr) (const char *, const char *, const char *, size_t, int); // int (*setxattr) (const char *, const char *, const char *, size_t, int);
// int (*getxattr) (const char *, const char *, char *, size_t); // int (*getxattr) (const char *, const char *, char *, size_t);

View File

@ -94,8 +94,9 @@ static uint32_t extract_u32(struct mt_state *state) {
static int do_open(const char *path, struct fuse_file_info *fi) { static int do_open(const char *path, struct fuse_file_info *fi) {
struct mt_state *state = malloc(sizeof(struct mt_state)); struct file_state *state = malloc(sizeof(struct file_state));
mt_init(state, 0); mt_random_t rng;
mt_init(&rng, 0);
fi->fh = (uint64_t)state; fi->fh = (uint64_t)state;
return 0; return 0;
@ -108,17 +109,23 @@ static int do_getattr(const char *path, struct stat *st) {
static int get_noise(size_t n, off_t offset, char* buf, static int get_noise(size_t n, off_t offset, char* buf,
struct fuse_file_info *fi) { struct fuse_file_info *fi) {
printf("getting random bits: %i@%i (%i)\n", n, offset, n*sizeof(char)); printf("getting random bits: %i@%i (%i)\n", n, offset, n*sizeof(char));
// FIXME this is wrong.
struct mt_state *state = (struct mt_state *)(fi->fh);
float buf_ratio = (float)sizeof(char)/(float)sizeof(uint32_t);
if(offset != state->consumed * buf_ratio) {
printf("wrong offset, discarding state\n");
}
// TODO got distracted, never actually did this.
uint32_t *tmp = malloc(n * sizeof(char)); uint32_t *tmp = malloc(n * sizeof(char));
printf("allocated %i\n", sizeof(char) * n); printf("allocated %i\n", sizeof(char) * n);
struct mt_state *state = (struct mt_state *)(fi->fh);
float buf_ratio = (float)sizeof(char)/(float)sizeof(uint32_t);
int count = n * buf_ratio; int count = n * buf_ratio;
printf("calling extract_u32 %i times (%i * %f)\n", count, n, buf_ratio); printf("calling extract_u32 %i times (%i * %f)\n", count, n, buf_ratio);
for(int i=0; i<count; i++) { for(int i=0; i<count; i++) {
tmp[i] = extract_u32(state); tmp[i] = extract_u32(state);
} }
// consumed is always in uint32_t. // consumed is always in uint32_t.
printf("advancing consumed: %i + %i\n", state->consumed, count); printf("advancing consumed: %i + %i\n", state->consumed, count);
state->consumed += count; state->consumed += count;
@ -169,6 +176,5 @@ Noiser* mersenne_init(void) {
n->files[7]->name = "200GB"; n->files[7]->name = "200GB";
n->files[7]->size = 200000000000; n->files[7]->size = 200000000000;
return n; return n;
} }

View File

@ -5,6 +5,8 @@
#include <fuse.h> #include <fuse.h>
#include <stddef.h> #include <stddef.h>
#include <pcg_variants.h>
#ifndef NOISEBOX_H #ifndef NOISEBOX_H
#define NOISEBOX_H #define NOISEBOX_H
@ -25,9 +27,31 @@ typedef struct {
// int (*do_readdir)(const char *path, void *buffer, fuse_fill_dir_t filler, // int (*do_readdir)(const char *path, void *buffer, fuse_fill_dir_t filler,
// off_t offset, struct fuse_file_info *fi); // off_t offset, struct fuse_file_info *fi);
int (*do_open)(const char *, struct fuse_file_info *); int (*do_open)(const char *, struct fuse_file_info *);
int (*do_release)(const char *, struct fuse_file_info *);
} Noiser; } Noiser;
typedef union {
pcg32_random_t *pcg;
} rng_state_t;
// linked list of open file states
struct file_state {
char *name;
rng_state_t rng;
size_t consumed;
struct file_state *next;
// assume prng output is some integral number of chars.
int char_ratio;
};
struct nb_context {
Noiser **noisers;
struct file_state *state_head;
};
Noiser* zero_init(void); Noiser* zero_init(void);
Noiser* mersenne_init(void); Noiser* mersenne_init(void);
Noiser* pcg_init(void);
#endif #endif

127
pcg.c Normal file
View File

@ -0,0 +1,127 @@
/*
* pcg.c -- component to provide random numbers from pcg on demand.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pcg_variants.h>
#include "noisebox.h"
// static int do_readdir(const char *path, void *buffer,
// fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) {
// filler(buffer, ".", NULL, 0);
// filler(buffer, "..", NULL, 0);
// }
static int do_getattr(const char *path, struct stat *st) {
return 0;
}
static int get_state(const char *path, struct fuse_file_info *fi) {
return 0;
}
static int do_open(const char *path, struct fuse_file_info *fi) {
// only called if state isn't already inited.
struct file_state *state = malloc(sizeof(struct file_state));
pcg32_random_t p;
// fixed constant seed
pcg32_srandom_r(&p, 42u, 54u);
state->rng.pcg = &p;
state->next = NULL;
state->char_ratio = 4;
fi->fh = (uint64_t)state;
return 0;
}
static int do_release(const char *path, struct fuse_file_info *fi) {
free((void *)fi->fh);
return 0;
}
static int get_noise(size_t n, off_t offset, char* buf,
struct fuse_file_info *fi) {
printf("getting pcg rand: %i:%i\n", n, offset);
printf("sizeof buf = %zu (%zu * %i)\n", n * sizeof(char), n, sizeof(char));
struct file_state *fh = (struct file_state *)(fi->fh);
pcg32_random_t *rng = fh->rng.pcg;
// if offset doesn't match, seek.
if(fh->consumed != offset) {
pcg32_advance_r(rng, offset - fh->consumed);
fh->consumed = offset;
}
uint32_t *tmp = malloc(n);
for(int i=0; (i*fh->char_ratio)<n; i++) {
tmp[i] = pcg32_random_r(rng);
// printf("got some noise, %i of %i\n", i, n);
}
fh->consumed += n;
memcpy(buf, tmp, n);
free(tmp);
printf("pcg random numbers obtained\n");
return n;
}
Noiser* pcg_init(void) {
Noiser* n = malloc(sizeof(Noiser));
n->name = "pcg";
n->state = NULL;
n->get_noise = get_noise;
n->do_open = do_open;
n->do_release = do_release;
// manually keep track of file count for now.
n->noisefile_count = 10;
n->files = malloc(sizeof(NoiseFile *) * n->noisefile_count);
n->files[0] = malloc(sizeof(NoiseFile));
n->files[0]->name = "1M";
n->files[0]->size = 1ULL<<20;
n->files[1] = malloc(sizeof(NoiseFile));
n->files[1]->name = "1G";
n->files[1]->size = 1ULL<<30;
n->files[2] = malloc(sizeof(NoiseFile));
n->files[2]->name = "100G";
n->files[2]->size = 100 * (1ULL<<30);
n->files[3] = malloc(sizeof(NoiseFile));
n->files[3]->name = "200GiB";
n->files[3]->size = 200 * (1ULL<<30);
n->files[4] = malloc(sizeof(NoiseFile));
n->files[4]->name = "400GiB";
n->files[4]->size = 400 * (1ULL<<30);
n->files[5] = malloc(sizeof(NoiseFile));
n->files[5]->name = "1GB";
n->files[5]->size = 1000000000;
n->files[6] = malloc(sizeof(NoiseFile));
n->files[6]->name = "100GB";
n->files[6]->size = 100000000000;
n->files[7] = malloc(sizeof(NoiseFile));
n->files[7]->name = "200GB";
n->files[7]->size = 200000000000;
n->files[8] = malloc(sizeof(NoiseFile));
n->files[8]->name = "400GB";
n->files[8]->size = 400000000000;
n->files[9] = malloc(sizeof(NoiseFile));
n->files[9]->name = "800GB";
n->files[9]->size = 800000000000;
return n;
}