Store CPU list in a metadata.json file
This allows early access to the CPU list in order to emit the PRV header before consuming events from the streams.
This commit is contained in:
parent
763bcf7c33
commit
60862db890
10
Makefile
10
Makefile
@ -17,16 +17,16 @@ all: $(BIN)
|
|||||||
libovni.a: ovni.o
|
libovni.a: ovni.o
|
||||||
ar -crs $@ $^
|
ar -crs $@ $^
|
||||||
|
|
||||||
dump: ovni.o dump.o
|
dump: ovni.o dump.o parson.o
|
||||||
|
|
||||||
test_speed: test_speed.c ovni.o
|
test_speed: test_speed.c ovni.o parson.o
|
||||||
|
|
||||||
emu: emu.o emu_ovni.o emu_nosv.o ovni.o prv.o
|
emu: emu.o emu_ovni.o emu_nosv.o ovni.o prv.o parson.o
|
||||||
|
|
||||||
libovni.so: ovni.o
|
libovni.so: ovni.o parson.o
|
||||||
$(LINK.c) -shared $^ -o $@
|
$(LINK.c) -shared $^ -o $@
|
||||||
|
|
||||||
ovni2prv: ovni2prv.c ovni.o
|
ovni2prv: ovni2prv.c ovni.o parson.o
|
||||||
|
|
||||||
ovnisync: ovnisync.c
|
ovnisync: ovnisync.c
|
||||||
mpicc -lm $^ -o $@
|
mpicc -lm $^ -o $@
|
||||||
|
120
emu.c
120
emu.c
@ -190,6 +190,7 @@ emulate(struct ovni_emu *emu)
|
|||||||
ovni_load_next_event(stream);
|
ovni_load_next_event(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
emu->lastclock = 0;
|
emu->lastclock = 0;
|
||||||
|
|
||||||
/* Then process all events */
|
/* Then process all events */
|
||||||
@ -237,6 +238,112 @@ emu_get_thread(struct ovni_emu *emu, int tid)
|
|||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_new_cpu(struct ovni_emu *emu, struct ovni_loom *loom, int i, int phyid)
|
||||||
|
{
|
||||||
|
/* The logical id must match our index */
|
||||||
|
assert(i == loom->ncpus);
|
||||||
|
|
||||||
|
assert(loom->cpu[i].state == CPU_ST_UNKNOWN);
|
||||||
|
|
||||||
|
loom->cpu[loom->ncpus].state = CPU_ST_READY;
|
||||||
|
loom->cpu[loom->ncpus].i = i;
|
||||||
|
loom->cpu[loom->ncpus].phyid = phyid;
|
||||||
|
loom->cpu[loom->ncpus].gindex = emu->total_cpus++;
|
||||||
|
|
||||||
|
dbg("new cpu %d at phyid=%d\n", i, phyid);
|
||||||
|
|
||||||
|
loom->ncpus++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
proc_load_cpus(struct ovni_emu *emu, struct ovni_loom *loom, struct ovni_eproc *proc)
|
||||||
|
{
|
||||||
|
JSON_Array *cpuarray;
|
||||||
|
JSON_Object *cpu;
|
||||||
|
JSON_Object *meta;
|
||||||
|
int i, index, phyid;
|
||||||
|
|
||||||
|
meta = json_value_get_object(proc->meta);
|
||||||
|
|
||||||
|
assert(meta);
|
||||||
|
|
||||||
|
cpuarray = json_object_get_array(meta, "cpus");
|
||||||
|
|
||||||
|
/* This process doesn't have the cpu list */
|
||||||
|
if(cpuarray == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
assert(loom->ncpus == 0);
|
||||||
|
|
||||||
|
for(i = 0; i < json_array_get_count(cpuarray); i++)
|
||||||
|
{
|
||||||
|
cpu = json_array_get_object(cpuarray, i);
|
||||||
|
|
||||||
|
index = (int) json_object_get_number(cpu, "index");
|
||||||
|
phyid = (int) json_object_get_number(cpu, "phyid");
|
||||||
|
|
||||||
|
add_new_cpu(emu, loom, index, phyid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Obtain CPUs in the metadata files and other data */
|
||||||
|
static int
|
||||||
|
load_metadata(struct ovni_emu *emu)
|
||||||
|
{
|
||||||
|
int i, j, k, s;
|
||||||
|
struct ovni_loom *loom;
|
||||||
|
struct ovni_eproc *proc;
|
||||||
|
struct ovni_ethread *thread;
|
||||||
|
struct ovni_stream *stream;
|
||||||
|
struct ovni_trace *trace;
|
||||||
|
|
||||||
|
trace = &emu->trace;
|
||||||
|
|
||||||
|
for(i=0; i<trace->nlooms; i++)
|
||||||
|
{
|
||||||
|
loom = &trace->loom[i];
|
||||||
|
for(j=0; j<loom->nprocs; j++)
|
||||||
|
{
|
||||||
|
proc = &loom->proc[j];
|
||||||
|
|
||||||
|
proc_load_cpus(emu, loom, proc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* One of the process must have the list of CPUs */
|
||||||
|
/* FIXME: The CPU list should be at the loom dir */
|
||||||
|
assert(loom->ncpus > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
destroy_metadata(struct ovni_emu *emu)
|
||||||
|
{
|
||||||
|
int i, j, k, s;
|
||||||
|
struct ovni_loom *loom;
|
||||||
|
struct ovni_eproc *proc;
|
||||||
|
struct ovni_ethread *thread;
|
||||||
|
struct ovni_stream *stream;
|
||||||
|
struct ovni_trace *trace;
|
||||||
|
|
||||||
|
trace = &emu->trace;
|
||||||
|
|
||||||
|
for(i=0; i<trace->nlooms; i++)
|
||||||
|
{
|
||||||
|
loom = &trace->loom[i];
|
||||||
|
for(j=0; j<loom->nprocs; j++)
|
||||||
|
{
|
||||||
|
proc = &loom->proc[j];
|
||||||
|
|
||||||
|
assert(proc->meta);
|
||||||
|
json_value_free(proc->meta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -256,16 +363,23 @@ main(int argc, char *argv[])
|
|||||||
memset(&emu, 0, sizeof(emu));
|
memset(&emu, 0, sizeof(emu));
|
||||||
|
|
||||||
if(ovni_load_trace(&emu.trace, tracedir))
|
if(ovni_load_trace(&emu.trace, tracedir))
|
||||||
return 1;
|
abort();
|
||||||
|
|
||||||
if(ovni_load_streams(&emu.trace))
|
if(ovni_load_streams(&emu.trace))
|
||||||
return 1;
|
abort();
|
||||||
|
|
||||||
printf("#Paraver (19/01/38 at 03:14):00000000000000000000_ns:0:1:1(%d:1)\n", 10);
|
if(load_metadata(&emu) != 0)
|
||||||
|
abort();
|
||||||
|
|
||||||
|
|
||||||
|
printf("#Paraver (19/01/38 at 03:14):00000000000000000000_ns:0:1:1(%d:1)\n", emu.total_cpus);
|
||||||
|
|
||||||
emulate(&emu);
|
emulate(&emu);
|
||||||
|
|
||||||
|
destroy_metadata(&emu);
|
||||||
|
|
||||||
ovni_free_streams(&emu.trace);
|
ovni_free_streams(&emu.trace);
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
5
emu.h
5
emu.h
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "ovni.h"
|
#include "ovni.h"
|
||||||
#include "uthash.h"
|
#include "uthash.h"
|
||||||
|
#include "parson.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
/* Debug macros */
|
/* Debug macros */
|
||||||
@ -91,6 +92,8 @@ struct ovni_eproc {
|
|||||||
size_t nthreads;
|
size_t nthreads;
|
||||||
struct ovni_ethread thread[OVNI_MAX_THR];
|
struct ovni_ethread thread[OVNI_MAX_THR];
|
||||||
|
|
||||||
|
JSON_Value *meta;
|
||||||
|
|
||||||
/* ------ Subsystem specific data --------*/
|
/* ------ Subsystem specific data --------*/
|
||||||
/* TODO: Use dynamic allocation */
|
/* TODO: Use dynamic allocation */
|
||||||
|
|
||||||
@ -189,7 +192,7 @@ struct ovni_emu {
|
|||||||
/* Total counters */
|
/* Total counters */
|
||||||
int total_thread;
|
int total_thread;
|
||||||
int total_proc;
|
int total_proc;
|
||||||
int total_cpu;
|
int total_cpus;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Emulator function declaration */
|
/* Emulator function declaration */
|
||||||
|
70
emu_ovni.c
70
emu_ovni.c
@ -243,74 +243,6 @@ ev_affinity(struct ovni_emu *emu)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
ev_cpu_count(struct ovni_emu *emu)
|
|
||||||
{
|
|
||||||
int i, max_ncpus, max_phyid;
|
|
||||||
struct ovni_loom *loom;
|
|
||||||
|
|
||||||
loom = emu->cur_loom;
|
|
||||||
max_ncpus = emu->cur_ev->payload.i32[0];
|
|
||||||
max_phyid = emu->cur_ev->payload.i32[1];
|
|
||||||
|
|
||||||
assert(max_ncpus < OVNI_MAX_CPU);
|
|
||||||
assert(max_phyid < OVNI_MAX_CPU);
|
|
||||||
|
|
||||||
for(i=0; i<OVNI_MAX_CPU; i++)
|
|
||||||
{
|
|
||||||
loom->cpu[i].state = CPU_ST_UNKNOWN;
|
|
||||||
loom->cpu[i].i = -1;
|
|
||||||
loom->cpu[i].phyid = -1;
|
|
||||||
loom->cpu[i].gindex = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
loom->ncpus = 0;
|
|
||||||
loom->max_ncpus = max_ncpus;
|
|
||||||
loom->max_phyid = max_phyid;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
ev_cpu_id(struct ovni_emu *emu)
|
|
||||||
{
|
|
||||||
int i, phyid;
|
|
||||||
struct ovni_loom *loom;
|
|
||||||
|
|
||||||
loom = emu->cur_loom;
|
|
||||||
i = emu->cur_ev->payload.i32[0];
|
|
||||||
phyid = emu->cur_ev->payload.i32[1];
|
|
||||||
|
|
||||||
/* The logical id must match our index */
|
|
||||||
assert(i == loom->ncpus);
|
|
||||||
|
|
||||||
assert(0 <= phyid && phyid <= loom->max_phyid);
|
|
||||||
|
|
||||||
assert(loom->cpu[i].state == CPU_ST_UNKNOWN);
|
|
||||||
|
|
||||||
loom->cpu[loom->ncpus].state = CPU_ST_READY;
|
|
||||||
loom->cpu[loom->ncpus].i = i;
|
|
||||||
loom->cpu[loom->ncpus].phyid = phyid;
|
|
||||||
loom->cpu[loom->ncpus].gindex = emu->total_cpu++;
|
|
||||||
|
|
||||||
dbg("new cpu %d at phyid=%d\n", i, phyid);
|
|
||||||
|
|
||||||
loom->ncpus++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
ev_cpu(struct ovni_emu *emu)
|
|
||||||
{
|
|
||||||
switch(emu->cur_ev->header.value)
|
|
||||||
{
|
|
||||||
case 'n': ev_cpu_count(emu); break;
|
|
||||||
case 'i': ev_cpu_id(emu); break;
|
|
||||||
default:
|
|
||||||
dbg("unknown cpu event value %c\n",
|
|
||||||
emu->cur_ev->header.value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
hook_pre_ovni(struct ovni_emu *emu)
|
hook_pre_ovni(struct ovni_emu *emu)
|
||||||
{
|
{
|
||||||
@ -320,7 +252,6 @@ hook_pre_ovni(struct ovni_emu *emu)
|
|||||||
{
|
{
|
||||||
case 'H': ev_thread(emu); break;
|
case 'H': ev_thread(emu); break;
|
||||||
case 'A': ev_affinity(emu); break;
|
case 'A': ev_affinity(emu); break;
|
||||||
case 'C': ev_cpu(emu); break;
|
|
||||||
case 'B': dbg("burst %c\n", emu->cur_ev->header.value); break;
|
case 'B': dbg("burst %c\n", emu->cur_ev->header.value); break;
|
||||||
default:
|
default:
|
||||||
dbg("unknown ovni event class %c\n",
|
dbg("unknown ovni event class %c\n",
|
||||||
@ -410,7 +341,6 @@ hook_emit_ovni(struct ovni_emu *emu)
|
|||||||
emit_thread_state(emu);
|
emit_thread_state(emu);
|
||||||
/* falltrough */
|
/* falltrough */
|
||||||
case 'A':
|
case 'A':
|
||||||
case 'C':
|
|
||||||
emit_thread_count(emu);
|
emit_thread_count(emu);
|
||||||
//emit_current_pid(emu);
|
//emit_current_pid(emu);
|
||||||
break;
|
break;
|
||||||
|
130
ovni.c
130
ovni.c
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include "ovni.h"
|
#include "ovni.h"
|
||||||
#include "ovni_trace.h"
|
#include "ovni_trace.h"
|
||||||
|
#include "parson.h"
|
||||||
|
|
||||||
#define ENABLE_DEBUG
|
#define ENABLE_DEBUG
|
||||||
|
|
||||||
@ -93,8 +94,113 @@ create_trace_stream()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
proc_metadata_init(struct ovni_rproc *proc)
|
||||||
|
{
|
||||||
|
JSON_Value *meta;
|
||||||
|
|
||||||
|
proc->meta = json_value_init_object();
|
||||||
|
|
||||||
|
if(proc->meta == NULL)
|
||||||
|
{
|
||||||
|
err("failed to create json object\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
proc_metadata_store(struct ovni_rproc *proc)
|
||||||
|
{
|
||||||
|
char path[PATH_MAX];
|
||||||
|
|
||||||
|
snprintf(path, PATH_MAX, "%s/metadata.json", proc->dir);
|
||||||
|
|
||||||
|
assert(proc->meta != NULL);
|
||||||
|
|
||||||
|
puts(json_serialize_to_string_pretty(proc->meta));
|
||||||
|
|
||||||
|
if(json_serialize_to_file_pretty(proc->meta, path) != JSONSuccess)
|
||||||
|
{
|
||||||
|
err("failed to write proc metadata\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ovni_add_cpu(int index, int phyid)
|
||||||
|
{
|
||||||
|
JSON_Array *cpuarray;
|
||||||
|
JSON_Object *cpu;
|
||||||
|
JSON_Object *meta;
|
||||||
|
JSON_Value *valcpu, *valcpuarray;
|
||||||
|
int append = 0;
|
||||||
|
|
||||||
|
assert(rproc.ready == 1);
|
||||||
|
assert(rproc.meta != NULL);
|
||||||
|
|
||||||
|
meta = json_value_get_object(rproc.meta);
|
||||||
|
|
||||||
|
assert(meta);
|
||||||
|
|
||||||
|
/* Find the CPU array and create it if needed */
|
||||||
|
cpuarray = json_object_dotget_array(meta, "cpus");
|
||||||
|
|
||||||
|
if(cpuarray == NULL)
|
||||||
|
{
|
||||||
|
valcpuarray = json_value_init_array();
|
||||||
|
assert(valcpuarray);
|
||||||
|
|
||||||
|
cpuarray = json_array(valcpuarray);
|
||||||
|
assert(cpuarray);
|
||||||
|
append = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
valcpuarray = json_array_get_wrapping_value(cpuarray);
|
||||||
|
assert(valcpuarray);
|
||||||
|
|
||||||
|
valcpu = json_value_init_object();
|
||||||
|
assert(valcpu);
|
||||||
|
|
||||||
|
cpu = json_object(valcpu);
|
||||||
|
assert(cpu);
|
||||||
|
|
||||||
|
if(json_object_set_number(cpu, "index", index) != 0)
|
||||||
|
abort();
|
||||||
|
|
||||||
|
if(json_object_set_number(cpu, "phyid", phyid) != 0)
|
||||||
|
abort();
|
||||||
|
|
||||||
|
if(json_array_append_value(cpuarray, valcpu) != 0)
|
||||||
|
abort();
|
||||||
|
|
||||||
|
if(append && json_object_set_value(meta, "cpus", valcpuarray) != 0)
|
||||||
|
abort();
|
||||||
|
|
||||||
|
//puts(json_serialize_to_string_pretty(rproc.meta));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
proc_set_app(int appid)
|
||||||
|
{
|
||||||
|
JSON_Object *meta;
|
||||||
|
|
||||||
|
assert(rproc.ready == 1);
|
||||||
|
assert(rproc.meta != NULL);
|
||||||
|
|
||||||
|
meta = json_value_get_object(rproc.meta);
|
||||||
|
|
||||||
|
assert(meta);
|
||||||
|
|
||||||
|
if(json_object_set_number(meta, "app_id", appid) != 0)
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ovni_proc_init(char *loom, int proc)
|
ovni_proc_init(int app, char *loom, int proc)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -105,6 +211,7 @@ ovni_proc_init(char *loom, int proc)
|
|||||||
/* FIXME: strcpy is insecure */
|
/* FIXME: strcpy is insecure */
|
||||||
strcpy(rproc.loom, loom);
|
strcpy(rproc.loom, loom);
|
||||||
rproc.proc = proc;
|
rproc.proc = proc;
|
||||||
|
rproc.app = app;
|
||||||
|
|
||||||
/* By default we use the monotonic clock */
|
/* By default we use the monotonic clock */
|
||||||
rproc.clockid = CLOCK_MONOTONIC;
|
rproc.clockid = CLOCK_MONOTONIC;
|
||||||
@ -112,8 +219,22 @@ ovni_proc_init(char *loom, int proc)
|
|||||||
if(create_trace_dirs(OVNI_TRACEDIR, loom, proc))
|
if(create_trace_dirs(OVNI_TRACEDIR, loom, proc))
|
||||||
abort();
|
abort();
|
||||||
|
|
||||||
|
if(proc_metadata_init(&rproc) != 0)
|
||||||
|
abort();
|
||||||
|
|
||||||
rproc.ready = 1;
|
rproc.ready = 1;
|
||||||
|
|
||||||
|
proc_set_app(app);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ovni_proc_fini()
|
||||||
|
{
|
||||||
|
if(proc_metadata_store(&rproc) != 0)
|
||||||
|
abort();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -511,6 +632,11 @@ load_proc(struct ovni_eproc *proc, int index, int pid, char *procdir)
|
|||||||
proc->index = index;
|
proc->index = index;
|
||||||
proc->gindex = total_procs++;
|
proc->gindex = total_procs++;
|
||||||
|
|
||||||
|
sprintf(path, "%s/%s", procdir, "metadata.json");
|
||||||
|
proc->meta = json_parse_file_with_comments(path);
|
||||||
|
|
||||||
|
assert(proc->meta);
|
||||||
|
|
||||||
if((dir = opendir(procdir)) == NULL)
|
if((dir = opendir(procdir)) == NULL)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "opendir %s failed: %s\n",
|
fprintf(stderr, "opendir %s failed: %s\n",
|
||||||
@ -545,6 +671,8 @@ load_proc(struct ovni_eproc *proc, int index, int pid, char *procdir)
|
|||||||
|
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
11
ovni.h
11
ovni.h
@ -8,6 +8,8 @@
|
|||||||
#include <linux/limits.h>
|
#include <linux/limits.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include "parson.h"
|
||||||
|
|
||||||
#define OVNI_MAX_CPU 256
|
#define OVNI_MAX_CPU 256
|
||||||
#define OVNI_MAX_PROC 32
|
#define OVNI_MAX_PROC 32
|
||||||
#define OVNI_MAX_THR 32
|
#define OVNI_MAX_THR 32
|
||||||
@ -93,6 +95,7 @@ struct ovni_rproc {
|
|||||||
/* Path of the process tracedir */
|
/* Path of the process tracedir */
|
||||||
char dir[PATH_MAX];
|
char dir[PATH_MAX];
|
||||||
|
|
||||||
|
int app;
|
||||||
int proc;
|
int proc;
|
||||||
char loom[HOST_NAME_MAX];
|
char loom[HOST_NAME_MAX];
|
||||||
int ncpus;
|
int ncpus;
|
||||||
@ -100,9 +103,13 @@ struct ovni_rproc {
|
|||||||
char procdir[PATH_MAX];
|
char procdir[PATH_MAX];
|
||||||
|
|
||||||
int ready;
|
int ready;
|
||||||
|
|
||||||
|
JSON_Value *meta;
|
||||||
};
|
};
|
||||||
|
|
||||||
int ovni_proc_init(char *loom, int proc);
|
int ovni_proc_init(int app, char *loom, int proc);
|
||||||
|
|
||||||
|
int ovni_proc_fini();
|
||||||
|
|
||||||
int ovni_thread_init(pid_t tid);
|
int ovni_thread_init(pid_t tid);
|
||||||
|
|
||||||
@ -120,6 +127,8 @@ int ovni_ev_size(struct ovni_ev *ev);
|
|||||||
|
|
||||||
int ovni_payload_size(struct ovni_ev *ev);
|
int ovni_payload_size(struct ovni_ev *ev);
|
||||||
|
|
||||||
|
void ovni_add_cpu(int index, int phyid);
|
||||||
|
|
||||||
/* Set the current clock in the event and queue it */
|
/* Set the current clock in the event and queue it */
|
||||||
void ovni_ev(struct ovni_ev *ev);
|
void ovni_ev(struct ovni_ev *ev);
|
||||||
void ovni_ev_jumbo(struct ovni_ev *ev, uint8_t *buf, uint32_t bufsize);
|
void ovni_ev_jumbo(struct ovni_ev *ev, uint8_t *buf, uint32_t bufsize);
|
||||||
|
250
parson.h
Normal file
250
parson.h
Normal file
@ -0,0 +1,250 @@
|
|||||||
|
/*
|
||||||
|
SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
Parson 1.1.3 ( http://kgabis.github.com/parson/ )
|
||||||
|
Copyright (c) 2012 - 2021 Krzysztof Gabis
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef parson_parson_h
|
||||||
|
#define parson_parson_h
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stddef.h> /* size_t */
|
||||||
|
|
||||||
|
/* Types and enums */
|
||||||
|
typedef struct json_object_t JSON_Object;
|
||||||
|
typedef struct json_array_t JSON_Array;
|
||||||
|
typedef struct json_value_t JSON_Value;
|
||||||
|
|
||||||
|
enum json_value_type {
|
||||||
|
JSONError = -1,
|
||||||
|
JSONNull = 1,
|
||||||
|
JSONString = 2,
|
||||||
|
JSONNumber = 3,
|
||||||
|
JSONObject = 4,
|
||||||
|
JSONArray = 5,
|
||||||
|
JSONBoolean = 6
|
||||||
|
};
|
||||||
|
typedef int JSON_Value_Type;
|
||||||
|
|
||||||
|
enum json_result_t {
|
||||||
|
JSONSuccess = 0,
|
||||||
|
JSONFailure = -1
|
||||||
|
};
|
||||||
|
typedef int JSON_Status;
|
||||||
|
|
||||||
|
typedef void * (*JSON_Malloc_Function)(size_t);
|
||||||
|
typedef void (*JSON_Free_Function)(void *);
|
||||||
|
|
||||||
|
/* Call only once, before calling any other function from parson API. If not called, malloc and free
|
||||||
|
from stdlib will be used for all allocations */
|
||||||
|
void json_set_allocation_functions(JSON_Malloc_Function malloc_fun, JSON_Free_Function free_fun);
|
||||||
|
|
||||||
|
/* Sets if slashes should be escaped or not when serializing JSON. By default slashes are escaped.
|
||||||
|
This function sets a global setting and is not thread safe. */
|
||||||
|
void json_set_escape_slashes(int escape_slashes);
|
||||||
|
|
||||||
|
/* Parses first JSON value in a file, returns NULL in case of error */
|
||||||
|
JSON_Value * json_parse_file(const char *filename);
|
||||||
|
|
||||||
|
/* Parses first JSON value in a file and ignores comments (/ * * / and //),
|
||||||
|
returns NULL in case of error */
|
||||||
|
JSON_Value * json_parse_file_with_comments(const char *filename);
|
||||||
|
|
||||||
|
/* Parses first JSON value in a string, returns NULL in case of error */
|
||||||
|
JSON_Value * json_parse_string(const char *string);
|
||||||
|
|
||||||
|
/* Parses first JSON value in a string and ignores comments (/ * * / and //),
|
||||||
|
returns NULL in case of error */
|
||||||
|
JSON_Value * json_parse_string_with_comments(const char *string);
|
||||||
|
|
||||||
|
/* Serialization */
|
||||||
|
size_t json_serialization_size(const JSON_Value *value); /* returns 0 on fail */
|
||||||
|
JSON_Status json_serialize_to_buffer(const JSON_Value *value, char *buf, size_t buf_size_in_bytes);
|
||||||
|
JSON_Status json_serialize_to_file(const JSON_Value *value, const char *filename);
|
||||||
|
char * json_serialize_to_string(const JSON_Value *value);
|
||||||
|
|
||||||
|
/* Pretty serialization */
|
||||||
|
size_t json_serialization_size_pretty(const JSON_Value *value); /* returns 0 on fail */
|
||||||
|
JSON_Status json_serialize_to_buffer_pretty(const JSON_Value *value, char *buf, size_t buf_size_in_bytes);
|
||||||
|
JSON_Status json_serialize_to_file_pretty(const JSON_Value *value, const char *filename);
|
||||||
|
char * json_serialize_to_string_pretty(const JSON_Value *value);
|
||||||
|
|
||||||
|
void json_free_serialized_string(char *string); /* frees string from json_serialize_to_string and json_serialize_to_string_pretty */
|
||||||
|
|
||||||
|
/* Comparing */
|
||||||
|
int json_value_equals(const JSON_Value *a, const JSON_Value *b);
|
||||||
|
|
||||||
|
/* Validation
|
||||||
|
This is *NOT* JSON Schema. It validates json by checking if object have identically
|
||||||
|
named fields with matching types.
|
||||||
|
For example schema {"name":"", "age":0} will validate
|
||||||
|
{"name":"Joe", "age":25} and {"name":"Joe", "age":25, "gender":"m"},
|
||||||
|
but not {"name":"Joe"} or {"name":"Joe", "age":"Cucumber"}.
|
||||||
|
In case of arrays, only first value in schema is checked against all values in tested array.
|
||||||
|
Empty objects ({}) validate all objects, empty arrays ([]) validate all arrays,
|
||||||
|
null validates values of every type.
|
||||||
|
*/
|
||||||
|
JSON_Status json_validate(const JSON_Value *schema, const JSON_Value *value);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* JSON Object
|
||||||
|
*/
|
||||||
|
JSON_Value * json_object_get_value (const JSON_Object *object, const char *name);
|
||||||
|
const char * json_object_get_string (const JSON_Object *object, const char *name);
|
||||||
|
size_t json_object_get_string_len(const JSON_Object *object, const char *name); /* doesn't account for last null character */
|
||||||
|
JSON_Object * json_object_get_object (const JSON_Object *object, const char *name);
|
||||||
|
JSON_Array * json_object_get_array (const JSON_Object *object, const char *name);
|
||||||
|
double json_object_get_number (const JSON_Object *object, const char *name); /* returns 0 on fail */
|
||||||
|
int json_object_get_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */
|
||||||
|
|
||||||
|
/* dotget functions enable addressing values with dot notation in nested objects,
|
||||||
|
just like in structs or c++/java/c# objects (e.g. objectA.objectB.value).
|
||||||
|
Because valid names in JSON can contain dots, some values may be inaccessible
|
||||||
|
this way. */
|
||||||
|
JSON_Value * json_object_dotget_value (const JSON_Object *object, const char *name);
|
||||||
|
const char * json_object_dotget_string (const JSON_Object *object, const char *name);
|
||||||
|
size_t json_object_dotget_string_len(const JSON_Object *object, const char *name); /* doesn't account for last null character */
|
||||||
|
JSON_Object * json_object_dotget_object (const JSON_Object *object, const char *name);
|
||||||
|
JSON_Array * json_object_dotget_array (const JSON_Object *object, const char *name);
|
||||||
|
double json_object_dotget_number (const JSON_Object *object, const char *name); /* returns 0 on fail */
|
||||||
|
int json_object_dotget_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */
|
||||||
|
|
||||||
|
/* Functions to get available names */
|
||||||
|
size_t json_object_get_count (const JSON_Object *object);
|
||||||
|
const char * json_object_get_name (const JSON_Object *object, size_t index);
|
||||||
|
JSON_Value * json_object_get_value_at(const JSON_Object *object, size_t index);
|
||||||
|
JSON_Value * json_object_get_wrapping_value(const JSON_Object *object);
|
||||||
|
|
||||||
|
/* Functions to check if object has a value with a specific name. Returned value is 1 if object has
|
||||||
|
* a value and 0 if it doesn't. dothas functions behave exactly like dotget functions. */
|
||||||
|
int json_object_has_value (const JSON_Object *object, const char *name);
|
||||||
|
int json_object_has_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type);
|
||||||
|
|
||||||
|
int json_object_dothas_value (const JSON_Object *object, const char *name);
|
||||||
|
int json_object_dothas_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type);
|
||||||
|
|
||||||
|
/* Creates new name-value pair or frees and replaces old value with a new one.
|
||||||
|
* json_object_set_value does not copy passed value so it shouldn't be freed afterwards. */
|
||||||
|
JSON_Status json_object_set_value(JSON_Object *object, const char *name, JSON_Value *value);
|
||||||
|
JSON_Status json_object_set_string(JSON_Object *object, const char *name, const char *string);
|
||||||
|
JSON_Status json_object_set_string_with_len(JSON_Object *object, const char *name, const char *string, size_t len); /* length shouldn't include last null character */
|
||||||
|
JSON_Status json_object_set_number(JSON_Object *object, const char *name, double number);
|
||||||
|
JSON_Status json_object_set_boolean(JSON_Object *object, const char *name, int boolean);
|
||||||
|
JSON_Status json_object_set_null(JSON_Object *object, const char *name);
|
||||||
|
|
||||||
|
/* Works like dotget functions, but creates whole hierarchy if necessary.
|
||||||
|
* json_object_dotset_value does not copy passed value so it shouldn't be freed afterwards. */
|
||||||
|
JSON_Status json_object_dotset_value(JSON_Object *object, const char *name, JSON_Value *value);
|
||||||
|
JSON_Status json_object_dotset_string(JSON_Object *object, const char *name, const char *string);
|
||||||
|
JSON_Status json_object_dotset_string_with_len(JSON_Object *object, const char *name, const char *string, size_t len); /* length shouldn't include last null character */
|
||||||
|
JSON_Status json_object_dotset_number(JSON_Object *object, const char *name, double number);
|
||||||
|
JSON_Status json_object_dotset_boolean(JSON_Object *object, const char *name, int boolean);
|
||||||
|
JSON_Status json_object_dotset_null(JSON_Object *object, const char *name);
|
||||||
|
|
||||||
|
/* Frees and removes name-value pair */
|
||||||
|
JSON_Status json_object_remove(JSON_Object *object, const char *name);
|
||||||
|
|
||||||
|
/* Works like dotget function, but removes name-value pair only on exact match. */
|
||||||
|
JSON_Status json_object_dotremove(JSON_Object *object, const char *key);
|
||||||
|
|
||||||
|
/* Removes all name-value pairs in object */
|
||||||
|
JSON_Status json_object_clear(JSON_Object *object);
|
||||||
|
|
||||||
|
/*
|
||||||
|
*JSON Array
|
||||||
|
*/
|
||||||
|
JSON_Value * json_array_get_value (const JSON_Array *array, size_t index);
|
||||||
|
const char * json_array_get_string (const JSON_Array *array, size_t index);
|
||||||
|
size_t json_array_get_string_len(const JSON_Array *array, size_t index); /* doesn't account for last null character */
|
||||||
|
JSON_Object * json_array_get_object (const JSON_Array *array, size_t index);
|
||||||
|
JSON_Array * json_array_get_array (const JSON_Array *array, size_t index);
|
||||||
|
double json_array_get_number (const JSON_Array *array, size_t index); /* returns 0 on fail */
|
||||||
|
int json_array_get_boolean(const JSON_Array *array, size_t index); /* returns -1 on fail */
|
||||||
|
size_t json_array_get_count (const JSON_Array *array);
|
||||||
|
JSON_Value * json_array_get_wrapping_value(const JSON_Array *array);
|
||||||
|
|
||||||
|
/* Frees and removes value at given index, does nothing and returns JSONFailure if index doesn't exist.
|
||||||
|
* Order of values in array may change during execution. */
|
||||||
|
JSON_Status json_array_remove(JSON_Array *array, size_t i);
|
||||||
|
|
||||||
|
/* Frees and removes from array value at given index and replaces it with given one.
|
||||||
|
* Does nothing and returns JSONFailure if index doesn't exist.
|
||||||
|
* json_array_replace_value does not copy passed value so it shouldn't be freed afterwards. */
|
||||||
|
JSON_Status json_array_replace_value(JSON_Array *array, size_t i, JSON_Value *value);
|
||||||
|
JSON_Status json_array_replace_string(JSON_Array *array, size_t i, const char* string);
|
||||||
|
JSON_Status json_array_replace_string_with_len(JSON_Array *array, size_t i, const char *string, size_t len); /* length shouldn't include last null character */
|
||||||
|
JSON_Status json_array_replace_number(JSON_Array *array, size_t i, double number);
|
||||||
|
JSON_Status json_array_replace_boolean(JSON_Array *array, size_t i, int boolean);
|
||||||
|
JSON_Status json_array_replace_null(JSON_Array *array, size_t i);
|
||||||
|
|
||||||
|
/* Frees and removes all values from array */
|
||||||
|
JSON_Status json_array_clear(JSON_Array *array);
|
||||||
|
|
||||||
|
/* Appends new value at the end of array.
|
||||||
|
* json_array_append_value does not copy passed value so it shouldn't be freed afterwards. */
|
||||||
|
JSON_Status json_array_append_value(JSON_Array *array, JSON_Value *value);
|
||||||
|
JSON_Status json_array_append_string(JSON_Array *array, const char *string);
|
||||||
|
JSON_Status json_array_append_string_with_len(JSON_Array *array, const char *string, size_t len); /* length shouldn't include last null character */
|
||||||
|
JSON_Status json_array_append_number(JSON_Array *array, double number);
|
||||||
|
JSON_Status json_array_append_boolean(JSON_Array *array, int boolean);
|
||||||
|
JSON_Status json_array_append_null(JSON_Array *array);
|
||||||
|
|
||||||
|
/*
|
||||||
|
*JSON Value
|
||||||
|
*/
|
||||||
|
JSON_Value * json_value_init_object (void);
|
||||||
|
JSON_Value * json_value_init_array (void);
|
||||||
|
JSON_Value * json_value_init_string (const char *string); /* copies passed string */
|
||||||
|
JSON_Value * json_value_init_string_with_len(const char *string, size_t length); /* copies passed string, length shouldn't include last null character */
|
||||||
|
JSON_Value * json_value_init_number (double number);
|
||||||
|
JSON_Value * json_value_init_boolean(int boolean);
|
||||||
|
JSON_Value * json_value_init_null (void);
|
||||||
|
JSON_Value * json_value_deep_copy (const JSON_Value *value);
|
||||||
|
void json_value_free (JSON_Value *value);
|
||||||
|
|
||||||
|
JSON_Value_Type json_value_get_type (const JSON_Value *value);
|
||||||
|
JSON_Object * json_value_get_object (const JSON_Value *value);
|
||||||
|
JSON_Array * json_value_get_array (const JSON_Value *value);
|
||||||
|
const char * json_value_get_string (const JSON_Value *value);
|
||||||
|
size_t json_value_get_string_len(const JSON_Value *value); /* doesn't account for last null character */
|
||||||
|
double json_value_get_number (const JSON_Value *value);
|
||||||
|
int json_value_get_boolean(const JSON_Value *value);
|
||||||
|
JSON_Value * json_value_get_parent (const JSON_Value *value);
|
||||||
|
|
||||||
|
/* Same as above, but shorter */
|
||||||
|
JSON_Value_Type json_type (const JSON_Value *value);
|
||||||
|
JSON_Object * json_object (const JSON_Value *value);
|
||||||
|
JSON_Array * json_array (const JSON_Value *value);
|
||||||
|
const char * json_string (const JSON_Value *value);
|
||||||
|
size_t json_string_len(const JSON_Value *value); /* doesn't account for last null character */
|
||||||
|
double json_number (const JSON_Value *value);
|
||||||
|
int json_boolean(const JSON_Value *value);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@ -13,7 +13,7 @@ int main()
|
|||||||
struct ovni_ev ev = {0};
|
struct ovni_ev ev = {0};
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
ovni_proc_init(0, 0);
|
ovni_proc_init(0, "test", 0);
|
||||||
ovni_thread_init(1);
|
ovni_thread_init(1);
|
||||||
|
|
||||||
ovni_ev_set_mcv(&ev, "OB.");
|
ovni_ev_set_mcv(&ev, "OB.");
|
||||||
|
Loading…
Reference in New Issue
Block a user