Skip to content

Commit d36854b

Browse files
authored
Merge pull request #201 from haiwen/support_byte_range_upload
Add byte-range upload.
2 parents 5c8c640 + d851199 commit d36854b

File tree

10 files changed

+672
-82
lines changed

10 files changed

+672
-82
lines changed

common/rpc-service.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5293,6 +5293,33 @@ seafile_org_get_shared_users_by_repo (int org_id,
52935293
org_id, repo_id);
52945294
}
52955295

5296+
/* Resumable file upload. */
5297+
5298+
gint64
5299+
seafile_get_upload_tmp_file_offset (const char *repo_id, const char *file_path,
5300+
GError **error)
5301+
{
5302+
if (!repo_id || !is_uuid_valid(repo_id)) {
5303+
g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
5304+
"Invalid repo id");
5305+
return -1;
5306+
}
5307+
5308+
int path_len;
5309+
if (!file_path || (path_len = strlen(file_path)) == 0) {
5310+
g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
5311+
"Invalid file path");
5312+
return -1;
5313+
}
5314+
5315+
char *rfile_path = format_dir_path (file_path);
5316+
gint64 ret = seaf_repo_manager_get_upload_tmp_file_offset (seaf->repo_mgr, repo_id,
5317+
rfile_path, error);
5318+
g_free (rfile_path);
5319+
5320+
return ret;
5321+
}
5322+
52965323
char *
52975324
seafile_convert_repo_path (const char *repo_id,
52985325
const char *path,

include/seafile-rpc.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1103,6 +1103,10 @@ seafile_org_get_shared_users_by_repo (int org_id,
11031103
const char *repo_id,
11041104
GError **error);
11051105

1106+
gint64
1107+
seafile_get_upload_tmp_file_offset (const char *repo_id, const char *file_path,
1108+
GError **error);
1109+
11061110
char *
11071111
seafile_convert_repo_path (const char *repo_id,
11081112
const char *path,

python/seafile/rpcclient.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -989,6 +989,11 @@ def get_file_count_info_by_path(repo_id, path):
989989
def get_trash_repo_owner(repo_id):
990990
pass
991991

992+
@searpc_func("int64", ["string", "string"])
993+
def seafile_get_upload_tmp_file_offset(repo_id, file_path):
994+
pass
995+
get_upload_tmp_file_offset = seafile_get_upload_tmp_file_offset
996+
992997
@searpc_func("int", ["string", "string", "string", "string"])
993998
def seafile_mkdir_with_parents (repo_id, parent_dir, relative_path, username):
994999
pass

python/seaserv/api.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,9 @@ def set_repo_history_limit(self, repo_id, days):
383383
def check_repo_blocks_missing(self, repo_id, blklist):
384384
return seafserv_threaded_rpc.check_repo_blocks_missing(repo_id, blklist)
385385

386+
def get_upload_tmp_file_offset (self, repo_id, file_path):
387+
return seafserv_threaded_rpc.get_upload_tmp_file_offset (repo_id, file_path)
388+
386389
# file lock
387390
def check_file_lock(self, repo_id, path, user):
388391
"""

server/http-server.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#define DEFAULT_MAX_INDEXING_THREADS 1
3636
#define DEFAULT_MAX_INDEX_PROCESSING_THREADS 3
3737
#define DEFAULT_FIXED_BLOCK_SIZE ((gint64)1 << 23) /* 8MB */
38+
#define DEFAULT_CLUSTER_SHARED_TEMP_FILE_MODE 0600
3839

3940
#define HOST "host"
4041
#define PORT "port"
@@ -130,6 +131,7 @@ load_http_config (HttpServerStruct *htp_server, SeafileSession *session)
130131
char *encoding;
131132
int max_indexing_threads;
132133
int max_index_processing_threads;
134+
char *cluster_shared_temp_file_mode = NULL;
133135

134136
host = fileserver_config_get_string (session->config, HOST, &error);
135137
if (!error) {
@@ -232,6 +234,28 @@ load_http_config (HttpServerStruct *htp_server, SeafileSession *session)
232234
seaf_message ("fileserver: max_index_processing_threads= %d\n",
233235
htp_server->max_index_processing_threads);
234236

237+
cluster_shared_temp_file_mode = fileserver_config_get_string (session->config,
238+
"cluster_shared_temp_file_mode",
239+
&error);
240+
if (error) {
241+
htp_server->cluster_shared_temp_file_mode = DEFAULT_CLUSTER_SHARED_TEMP_FILE_MODE;
242+
g_clear_error (&error);
243+
} else {
244+
if (!cluster_shared_temp_file_mode) {
245+
htp_server->cluster_shared_temp_file_mode = DEFAULT_CLUSTER_SHARED_TEMP_FILE_MODE;
246+
} else {
247+
htp_server->cluster_shared_temp_file_mode = strtol(cluster_shared_temp_file_mode, NULL, 8);
248+
249+
if (htp_server->cluster_shared_temp_file_mode < 0001 ||
250+
htp_server->cluster_shared_temp_file_mode > 0777)
251+
htp_server->cluster_shared_temp_file_mode = DEFAULT_CLUSTER_SHARED_TEMP_FILE_MODE;
252+
253+
g_free (cluster_shared_temp_file_mode);
254+
}
255+
}
256+
seaf_message ("fileserver: cluster_shared_temp_file_mode = %o\n",
257+
htp_server->cluster_shared_temp_file_mode);
258+
235259
encoding = g_key_file_get_string (session->config,
236260
"zip", "windows_encoding",
237261
&error);

server/http-server.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ struct _HttpServerStruct {
2121
int max_indexing_threads;
2222
int worker_threads;
2323
int max_index_processing_threads;
24+
int cluster_shared_temp_file_mode;
2425
};
2526

2627
typedef struct _HttpServerStruct HttpServerStruct;

server/repo-mgr.c

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,6 +1058,12 @@ create_tables_mysql (SeafRepoManager *mgr)
10581058
if (seaf_db_query (db, sql) < 0)
10591059
return -1;
10601060

1061+
sql = "CREATE TABLE IF NOT EXISTS WebUploadTempFiles ( "
1062+
"id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT, repo_id CHAR(40) NOT NULL, "
1063+
"file_path TEXT NOT NULL, tmp_file_path TEXT NOT NULL) ENGINE=INNODB";
1064+
if (seaf_db_query (db, sql) < 0)
1065+
return -1;
1066+
10611067
return 0;
10621068
}
10631069

@@ -1206,6 +1212,11 @@ create_tables_sqlite (SeafRepoManager *mgr)
12061212
if (seaf_db_query (db, sql) < 0)
12071213
return -1;
12081214

1215+
sql = "CREATE TABLE IF NOT EXISTS WebUploadTempFiles (repo_id CHAR(40) NOT NULL, "
1216+
"file_path TEXT NOT NULL, tmp_file_path TEXT NOT NULL)";
1217+
if (seaf_db_query (db, sql) < 0)
1218+
return -1;
1219+
12091220
return 0;
12101221
}
12111222

@@ -1344,6 +1355,11 @@ create_tables_pgsql (SeafRepoManager *mgr)
13441355
if (seaf_db_query (db, sql) < 0)
13451356
return -1;
13461357

1358+
sql = "CREATE TABLE IF NOT EXISTS WebUploadTempFiles (repo_id CHAR(40) NOT NULL, "
1359+
"file_path TEXT NOT NULL, tmp_file_path TEXT NOT NULL)";
1360+
if (seaf_db_query (db, sql) < 0)
1361+
return -1;
1362+
13471363
sql = "CREATE TABLE IF NOT EXISTS RepoInfo (repo_id CHAR(36) PRIMARY KEY, "
13481364
"name VARCHAR(255) NOT NULL, update_time BIGINT, version INTEGER, "
13491365
"is_encrypted INTEGER, last_modifier VARCHAR(255))";
@@ -3918,6 +3934,119 @@ seaf_get_total_storage (GError **error)
39183934
return size;
39193935
}
39203936

3937+
int
3938+
seaf_repo_manager_add_upload_tmp_file (SeafRepoManager *mgr,
3939+
const char *repo_id,
3940+
const char *file_path,
3941+
const char *tmp_file,
3942+
GError **error)
3943+
{
3944+
int ret = seaf_db_statement_query (mgr->seaf->db,
3945+
"INSERT INTO WebUploadTempFiles "
3946+
"(repo_id, file_path, tmp_file_path) "
3947+
"VALUES (?, ?, ?)", 3, "string", repo_id,
3948+
"string", file_path, "string", tmp_file);
3949+
3950+
if (ret < 0) {
3951+
g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
3952+
"Failed to add upload tmp file record to db.");
3953+
}
3954+
3955+
return ret;
3956+
}
3957+
3958+
int
3959+
seaf_repo_manager_del_upload_tmp_file (SeafRepoManager *mgr,
3960+
const char *repo_id,
3961+
const char *file_path,
3962+
GError **error)
3963+
{
3964+
int ret = seaf_db_statement_query (mgr->seaf->db,
3965+
"DELETE FROM WebUploadTempFiles WHERE "
3966+
"repo_id = ? AND file_path = ?",
3967+
2, "string", repo_id, "string", file_path);
3968+
if (ret < 0) {
3969+
g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
3970+
"Failed to delete upload tmp file record from db.");
3971+
}
3972+
3973+
return ret;
3974+
}
3975+
3976+
static gboolean
3977+
get_tmp_file_path (SeafDBRow *row, void *data)
3978+
{
3979+
char **path = data;
3980+
3981+
*path = g_strdup (seaf_db_row_get_column_text (row, 0));
3982+
3983+
return FALSE;
3984+
}
3985+
3986+
char *
3987+
seaf_repo_manager_get_upload_tmp_file (SeafRepoManager *mgr,
3988+
const char *repo_id,
3989+
const char *file_path,
3990+
GError **error)
3991+
{
3992+
char *tmp_file_path = NULL;
3993+
3994+
int ret = seaf_db_statement_foreach_row (mgr->seaf->db,
3995+
"SELECT tmp_file_path FROM WebUploadTempFiles "
3996+
"WHERE repo_id = ? AND file_path = ?",
3997+
get_tmp_file_path, &tmp_file_path,
3998+
2, "string", repo_id, "string", file_path);
3999+
if (ret < 0) {
4000+
g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
4001+
"Failed to get upload temp file path from db.");
4002+
return NULL;
4003+
}
4004+
4005+
return tmp_file_path;
4006+
}
4007+
4008+
gint64
4009+
seaf_repo_manager_get_upload_tmp_file_offset (SeafRepoManager *mgr,
4010+
const char *repo_id,
4011+
const char *file_path,
4012+
GError **error)
4013+
{
4014+
char *tmp_file_path = NULL;
4015+
SeafStat file_stat;
4016+
4017+
tmp_file_path = seaf_repo_manager_get_upload_tmp_file (mgr, repo_id,
4018+
file_path, error);
4019+
if (*error) {
4020+
return -1;
4021+
}
4022+
4023+
if (!tmp_file_path)
4024+
return 0;
4025+
4026+
if (seaf_stat (tmp_file_path, &file_stat) < 0) {
4027+
if (errno == ENOENT) {
4028+
seaf_message ("Temp file %s doesn't exist, remove reocrd from db.\n",
4029+
tmp_file_path);
4030+
if (seaf_repo_manager_del_upload_tmp_file (mgr, repo_id,
4031+
file_path, error) < 0) {
4032+
g_free (tmp_file_path);
4033+
return -1;
4034+
}
4035+
return 0;
4036+
}
4037+
seaf_warning ("Failed to stat temp file %s: %s.\n",
4038+
tmp_file_path, strerror(errno));
4039+
g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
4040+
"Failed to stat temp file.");
4041+
g_free (tmp_file_path);
4042+
return -1;
4043+
}
4044+
4045+
g_free (tmp_file_path);
4046+
4047+
return file_stat.st_size;
4048+
}
4049+
39214050
void
39224051
seaf_repo_manager_update_repo_info (SeafRepoManager *mgr,
39234052
const char *repo_id, const char *head_commit_id)

server/repo-mgr.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,31 @@ seaf_get_total_file_number (GError **error);
818818
gint64
819819
seaf_get_total_storage (GError **error);
820820

821+
int
822+
seaf_repo_manager_add_upload_tmp_file (SeafRepoManager *mgr,
823+
const char *repo_id,
824+
const char *file_path,
825+
const char *tmp_file,
826+
GError **error);
827+
828+
int
829+
seaf_repo_manager_del_upload_tmp_file (SeafRepoManager *mgr,
830+
const char *repo_id,
831+
const char *file_path,
832+
GError **error);
833+
834+
char *
835+
seaf_repo_manager_get_upload_tmp_file (SeafRepoManager *mgr,
836+
const char *repo_id,
837+
const char *file_path,
838+
GError **error);
839+
840+
gint64
841+
seaf_repo_manager_get_upload_tmp_file_offset (SeafRepoManager *mgr,
842+
const char *repo_id,
843+
const char *file_path,
844+
GError **error);
845+
821846
void
822847
seaf_repo_manager_update_repo_info (SeafRepoManager *mgr,
823848
const char *repo_id,

server/seaf-server.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,11 @@ static void start_rpc_service (CcnetClient *client, int cloud_mode)
587587
"get_virtual_repo",
588588
searpc_signature_object__string_string_string());
589589

590+
searpc_server_register_function ("seafserv-threaded-rpcserver",
591+
seafile_get_upload_tmp_file_offset,
592+
"seafile_get_upload_tmp_file_offset",
593+
searpc_signature_int64__string_string());
594+
590595
/* Clean trash */
591596

592597
searpc_server_register_function ("seafserv-threaded-rpcserver",

0 commit comments

Comments
 (0)