Partial roll back VFS refactor due internal breakages
PiperOrigin-RevId: 862210191 Change-Id: Ia15a345a267bcef4b593d507d54f1668da0c0611
This commit is contained in:
committed by
Copybara-Service
parent
19ff06155a
commit
2fd9b5e92f
+27
-97
@@ -17,115 +17,45 @@
|
||||
#ifndef MUJOCO_SRC_USER_USER_VFS_H_
|
||||
#define MUJOCO_SRC_USER_USER_VFS_H_
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <mujoco/mjexport.h>
|
||||
#include <mujoco/mjmodel.h>
|
||||
#include <mujoco/mujoco.h>
|
||||
#include "user/user_util.h"
|
||||
#include <mujoco/mjplugin.h>
|
||||
|
||||
namespace mujoco::user {
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Underlying Virtual File System implementation for opaque mjVFS struct.
|
||||
//
|
||||
// This class owns and manages all the mjResource instances that are created
|
||||
// using the mju_openResource. Its main job is to find the correct
|
||||
// mjpResourceProvider to handle the mju open/read/close operations. It does
|
||||
// this by "mounting" mjpResourceProviders at specific paths such that any
|
||||
// operation within that path will be handled by the mjpResourceProvider.
|
||||
//
|
||||
// Mounting can be done explicitly (using mj_mountVFS) or implicitly (using
|
||||
// mjp_registerResourceProvider). If no provider is found for a given path,
|
||||
// then a "default" provider is used that uses normal C file operations to
|
||||
// open/read/close files.
|
||||
//
|
||||
// To support legacy use-cases (where the VFS is an optional argument), a
|
||||
// "self-destruct" mode can be configured so that a temporary VFS instance can
|
||||
// be created with a lifetime tied to the opened mjResource instance.
|
||||
//
|
||||
// This class itself is thread-safe, but it makes no guarantees about the
|
||||
// thread-safety of the underlying mjResourceProviders.
|
||||
class VFS {
|
||||
public:
|
||||
explicit VFS(mjVFS* vfs);
|
||||
~VFS();
|
||||
// Initialize an empty VFS, mj_deleteVFS must be called to deallocate the VFS
|
||||
MJAPI void mj_defaultVFS(mjVFS* vfs);
|
||||
|
||||
VFS(const VFS&) = delete;
|
||||
VFS& operator=(const VFS&) = delete;
|
||||
// add file to VFS, return 0: success, 2: repeated name, -1: not found on disk
|
||||
MJAPI int mj_addFileVFS(mjVFS* vfs, const char* directory, const char* filename);
|
||||
|
||||
// Status codes for VFS operations. Values are based on the mj_VFS APIs.
|
||||
enum Status {
|
||||
kSuccess = 0,
|
||||
kFailedToLoad = -1,
|
||||
kFailedToRead = -1,
|
||||
kNotFound = -1,
|
||||
kRepeatedName = 2,
|
||||
kInvalidVfs = -1,
|
||||
kInvalidResource = -1,
|
||||
kInvalidResourceProvider = -1,
|
||||
};
|
||||
// add file from buffer into VFS, return 0: success, 2: repeated name, -1: failed to load
|
||||
MJAPI int mj_addBufferVFS(mjVFS* vfs, const char* filename, const void* buffer, int nbuffer);
|
||||
|
||||
// Opens a mjResource for the given path, or nullptr on error. If successful,
|
||||
// will invoke the 'open' callback for the mjpResourceProvider associated with
|
||||
// the path/dir.
|
||||
mjResource* Open(const char* dir, const char* name);
|
||||
// mount a ResourceProvider to handle file operations under the given path; return 0: success,
|
||||
// 2: repeated name, -1: invalid resource provider
|
||||
MJAPI int mj_mountVFS(mjVFS* vfs, const char* filepath, const mjpResourceProvider* provider);
|
||||
|
||||
// Sets `buffer` to the contents of the resource and returns the number of
|
||||
// bytes of the content. This is done by invoking the 'read' callback for the
|
||||
// mjpResourceProvider associated with the resource. Returns -1 on error.
|
||||
int Read(mjResource* resource, const void** buffer);
|
||||
// unmount a previously mounted ResourceProvider; return 0: success, -1: not found in VFS
|
||||
MJAPI int mj_unmountVFS(mjVFS* vfs, const char* filename);
|
||||
|
||||
// Closes the resource by invoking the 'close' callback for the
|
||||
// mjpResourceProvider associated with the resource.
|
||||
Status Close(mjResource* resource);
|
||||
// return file index in VFS, or -1 if not found in VFS
|
||||
MJAPI int mj_findFileVFS(const mjVFS* vfs, const char* filename);
|
||||
|
||||
// Mounts a ResourceProvider at the given path. All subsequent operations
|
||||
// under `path` will be delegated to the `provider` until it is unmounted.
|
||||
Status Mount(const FilePath& path, const mjpResourceProvider* provider);
|
||||
// delete file from VFS, return 0: success, -1: not found in VFS
|
||||
MJAPI int mj_deleteFileVFS(mjVFS* vfs, const char* filename);
|
||||
|
||||
// Unmounts the ResourceProvider from the given path.
|
||||
Status Unmount(const FilePath& path);
|
||||
// delete all files from VFS
|
||||
MJAPI void mj_deleteVFS(mjVFS* vfs);
|
||||
|
||||
// Sets a destructor to be called when the VFS has no more open resources.
|
||||
// Assumes that `destructor` will delete `this`.
|
||||
//
|
||||
// This is useful for when you want to create a temporary VFS instance with
|
||||
// a lifetime tied to a single mjResource to be opened. The `destructor`
|
||||
// should be set to `delete this` and any other cleanup that needs to happen.
|
||||
void SetToSelfDestruct(std::function<void(mjVFS*)> destructor);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
// Converts the public C-API pointer to the internal C++ class.
|
||||
static VFS* Upcast(mjVFS* vfs);
|
||||
static const VFS* Upcast(const mjVFS* vfs);
|
||||
|
||||
private:
|
||||
using ResourcePtr = std::unique_ptr<mjResource, void (*)(mjResource*)>;
|
||||
ResourcePtr CreateResource(std::string_view name,
|
||||
const mjpResourceProvider* provider);
|
||||
|
||||
// Returns a mounted mjResource* that matches the given path. If no explicitly
|
||||
// mounted mjResource* is found, returns a "default" mounting that uses the
|
||||
// C file system.
|
||||
mjResource* FindMount(const std::string& fullpath);
|
||||
|
||||
// Invokes the `destructor_, but only if it has been set previously. This
|
||||
// should be only called when resources_ is empty and callers should assume
|
||||
// that `this` will be invalidated after this call.
|
||||
void MaybeSelfDestruct();
|
||||
|
||||
mjVFS* self_;
|
||||
std::mutex mutex_; // Protects open_resources_ and mounts_.
|
||||
std::unordered_map<mjResource*, ResourcePtr> open_resources_;
|
||||
std::unordered_map<std::string, ResourcePtr> mounts_;
|
||||
mjResource default_mount_;
|
||||
mjpResourceProvider default_provider_;
|
||||
std::function<void(mjVFS*)> destructor_;
|
||||
};
|
||||
|
||||
} // namespace mujoco::user
|
||||
const mjpResourceProvider* GetVfsResourceProvider();
|
||||
|
||||
#endif // MUJOCO_SRC_USER_USER_VFS_H_
|
||||
|
||||
Reference in New Issue
Block a user