diff --git a/apps/nexus/borderserver.cpp b/apps/nexus/borderserver.cpp new file mode 100644 index 00000000..239c285f --- /dev/null +++ b/apps/nexus/borderserver.cpp @@ -0,0 +1,61 @@ +#include "borderserver.h" +#include + +using namespace std; +using namespace nxs; + +void BorderServer::AddBorder(unsigned short nbord, unsigned int used) { + BorderEntry entry; + entry.border_start = Size(); + entry.border_size = nbord; + entry.border_used = used; + borders.push_back(entry); + Resize(entry.border_start + nbord); +} + +Border BorderServer::GetBorder(unsigned int border, bool flush) { + assert(border < borders.size()); + BorderEntry &entry = borders[border]; + Link *start = GetRegion(entry.border_start, entry.border_size, flush); + return Border(start, entry.border_used, entry.border_size); +} + +bool BorderServer::ResizeBorder(unsigned int border, unsigned int nbord) { + + assert(border < borders.size()); + BorderEntry &entry = borders[border]; + if(nbord > entry.border_size) { + unsigned int capacity = nbord; + if(capacity < entry.border_size*2) + capacity = entry.border_size * 2; + unsigned int newstart = Size(); + Resize(newstart + capacity); + + Link *src = GetRegion(entry.border_start, entry.border_size); + Link *dst = GetRegion(newstart, capacity, false); + memcpy(dst, src, entry.border_used * sizeof(Link)); + entry.border_start = newstart; + entry.border_size = capacity; + entry.border_used = nbord; + return true; + } + entry.border_used = nbord; + return false; +} + +bool BorderServer::ReadEntries(FILE *fp) { + unsigned int n; + fread(&n, 1, sizeof(int), fp); + borders.resize(n); + fread(&*borders.begin(), n, sizeof(BorderEntry), fp); + return true; +} + +bool BorderServer::WriteEntries(FILE *fp) { + unsigned int n = borders.size(); + fwrite(&n, 1, sizeof(int), fp); + fwrite(&*borders.begin(), n, sizeof(BorderEntry), fp); + return true; +} + + diff --git a/apps/nexus/borderserver.h b/apps/nexus/borderserver.h new file mode 100644 index 00000000..36faabb1 --- /dev/null +++ b/apps/nexus/borderserver.h @@ -0,0 +1,42 @@ +#ifndef NXS_BORDERSERVER_H +#define NXS_BORDERSERVER_H + +#include "vfile.h" +#include "border.h" +#include + +namespace nxs { + +struct BorderEntry { + unsigned int border_start; //granuralita' Link + unsigned short border_size; //in Links + unsigned short border_used; //in Links +}; + +class BorderServer: public VFile { + public: + void AddBorder(unsigned short nbord, unsigned int used = 0); + Border GetBorder(unsigned int border, bool flush = true); + //return true if you need to reread border as it changed location + bool ResizeBorder(unsigned int border, unsigned int nbord); + + bool ReadEntries(FILE *fp); + bool WriteEntries(FILE *fp); + + unsigned int BorderSize(unsigned int i) { + return borders[i].border_used; + } + unsigned int BorderCapacity(unsigned int i) { + return borders[i].border_size; + } + + + + + std::vector borders; + +}; + +} + +#endif diff --git a/apps/nexus/patchserver.cpp b/apps/nexus/patchserver.cpp new file mode 100644 index 00000000..0d0341ad --- /dev/null +++ b/apps/nexus/patchserver.cpp @@ -0,0 +1,162 @@ +#include "patchserver.h" + +#include + +using namespace std; +using namespace nxs; + +//TODO support compression! + + +bool PatchServer::Create(const std::string &filename, + Signature sig, + unsigned int csize, + unsigned int rsize) { + signature = sig; + chunk_size = csize; + ram_size = rsize; + ram_used = 0; + lru.clear(); + return File::Create(filename); +} + +bool PatchServer::Load(const std::string &filename, Signature sig, + unsigned int csize, bool readonly, + unsigned int rsize) { + signature = sig; + chunk_size = csize; + ram_size = rsize; + ram_used = 0; + lru.clear(); + return File::Load(filename, readonly); +} + +void PatchServer::Close() { + cerr << "Closing!" << endl; + FlushAll(); + File::Close(); +} + +//TODO add error checking. +bool PatchServer::ReadEntries(FILE *fp) { + unsigned int n; + fread(&n, 1, sizeof(int), fp); + patches.resize(n); + for(unsigned int i = 0; i < n; i++) { + patches[i].patch = NULL; + fread(&(patches[i].patch_start), 1, sizeof(unsigned int), fp); + fread(&(patches[i].patch_size), 1, sizeof(unsigned short), fp); + fread(&(patches[i].ram_used), 1, sizeof(unsigned short), fp); + patches[i].lru_pos = 0xffffffff; + } + return true; +} + +bool PatchServer::WriteEntries(FILE *fp) { + unsigned int n = patches.size(); + fwrite(&n, 1, sizeof(int), fp); + for(unsigned int i = 0; i < patches.size(); i++) { + fwrite(&(patches[i].patch_start), 1, sizeof(unsigned int), fp); + fwrite(&(patches[i].patch_size), 1, sizeof(unsigned short), fp); + fwrite(&(patches[i].ram_used), 1, sizeof(unsigned short), fp); + } + return true; +} + +void PatchServer::AddPatch(unsigned short nvert, unsigned short nface) { + PatchEntry entry; + entry.patch = NULL; + entry.patch_start = Length()/chunk_size; + entry.patch_size = Patch::ChunkSize(signature, nvert, nface, chunk_size); + entry.ram_used = entry.patch_size; + entry.lru_pos = 0xffffffff; + patches.push_back(entry); + + Redim(Length() + entry.patch_size * chunk_size); +} + +Patch &PatchServer::GetPatch(unsigned int idx, + unsigned short nvert, unsigned short nface, + bool flush) { + + assert(idx < patches.size()); + PatchEntry &entry = patches[idx]; + + if(entry.patch) { + assert(entry.lru_pos < lru.size()); + assert(lru[entry.lru_pos].patch == idx); + lru[entry.lru_pos].frame = frame++; + } else { + SetPosition(entry.patch_start * chunk_size); + + assert(entry.patch_size != 0); + char *start = new char[entry.patch_size * chunk_size]; + ReadBuffer(start, entry.patch_size * chunk_size); + + entry.patch = new Patch(signature, start, nvert, nface); + entry.lru_pos = lru.size(); + lru.push_back(PTime(idx, frame++)); + ram_used += entry.ram_used; + } + + //avoid frame overflow! + if(frame > (1<<30)) { + cerr << "oVERFLOW!" << endl;; + for(unsigned int i = 0; i < lru.size(); i++) { + if(lru[i].frame < (1<<29)) lru[i].frame = 0; + else lru[i].frame -= (1<<29); + } + make_heap(lru.begin(), lru.end()); + for(unsigned int i = 0; i < lru.size(); i++) + patches[lru[i].patch].lru_pos = i; + } + + if(flush && ram_used > ram_size * 1.1) + Flush(); + + return *(entry.patch); +} + +void PatchServer::Flush() { + cerr << "FLUSHING\n\n\n n"; + cerr << "ram_size: " << ram_size << endl; + cerr << "ram_used: " << ram_used << endl; + make_heap(lru.begin(), lru.end()); + while(ram_used > ram_size) { + pop_heap(lru.begin(), lru.end()); + PTime &ptime = lru.back(); + + Flush(ptime.patch); + + lru.pop_back(); + } + make_heap(lru.begin(), lru.end()); + for(unsigned int i = 0; i < lru.size(); i++) + patches[lru[i].patch].lru_pos = i; +} + +void PatchServer::FlushAll() { + for(unsigned int i = 0; i < lru.size(); i++) { + PTime &ptime = lru[i]; + Flush(ptime.patch); + } + assert(ram_used == 0); + lru.clear(); +} + + +void PatchServer::Flush(unsigned int patch) { + + PatchEntry &entry = patches[patch]; + assert(entry.patch); + + if(!readonly) { //write back patch + SetPosition(entry.patch_start * chunk_size); + WriteBuffer(entry.patch->start, entry.patch_size * chunk_size); + } + delete [](entry.patch->start); + delete entry.patch; + entry.patch = NULL; + entry.lru_pos = 0xffffffff; + ram_used -= entry.ram_used; +} diff --git a/apps/nexus/patchserver.h b/apps/nexus/patchserver.h new file mode 100644 index 00000000..dd2125bb --- /dev/null +++ b/apps/nexus/patchserver.h @@ -0,0 +1,64 @@ +#ifndef NXS_PATCH_SERVER_H +#define NXS_PATCH_SERVER_H + +#include "patch.h" +#include "file.h" + +#include + +namespace nxs { + +struct PatchEntry { + Patch *patch; + unsigned int patch_start; //granularita' Chunk + unsigned short patch_size; //in chunks + unsigned short ram_used; // in chunks (used when compressed) + unsigned int lru_pos; +}; + +class PatchServer: public File { + public: + struct PTime { + unsigned int patch; + unsigned int frame; + + PTime(unsigned int p = 0xffffffff, unsigned int f = 0xffffffff): + patch(p), frame(f) {} + + bool operator<(const PTime &p) const { return frame < p.frame; } + }; + + + Signature signature; + unsigned int chunk_size; + unsigned int ram_size; + unsigned int ram_used; + unsigned int frame; + + + bool Create(const std::string &filename, Signature signature, + unsigned int chunk_size, unsigned int ram_size = 128000); + bool Load(const std::string &filename, Signature sig, + unsigned int chunk_size, bool readonly, + unsigned int ram_size = 128000); + + void Close(); + + bool ReadEntries(FILE *fp); + bool WriteEntries(FILE *fp); + + void AddPatch(unsigned short nvert, unsigned short nface); + Patch &GetPatch(unsigned int patch, unsigned short nvert, unsigned short nface, + bool flush = true); + + void Flush(); + void FlushAll(); + void Flush(unsigned int patch); + + std::vector patches; + std::vector lru; +}; + +} + +#endif