seafile/common/fs-mgr.h
feiniks 8e0e9ce76b
Checkout file directly (#2781)
* Checkout file directly

Add download progress

Return error when cancel task

Check if usr is NULL when get notif server

Adjust code struct

Checkout file from offset

Don't use http task

Adjust function parameters

* Support set file_id attr to tmp file

* user error_id to check failed

---------

Co-authored-by: yangheran <heran.yang@seafile.com>
2024-07-03 16:46:58 +08:00

455 lines
14 KiB
C

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
#ifndef SEAF_FILE_MGR_H
#define SEAF_FILE_MGR_H
#include <glib.h>
#include "seafile-object.h"
#include "obj-store.h"
#include "cdc/cdc.h"
#include "../common/seafile-crypt.h"
#define CURRENT_DIR_OBJ_VERSION 1
#define CURRENT_SEAFILE_OBJ_VERSION 1
#define CDC_AVERAGE_BLOCK_SIZE (1 << 23) /* 8MB */
#define CDC_MIN_BLOCK_SIZE (6 * (1 << 20)) /* 6MB */
#define CDC_MAX_BLOCK_SIZE (10 * (1 << 20)) /* 10MB */
#define SEAF_TMP_EXT "~"
#define SEAFILE_FILE_ID_ATTR "user.file-id"
typedef struct _SeafFSManager SeafFSManager;
typedef struct _SeafFSObject SeafFSObject;
typedef struct _Seafile Seafile;
typedef struct _SeafDir SeafDir;
typedef struct _SeafDirent SeafDirent;
typedef enum {
SEAF_METADATA_TYPE_INVALID,
SEAF_METADATA_TYPE_FILE,
SEAF_METADATA_TYPE_LINK,
SEAF_METADATA_TYPE_DIR,
} SeafMetadataType;
/* Common to seafile and seafdir objects. */
struct _SeafFSObject {
int type;
};
struct _Seafile {
SeafFSObject object;
int version;
char file_id[41];
guint64 file_size;
guint32 n_blocks;
char **blk_sha1s;
int ref_count;
};
void
seafile_ref (Seafile *seafile);
void
seafile_unref (Seafile *seafile);
int
seafile_save (SeafFSManager *fs_mgr,
const char *repo_id,
int version,
Seafile *file);
#define SEAF_DIR_NAME_LEN 256
struct _SeafDirent {
int version;
guint32 mode;
char id[41];
guint32 name_len;
char *name;
/* attributes for version > 0 */
gint64 mtime;
char *modifier; /* for files only */
gint64 size; /* for files only */
};
struct _SeafDir {
SeafFSObject object;
int version;
char dir_id[41];
GList *entries;
/* data in on-disk format. */
void *ondisk;
int ondisk_size;
};
SeafDir *
seaf_dir_new (const char *id, GList *entries, int version);
void
seaf_dir_free (SeafDir *dir);
SeafDir *
seaf_dir_from_data (const char *dir_id, uint8_t *data, int len,
gboolean is_json);
void *
seaf_dir_to_data (SeafDir *dir, int *len);
int
seaf_dir_save (SeafFSManager *fs_mgr,
const char *repo_id,
int version,
SeafDir *dir);
SeafDirent *
seaf_dirent_new (int version, const char *sha1, int mode, const char *name,
gint64 mtime, const char *modifier, gint64 size);
void
seaf_dirent_free (SeafDirent *dent);
SeafDirent *
seaf_dirent_dup (SeafDirent *dent);
int
seaf_metadata_type_from_data (const char *obj_id,
uint8_t *data, int len, gboolean is_json);
/* Parse an fs object without knowing its type. */
SeafFSObject *
seaf_fs_object_from_data (const char *obj_id,
uint8_t *data, int len,
gboolean is_json);
void
seaf_fs_object_free (SeafFSObject *obj);
typedef struct {
/* TODO: GHashTable may be inefficient when we have large number of IDs. */
GHashTable *block_hash;
GPtrArray *block_ids;
uint32_t n_blocks;
uint32_t n_valid_blocks;
} BlockList;
BlockList *
block_list_new ();
void
block_list_free (BlockList *bl);
void
block_list_insert (BlockList *bl, const char *block_id);
/* Return a blocklist containing block ids which are in @bl1 but
* not in @bl2.
*/
BlockList *
block_list_difference (BlockList *bl1, BlockList *bl2);
struct _SeafileSession;
typedef struct _SeafFSManagerPriv SeafFSManagerPriv;
struct _SeafFSManager {
struct _SeafileSession *seaf;
struct SeafObjStore *obj_store;
SeafFSManagerPriv *priv;
};
SeafFSManager *
seaf_fs_manager_new (struct _SeafileSession *seaf,
const char *seaf_dir);
int
seaf_fs_manager_init (SeafFSManager *mgr);
#ifndef SEAFILE_SERVER
struct _CheckoutBlockAux {
const char *repo_id;
const char *host;
const char *token;
gboolean use_fileserver_port;
void *task;
};
typedef struct _CheckoutBlockAux CheckoutBlockAux;
void
free_checkout_block_aux (CheckoutBlockAux *aux);
typedef int (*CheckoutBlockCallback) (const char *, const char *, int, SeafileCrypt *, CheckoutBlockAux *);
struct _FileCheckoutData {
const char *repo_id;
int version;
const char *file_id;
const char *file_path;
guint32 mode;
guint64 mtime;
struct SeafileCrypt *crypt;
const char *in_repo_path;
const char *conflict_head_id;
gboolean force_conflict;
gboolean *conflicted;
const char *email;
gint64 skip_buffer_size;
int block_offset;
};
typedef struct _FileCheckoutData FileCheckoutData;
int
seaf_fs_manager_checkout_file (SeafFSManager *mgr,
FileCheckoutData *data,
int *error_id,
CheckoutBlockCallback callback,
CheckoutBlockAux *user_data);
#endif /* not SEAFILE_SERVER */
/**
* Check in blocks and create seafile/symlink object.
* Returns sha1 id for the seafile/symlink object in @sha1 parameter.
*/
int
seaf_fs_manager_index_file_blocks (SeafFSManager *mgr,
const char *repo_id,
int version,
GList *paths,
GList *blockids,
unsigned char sha1[],
gint64 file_size);
int
seaf_fs_manager_index_raw_blocks (SeafFSManager *mgr,
const char *repo_id,
int version,
GList *paths,
GList *blockids);
int
seaf_fs_manager_index_existed_file_blocks (SeafFSManager *mgr,
const char *repo_id,
int version,
GList *blockids,
unsigned char sha1[],
gint64 file_size);
int
seaf_fs_manager_index_blocks (SeafFSManager *mgr,
const char *repo_id,
int version,
const char *file_path,
unsigned char sha1[],
gint64 *size,
SeafileCrypt *crypt,
gboolean write_data,
gboolean use_cdc);
Seafile *
seaf_fs_manager_get_seafile (SeafFSManager *mgr,
const char *repo_id,
int version,
const char *file_id);
SeafDir *
seaf_fs_manager_get_seafdir (SeafFSManager *mgr,
const char *repo_id,
int version,
const char *dir_id);
/* Make sure entries in the returned dir is sorted in descending order.
*/
SeafDir *
seaf_fs_manager_get_seafdir_sorted (SeafFSManager *mgr,
const char *repo_id,
int version,
const char *dir_id);
SeafDir *
seaf_fs_manager_get_seafdir_sorted_by_path (SeafFSManager *mgr,
const char *repo_id,
int version,
const char *root_id,
const char *path);
int
seaf_fs_manager_populate_blocklist (SeafFSManager *mgr,
const char *repo_id,
int version,
const char *root_id,
BlockList *bl);
/*
* For dir object, set *stop to TRUE to stop traversing the subtree.
*/
typedef gboolean (*TraverseFSTreeCallback) (SeafFSManager *mgr,
const char *repo_id,
int version,
const char *obj_id,
int type,
void *user_data,
gboolean *stop);
int
seaf_fs_manager_traverse_tree (SeafFSManager *mgr,
const char *repo_id,
int version,
const char *root_id,
TraverseFSTreeCallback callback,
void *user_data,
gboolean skip_errors);
typedef gboolean (*TraverseFSPathCallback) (SeafFSManager *mgr,
const char *path,
SeafDirent *dent,
void *user_data,
gboolean *stop);
int
seaf_fs_manager_traverse_path (SeafFSManager *mgr,
const char *repo_id,
int version,
const char *root_id,
const char *dir_path,
TraverseFSPathCallback callback,
void *user_data);
gboolean
seaf_fs_manager_object_exists (SeafFSManager *mgr,
const char *repo_id,
int version,
const char *id);
void
seaf_fs_manager_delete_object (SeafFSManager *mgr,
const char *repo_id,
int version,
const char *id);
gint64
seaf_fs_manager_get_file_size (SeafFSManager *mgr,
const char *repo_id,
int version,
const char *file_id);
gint64
seaf_fs_manager_get_fs_size (SeafFSManager *mgr,
const char *repo_id,
int version,
const char *root_id);
#ifndef SEAFILE_SERVER
int
seafile_write_chunk (const char *repo_id,
int version,
CDCDescriptor *chunk,
SeafileCrypt *crypt,
uint8_t *checksum,
gboolean write_data);
int
seafile_check_write_chunk (CDCDescriptor *chunk,
uint8_t *sha1,
gboolean write_data);
#endif /* SEAFILE_SERVER */
uint32_t
calculate_chunk_size (uint64_t total_size);
int
seaf_fs_manager_count_fs_files (SeafFSManager *mgr,
const char *repo_id,
int version,
const char *root_id);
SeafDir *
seaf_fs_manager_get_seafdir_by_path(SeafFSManager *mgr,
const char *repo_id,
int version,
const char *root_id,
const char *path,
GError **error);
char *
seaf_fs_manager_get_seafile_id_by_path (SeafFSManager *mgr,
const char *repo_id,
int version,
const char *root_id,
const char *path,
GError **error);
char *
seaf_fs_manager_path_to_obj_id (SeafFSManager *mgr,
const char *repo_id,
int version,
const char *root_id,
const char *path,
guint32 *mode,
GError **error);
char *
seaf_fs_manager_get_seafdir_id_by_path (SeafFSManager *mgr,
const char *repo_id,
int version,
const char *root_id,
const char *path,
GError **error);
SeafDirent *
seaf_fs_manager_get_dirent_by_path (SeafFSManager *mgr,
const char *repo_id,
int version,
const char *root_id,
const char *path,
GError **error);
/* Check object integrity. */
gboolean
seaf_fs_manager_verify_seafdir (SeafFSManager *mgr,
const char *repo_id,
int version,
const char *dir_id,
gboolean verify_id,
gboolean *io_error);
gboolean
seaf_fs_manager_verify_seafile (SeafFSManager *mgr,
const char *repo_id,
int version,
const char *file_id,
gboolean verify_id,
gboolean *io_error);
gboolean
seaf_fs_manager_verify_object (SeafFSManager *mgr,
const char *repo_id,
int version,
const char *obj_id,
gboolean verify_id,
gboolean *io_error);
int
dir_version_from_repo_version (int repo_version);
int
seafile_version_from_repo_version (int repo_version);
struct _CDCFileDescriptor;
void
seaf_fs_manager_calculate_seafile_id_json (int repo_version,
struct _CDCFileDescriptor *cdc,
guint8 *file_id_sha1);
int
seaf_fs_manager_remove_store (SeafFSManager *mgr,
const char *store_id);
#endif