Hi Christoph,
Well, the loader setup is embarrasingly simple, so I can share that
wihout worries. See the attached bsFileSys.xxx files (it requires
boost::filesystem, but that is not necessary, merely a convenience). The
zip-datasource implements this for a zip-archive (to read from
directories within a zip-file) by using ZipIOs. The latter works
somewhat ok but I need to reconfigure our app a lot to make it truly
usable for us (we have some relative paths & includes in scripts that
mess things up quite a bit currently).
What I really wanted was a good virtual file system with zip and
whatnot-support, but I haven't been able to find anything like that on
the net. I could also imagine using URI's and a xml-alike content
resolver framework, but neither of this is top-priority at all.
The cache system is not really what you're looking for, I think. It
serves to speed up reloading previously read & optimized content as
gzipped .osb files (not a single cache, but individial files), for
faster subsequent runs (tristripping and sharing opts can take time, esp
in debug). I'm using boost-iostream there, to add a gzip-(de)compressor
to the original data-stream (usually from file) to reduce disk-access,
which is the limiting factor for us. It does not work when loading the
zipped .osb-files, as the boost-gzip-decompressor cannot provide random
access to the file. (I probably could get away with decompressing to
memory and reading from that, but I need to figure out how large the
decompressed file is.. which I should be able to figure out by checking
the streampos.. hmm :) ..
Anyway, since it, at the moment, doesn't work with .osg & zipped cache
files, it will need some work before it should be released. It also
depends on the boost::iostreams library, which may not be ideal, but
since OpenSG 2.0 seems to be boost-dependent anyway, it might not matter
much when push comes to shove. :)
Cheers,
/Marcus
Christoph Fünfzig wrote:
Hi Marcus,
thanks for your response.
Your framework seems interesting. Your concern is to cache the loaded files
into an OSB file? Can you perhaps send me the sources?
Because of maintainance I am quite wary about large external libraries,
so I am searching for small and easy to integrate ones.
Do you know, if there are plans for remote FileIO in version 2.0 in this
direction?
Christoph
Marcus Lindblom wrote:
Hi Christoph,
Just some related comments:
I would like something like that as well, and I have written some very
basic framework for our application which allows pluggable
content-providers (file/zip/ftp/http, etc). I've only implemented file &
zip (via the ZipIOs lib). However, I ran in to a problem in my caching
system, since the .osb-reader seemed to require random-access to the
stream (I get an exception 'no random access' when trying to read
osg-files from a zipistream.). VRML works fine though.
That might be something to watch out for, depending on what you're
trying to load.
/Marcus
P.S. I didn't mention this on the list at the time because it's just a
nice-to-have for us and I figured it might solve itself in 2.0 or so. :)
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Opensg-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensg-users
#include "stdafx.h"
#include <base/base/bsFileSys.h>
#include <base/base/bsFunctional.h>
#include <base/base/bsLog.h>
#include <base/base/bsSingleton.h>
#include <base/base/bsRefPtr.h>
#include <boost/iostreams/device/back_inserter.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/io/ios_state.hpp>
namespace fs = boost::filesystem;
namespace io = boost::iostreams;
namespace mtc
{
namespace styx
{
namespace base
{
using std:: string;
namespace
{
static LogDecorator s_log("FileSys");
// end anonymous namespace
}
/// FileSysProxy which forwards fs requests to the current target
class FileSysProxy :
public DataSource
{
public:
typedef std::deque<DataSource *> Sources;
Sources m_sources;
FileSysProxy() { m_sources.push_back(&m_stdsys); }
protected:
virtual bool doRead(const std::string& id, Buffer& buf)
{
bool found = false;
for (Sources::iterator i = m_sources.begin();
!found && i != m_sources.end(); ++i) {
std::string where = (*i)->find(id);
if (!where.empty()) {
found = (*i)->read(where, buf);
}
}
return found;
}
virtual std::string doFind(const std::string& id)
{
std::string str;
for (Sources::iterator i = m_sources.begin();
str.empty() && i != m_sources.end(); ++i) {
str = (*i)->find(id);
}
return str;
}
virtual IStreamPtr doOpen(const std::string& id)
{
IStreamPtr is;
for (Sources::iterator i = m_sources.begin(); !is && i !=
m_sources.end();
++i) {
std::string where = (*i)->find(id);
if (!where.empty()) {
is = (*i)->open(where);
}
}
return is;
}
private:
StdFileSys m_stdsys;
};
MTC_IMPLEMENT_NIFTYCOUNTER(FileSysInit);
int GetLongevity(FileSysProxy* )
{
return 3;
}
typedef SingletonHolder<FileSysProxy, CreateUsingNew, SingletonWithLongevity>
FileSysProxyS;
///////////////////////////////////////////
// Buffer
Buffer::Buffer(size_t size) :
m_data(size)
{ }
Buffer::~Buffer()
{ }
std::istream & operator >>(std::istream & is, Buffer & buf) {
boost::io::ios_flags_saver ifs(is, std::ios::binary);
return is.read(buf.data(), boost::numeric_cast < std::streamsize >
(buf.size()));
}
std::ostream & operator <<(std::ostream & os, Buffer & buf) {
boost::io::ios_flags_saver ifs(os, std::ios::binary);
return os.write(buf.data(), boost::numeric_cast < std::streamsize >
(buf.size()));
}
///////////////////////////////////////////
DataSource::~DataSource()
{ }
bool DataSource::read(const std::string& id, Buffer& buf)
{
return doRead(id, buf);
}
std::string DataSource::find(const std::string& id)
{
return doFind(id);
}
DataSource::IStreamPtr DataSource::open(const std::string& id)
{
return doOpen(id);
}
///////////////////////////////////////////
// FileSys
DataSource& FileSys::the()
{
return FileSysProxyS::the();
}
void FileSys::addDataSource(DataSource* ds)
{
assert(ds);
FileSysProxyS::the().m_sources.push_front(ds);
}
void FileSys::subDataSource(DataSource* ds)
{
assert(ds);
FileSysProxyS::type::Sources& s = FileSysProxyS::the().m_sources;
s.erase(std::find(s.begin(), s.end(), ds));
}
std::string FileSys::tempdir()
{
char* dir = 0;
if ((dir = getenv("STYXTMP")) != 0) { } else if ((dir = getenv("TMP")) !=
0) { } else if ((dir = getenv("TEMP")) != 0) { } else {
s_log.info("Unable to determine temp directory. Using '/tmp'.");
}
return dir ? std::string(dir) : "/tmp";
}
///////////////////////////////////////////
// StdFileSys
bool StdFileSys::doRead(const std::string& id, Buffer& buf)
{
if(IStreamPtr is = doOpen(id)) {
std::deque<char> data;
io::copy(*is, io::back_inserter(data));
if (!is->fail()) {
buf.resize(data.size());
std::copy(data.begin(), data.end(), buf.data());
} else {
s_log.err("Error during read of file '%s'.", id.c_str());
}
return !is->fail();
} else {
return false;
}
}
std::string StdFileSys::doFind(const std::string& id)
{
/*$off*/
try {
fs::path path(id, fs::native);
if (!path.is_complete()) {
path = fs::system_complete(path);
}
return path.native_file_string();
} catch(fs::filesystem_error & e) {
s_log.err("Unable to build path for %s: %s", id.c_str(), e.what());
return std::string();
}
/*$on*/
}
DataSource::IStreamPtr StdFileSys::doOpen(const std::string& id)
{
IStreamPtr is;
fs::path path(id, fs::native);
if (!path.is_complete()) {
std::string file = find(id);
if (file.empty()) {
return is;
}
path = fs::path(file, fs::native);
}
try {
is.reset(new fs::ifstream(path, std::ios::binary));
} catch (std::ios_base::failure &) {
is.reset();
}
if (is && !*is) {
is.reset();
}
if(!is) {
std::ostringstream os;
os << "Error opening " << id << " at " << path.string();
s_log.err(os.str());
}
return is;
}
}
}
}
#ifndef MENTICE_STYXBASE_BASE_FILESYS_H
#define MENTICE_STYXBASE_BASE_FILESYS_H
#include <base/base/bsNiftyCounter.h>
namespace mtc
{
namespace styx
{
namespace base
{
/** simple byte-buffer wrapper
*/
class STYXBASE_DECLSPEC Buffer
{
public:
Buffer(size_t size = 0);
~ Buffer();
void resize(size_t len) { m_data.resize(len); }
char* data() { return size() > 0 ? &m_data.front() : 0; }
size_t size() { return m_data.size(); }
std::string toString() {
return std::string(data(), size());
}
private:
std::vector<char> m_data;
};
STYXBASE_DECLSPEC std::istream& operator>>(std::istream &is, Buffer &buf);
STYXBASE_DECLSPEC std::ostream& operator<<(std::ostream &os, Buffer &buf);
// input data
class STYXBASE_DECLSPEC DataSource
{
public:
typedef boost::shared_ptr<std::istream> IStreamPtr;
virtual ~DataSource();
/// Data load (loads into buffer)
bool read(const std::string& id, Buffer& buf);
/// File lookup (returns path to file, may or may not be to local
filesystem)
std::string find(const std::string& id);
/// Data access (opens file, returns null if unsuccessful)
IStreamPtr open(const std::string& id);
protected:
virtual bool doRead(const std::string& id, Buffer& buf) = 0;
virtual std::string doFind(const std::string& id) = 0;
virtual IStreamPtr doOpen(const std::string& id) = 0;
};
/// FileSystem wrapper module
class STYXBASE_DECLSPEC FileSys : boost::noncopyable
{
public:
/** returns a proxy fwd to the currect global filesys
(StdFileSys is default)
*/
static DataSource& the();
/// sets the global filesystem, null objects are ignored
static void addDataSource(DataSource* ds);
static void subDataSource(DataSource* ds);
/// Retrieve temporary directory on this system
static std::string tempdir();
};
/// simple FileSys which uses std::istream
class STYXBASE_DECLSPEC StdFileSys :
public DataSource
{
protected:
/// Uses fopen(),fread()
virtual bool doRead(const std::string& id, Buffer& buf);
/// Returns the id wrapped as-is in a string
virtual std::string doFind(const std::string& id);
/// Opens file using ifstream
virtual IStreamPtr doOpen(const std::string& id);
};
/// @}
MTC_DECLARE_NIFTYCOUNTER(FileSysInit, STYXBASE_DECLSPEC);
/////////////////////////////////////////////////////////////////////////////
}
}
}
#endif
#include <stdafx.h>
#include <base/fw/fwZipDataSource.h>
#include <base/script/scpScriptClassImpl.h>
#include <base/base/bsLog.h>
#ifdef _DEBUG
#pragma message("Styx link to lib file: zipiosd.lib")
#pragma comment(lib, "zipiosd.lib")
#pragma message("Styx link to lib file: zlibd.lib")
#pragma comment(lib, "zlibd.lib")
#else
#pragma message("Styx link to lib file: zipios.lib")
#pragma comment(lib, "zipios.lib")
#pragma message("Styx link to lib file: zlib.lib")
#pragma comment(lib, "zlib.lib")
#endif
namespace mtc
{
namespace styx
{
namespace fw
{
namespace
{
base::LogDecorator s_log("ZipDataSource");
}
MTC_IMPLEMENT_SCRIPTABLE(ZipDataSource)
void ZipDataSource::initType(SCI& type)
{
type.attr("source").bind(setZipFile);
}
ZipDataSource::ZipDataSource()
{ }
ZipDataSource::~ZipDataSource()
{ }
void ZipDataSource::setZipFile(const std::string& file)
{
// if (IStreamPtr isp = base::FileSys::the().open(file)) {
//m_istream = isp;
//m_zipfile.reset(new zipios::ZipFile(*m_istream, "zip://" + file +
'/'));
if(true) {
m_zipfile.reset(new zipios::ZipFile(file));
if (m_zipfile->isValid()) {
s_log.info("Loaded zip %s with %i entries.", file.c_str(),
m_zipfile->size());
return;
}
s_log.err("Zip file %s not valid.", file.c_str());
m_zipfile.reset();
m_istream.reset();
} else {
s_log.err("Zip file %s not found.", file.c_str());
}
throw std::runtime_error("error loading zip file");
}
std::string ZipDataSource::doFind(const std::string& id)
{
if (m_zipfile) {
if (m_zipfile->getEntry(id) != 0) {
return m_zipfile->getName() + id;
}
}
return std::string();
}
ZipDataSource::IStreamPtr ZipDataSource::doOpen(const std::string& id)
{
if (m_zipfile) {
std::string zipfile = id.substr(0, m_zipfile->getName().size());
std::string zipentry = id.substr(m_zipfile->getName().size());
if (zipfile == m_zipfile->getName()) {
return IStreamPtr(m_zipfile->getInputStream(zipentry));
}
}
return IStreamPtr();
}
}
}
}
#ifndef MENTICE_STYXBASE_FW_ZIPDATASOURCE_H
#define MENTICE_STYXBASE_FW_ZIPDATASOURCE_H
#include <base/script/scpScriptObject.h>
#include <base/base/bsFileSys.h>
#undef IGNORE
#include <zipios++/zipfile.h>
namespace mtc
{
namespace styx
{
namespace fw
{
/// Calls update on updatables
class STYXBASE_DECLSPEC ZipDataSource :
public script::ScriptObject,
public base::StdFileSys
{
MTC_DECLARE_SCRIPTABLE(ZipDataSource, script::ScriptObject)
public:
ZipDataSource();
~ ZipDataSource();
void setZipFile(const std::string& zipfile);
protected:
virtual std::string doFind(const std::string& id);
virtual IStreamPtr doOpen(const std::string& id);
private:
std::string m_filename;
IStreamPtr m_istream;
boost::scoped_ptr<zipios::ZipFile> m_zipfile;
};
MTC_INITIALIZE_SCRIPTABLE(ZipDataSource)
}
}
}
#endif
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Opensg-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensg-users