2004-10-09 13:09:13 +02:00
|
|
|
#include "patchserver.h"
|
|
|
|
#include <iostream>
|
2004-10-09 16:46:47 +02:00
|
|
|
#include <algorithm>
|
2004-10-09 13:09:13 +02:00
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
using namespace nxs;
|
|
|
|
|
|
|
|
|
|
|
|
bool PatchServer::Create(const std::string &filename,
|
|
|
|
Signature sig,
|
|
|
|
unsigned int csize,
|
|
|
|
unsigned int rsize) {
|
|
|
|
signature = sig;
|
|
|
|
chunk_size = csize;
|
2004-10-09 16:46:47 +02:00
|
|
|
frame = 0;
|
2004-10-09 13:09:13 +02:00
|
|
|
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;
|
2004-10-09 16:46:47 +02:00
|
|
|
frame = 0;
|
2004-10-09 13:09:13 +02:00
|
|
|
ram_used = 0;
|
|
|
|
lru.clear();
|
|
|
|
return File::Load(filename, readonly);
|
|
|
|
}
|
|
|
|
|
2004-10-09 16:46:47 +02:00
|
|
|
void PatchServer::Close() {
|
2004-10-09 13:09:13 +02:00
|
|
|
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);
|
2004-10-10 19:19:42 +02:00
|
|
|
fread(&(patches[i].ram_size), 1, sizeof(unsigned short), fp);
|
|
|
|
fread(&(patches[i].disk_size), 1, sizeof(unsigned short), fp);
|
2004-10-09 13:09:13 +02:00
|
|
|
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);
|
2004-10-10 19:19:42 +02:00
|
|
|
fwrite(&(patches[i].ram_size), 1, sizeof(unsigned short), fp);
|
|
|
|
fwrite(&(patches[i].disk_size), 1, sizeof(unsigned short), fp);
|
2004-10-09 13:09:13 +02:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PatchServer::AddPatch(unsigned short nvert, unsigned short nface) {
|
|
|
|
PatchEntry entry;
|
|
|
|
entry.patch = NULL;
|
2004-10-10 19:19:42 +02:00
|
|
|
entry.ram_size = Patch::ChunkSize(signature, nvert, nface, chunk_size);
|
|
|
|
|
|
|
|
//if compressed we do not allocate space now (how much anyway?)
|
|
|
|
// if((signature & NXS_COMPRESSED) != 0) {
|
|
|
|
entry.disk_size = 0xffff;
|
|
|
|
entry.patch_start = 0xffffffff;
|
|
|
|
/* } else {
|
|
|
|
entry.disk_size = entry.ram_size;
|
|
|
|
entry.patch_start = Length()/chunk_size;
|
|
|
|
Redim(Length() + entry.disk_size * chunk_size);
|
|
|
|
}*/
|
2004-10-09 13:09:13 +02:00
|
|
|
entry.lru_pos = 0xffffffff;
|
|
|
|
patches.push_back(entry);
|
2004-10-10 19:19:42 +02:00
|
|
|
|
2004-10-09 13:09:13 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Patch &PatchServer::GetPatch(unsigned int idx,
|
|
|
|
unsigned short nvert, unsigned short nface,
|
|
|
|
bool flush) {
|
|
|
|
assert(idx < patches.size());
|
|
|
|
PatchEntry &entry = patches[idx];
|
|
|
|
|
2004-10-10 19:19:42 +02:00
|
|
|
if(entry.patch) { //already on buffer
|
2004-10-09 13:09:13 +02:00
|
|
|
assert(entry.lru_pos < lru.size());
|
|
|
|
assert(lru[entry.lru_pos].patch == idx);
|
|
|
|
lru[entry.lru_pos].frame = frame++;
|
2004-10-10 19:19:42 +02:00
|
|
|
|
2004-10-09 13:09:13 +02:00
|
|
|
} else {
|
2004-10-10 19:19:42 +02:00
|
|
|
|
|
|
|
assert(entry.lru_pos == 0xffffffff);
|
|
|
|
if(flush) Flush();
|
|
|
|
|
|
|
|
|
|
|
|
char *ram = new char[entry.ram_size * chunk_size];
|
|
|
|
entry.patch = new Patch(signature, ram, nvert, nface);
|
2004-10-09 13:09:13 +02:00
|
|
|
|
2004-10-10 19:19:42 +02:00
|
|
|
if(entry.patch_start != 0xffffffff) { //was allocated.
|
|
|
|
assert(entry.disk_size != 0xffff);
|
|
|
|
|
|
|
|
SetPosition(entry.patch_start * chunk_size);
|
|
|
|
|
|
|
|
if((signature & NXS_COMPRESSED) == 0) { //not compressed
|
|
|
|
ReadBuffer(ram, entry.disk_size * chunk_size);
|
|
|
|
} else {
|
|
|
|
|
|
|
|
unsigned char *disk = new unsigned char[entry.disk_size * chunk_size];
|
|
|
|
ReadBuffer(disk, entry.disk_size * chunk_size);
|
|
|
|
|
|
|
|
entry.patch->Decompress(entry.ram_size * chunk_size,
|
|
|
|
disk, entry.disk_size * chunk_size);
|
|
|
|
delete []disk;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-10-09 13:09:13 +02:00
|
|
|
entry.lru_pos = lru.size();
|
|
|
|
lru.push_back(PTime(idx, frame++));
|
2004-10-10 19:19:42 +02:00
|
|
|
ram_used += entry.ram_size;
|
2004-10-09 13:09:13 +02:00
|
|
|
}
|
2004-10-09 16:46:47 +02:00
|
|
|
|
2004-10-09 13:09:13 +02:00
|
|
|
//avoid frame overflow!
|
|
|
|
if(frame > (1<<30)) {
|
2004-10-09 16:46:47 +02:00
|
|
|
cerr << "oVERFLOW! (nothing dangerous... just warning." << endl;;
|
2004-10-09 13:09:13 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
return *(entry.patch);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PatchServer::Flush() {
|
2004-10-10 19:19:42 +02:00
|
|
|
|
|
|
|
if(ram_used < ram_size * 1.5) return;
|
|
|
|
|
2004-10-09 13:09:13 +02:00
|
|
|
make_heap(lru.begin(), lru.end());
|
2004-10-10 19:19:42 +02:00
|
|
|
for(unsigned int i = 0; i < lru.size(); i++)
|
|
|
|
patches[lru[i].patch].lru_pos = i;
|
|
|
|
|
2004-10-09 13:09:13 +02:00
|
|
|
while(ram_used > ram_size) {
|
|
|
|
pop_heap(lru.begin(), lru.end());
|
|
|
|
PTime &ptime = lru.back();
|
|
|
|
Flush(ptime.patch);
|
|
|
|
lru.pop_back();
|
|
|
|
}
|
|
|
|
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
|
2004-10-10 19:19:42 +02:00
|
|
|
|
|
|
|
|
|
|
|
if((signature & NXS_COMPRESSED)) {
|
|
|
|
unsigned int compressed_size;
|
|
|
|
char *compressed = entry.patch->Compress(entry.ram_size * chunk_size,
|
|
|
|
compressed_size);
|
|
|
|
if(entry.disk_size == 0xffff) {//allocate space
|
|
|
|
assert(entry.patch_start == 0xffffffff);
|
|
|
|
entry.disk_size = (unsigned int)((compressed_size-1)/chunk_size) + 1;
|
|
|
|
entry.patch_start = Length()/chunk_size;
|
|
|
|
Redim(Length() + entry.disk_size * chunk_size);
|
|
|
|
} else {
|
|
|
|
cerr << "OOOOPSPPPS not supported!" << endl;
|
|
|
|
exit(-1);
|
|
|
|
}
|
|
|
|
SetPosition(entry.patch_start * chunk_size);
|
|
|
|
WriteBuffer(compressed, entry.disk_size * chunk_size);
|
|
|
|
delete []compressed;
|
|
|
|
} else {
|
|
|
|
if(entry.disk_size == 0xffff) {
|
|
|
|
entry.disk_size = entry.ram_size;
|
|
|
|
entry.patch_start = Length()/chunk_size;
|
|
|
|
Redim(Length() + entry.disk_size * chunk_size);
|
|
|
|
}
|
|
|
|
SetPosition(entry.patch_start * chunk_size);
|
|
|
|
WriteBuffer(entry.patch->start, entry.disk_size * chunk_size);
|
|
|
|
}
|
|
|
|
/* FILE *fo = fopen("tmp", "wb+");
|
|
|
|
fwrite(entry.patch->start, 1, entry.disk_size * chunk_size, fo);
|
|
|
|
fclose(fo);
|
|
|
|
exit(0);*/
|
2004-10-09 13:09:13 +02:00
|
|
|
}
|
2004-10-10 19:19:42 +02:00
|
|
|
|
2004-10-09 13:09:13 +02:00
|
|
|
delete [](entry.patch->start);
|
|
|
|
delete entry.patch;
|
|
|
|
entry.patch = NULL;
|
|
|
|
entry.lru_pos = 0xffffffff;
|
2004-10-10 19:19:42 +02:00
|
|
|
ram_used -= entry.ram_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PatchServer::SetRamBufferSize(unsigned int r_buffer) {
|
|
|
|
ram_size = (unsigned int)(r_buffer/chunk_size) + 1;
|
2004-10-09 13:09:13 +02:00
|
|
|
}
|