Skip to content

Commit d944ded

Browse files
author
virco
committed
improvements
1 parent bd1f418 commit d944ded

File tree

6 files changed

+183
-67
lines changed

6 files changed

+183
-67
lines changed

pdiff.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,7 @@ static void process_deletefolder(const binresult *entry){
747747
}
748748
meta=psync_find_result(entry, "metadata", PARAM_HASH);
749749
folderid=psync_find_result(meta, "folderid", PARAM_NUM)->num;
750+
psync_path_status_folder_deleted(folderid);
750751
if (psync_is_folder_in_downloadlist(folderid)){
751752
psync_del_folder_from_downloadlist(folderid);
752753
res=psync_sql_query("SELECT syncid, localfolderid FROM syncedfolder WHERE folderid=?");
@@ -773,7 +774,6 @@ static void process_deletefolder(const binresult *entry){
773774
psync_sql_run(st2);
774775
psync_fs_folder_deleted(folderid);
775776
}
776-
psync_path_status_del_from_parent_cache(folderid);
777777
}
778778

779779
static void check_for_deletedfileid(const binresult *meta){

plibs.c

Lines changed: 87 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@ struct run_after_ptr {
4949
void *ptr;
5050
};
5151

52+
typedef struct {
53+
psync_list list;
54+
psync_transaction_callback_t commit_callback;
55+
psync_transaction_callback_t rollback_callback;
56+
void *ptr;
57+
} tran_callback_t;
58+
5259
static const uint8_t __hex_lookupl[513]={
5360
"000102030405060708090a0b0c0d0e0f"
5461
"101112131415161718191a1b1c1d1e1f"
@@ -113,6 +120,10 @@ PSYNC_THREAD uint32_t psync_error=0;
113120

114121
static pthread_mutex_t psync_db_checkpoint_mutex;
115122

123+
static int in_transaction=0;
124+
static int transaction_failed=0;
125+
static psync_list tran_callbacks;
126+
116127

117128
char *psync_strdup(const char *str){
118129
size_t len;
@@ -761,30 +772,72 @@ int psync_sql_statement(const char *sql){
761772

762773
#if IS_DEBUG
763774
int psync_sql_do_start_transaction(const char *file, unsigned line){
775+
psync_sql_res *res;
764776
psync_sql_do_lock(file, line);
765-
if (unlikely(psync_sql_do_statement("BEGIN", file, line))){
777+
res=psync_sql_do_prep_statement("BEGIN", file, line);
766778
#else
767779
int psync_sql_start_transaction(){
780+
psync_sql_res *res;
768781
psync_sql_lock();
769-
if (unlikely(psync_sql_statement("BEGIN"))){
782+
res=psync_sql_prep_statement("BEGIN");
770783
#endif
771-
psync_sql_unlock();
784+
assert(!in_transaction);
785+
if (unlikely(!res || psync_sql_run_free(res)))
772786
return -1;
787+
in_transaction=1;
788+
transaction_failed=0;
789+
psync_list_init(&tran_callbacks);
790+
return 0;
791+
}
792+
793+
static void run_commit_callbacks(int success){
794+
tran_callback_t *cb;
795+
psync_list *l1, *l2;
796+
psync_list_for_each_safe(l1, l2, &tran_callbacks) {
797+
cb=psync_list_element(l1, tran_callback_t, list);
798+
if (success)
799+
cb->commit_callback(cb->ptr);
800+
else
801+
cb->rollback_callback(cb->ptr);
802+
psync_free(cb);
773803
}
774-
else
775-
return 0;
776804
}
777805

778806
int psync_sql_commit_transaction(){
779-
int code=psync_sql_statement("COMMIT");
780-
psync_sql_unlock();
781-
return code;
807+
assert(in_transaction);
808+
if (likely(!transaction_failed)){
809+
psync_sql_res *res=psync_sql_prep_statement("COMMIT");
810+
if (likely(!psync_sql_run_free(res))){
811+
run_commit_callbacks(1);
812+
in_transaction=0;
813+
psync_sql_unlock();
814+
return 0;
815+
}
816+
}
817+
else
818+
debug(D_NOTICE, "rolling back transaction as some statements failed");
819+
psync_sql_rollback_transaction();
820+
return -1;
782821
}
783822

784823
int psync_sql_rollback_transaction(){
785-
int code=psync_sql_statement("ROLLBACK");
824+
psync_sql_res *res=psync_sql_prep_statement("ROLLBACK");
825+
assert(in_transaction);
826+
psync_sql_run_free(res);
827+
run_commit_callbacks(0);
828+
in_transaction=0;
786829
psync_sql_unlock();
787-
return code;
830+
return 0;
831+
}
832+
833+
void psync_sql_transation_add_callbacks(psync_transaction_callback_t commit_callback, psync_transaction_callback_t rollback_callback, void *ptr){
834+
tran_callback_t *cb;
835+
assert(in_transaction);
836+
cb=psync_new(tran_callback_t);
837+
cb->commit_callback=commit_callback;
838+
cb->rollback_callback=rollback_callback;
839+
cb->ptr=ptr;
840+
psync_list_add_tail(&tran_callbacks, &cb->list);
788841
}
789842

790843
#if IS_DEBUG && 0
@@ -1315,41 +1368,58 @@ psync_sql_res *psync_sql_prep_statement(const char *sql){
13151368
#endif
13161369
}
13171370

1318-
void psync_sql_reset(psync_sql_res *res){
1371+
int psync_sql_reset(psync_sql_res *res){
13191372
int code=sqlite3_reset(res->stmt);
1320-
if (unlikely(code!=SQLITE_OK))
1373+
if (unlikely(code!=SQLITE_OK)){
13211374
debug(D_ERROR, "sqlite3_reset returned error: %s", sqlite3_errmsg(psync_db));
1375+
return -1;
1376+
}
1377+
else
1378+
return 0;
13221379
}
13231380

1324-
void psync_sql_run(psync_sql_res *res){
1381+
int psync_sql_run(psync_sql_res *res){
13251382
int code=sqlite3_step(res->stmt);
1326-
if (unlikely(code!=SQLITE_DONE))
1383+
if (unlikely(code!=SQLITE_DONE)){
13271384
debug(D_ERROR, "sqlite3_step returned error: %s: %s", sqlite3_errmsg(psync_db), res->sql);
1385+
transaction_failed=1;
1386+
return -1;
1387+
}
13281388
code=sqlite3_reset(res->stmt);
13291389
if (unlikely(code!=SQLITE_OK))
13301390
debug(D_ERROR, "sqlite3_reset returned error: %s", sqlite3_errmsg(psync_db));
1391+
return 0;
13311392
}
13321393

1333-
void psync_sql_run_free_nocache(psync_sql_res *res){
1394+
int psync_sql_run_free_nocache(psync_sql_res *res){
13341395
int code=sqlite3_step(res->stmt);
1335-
if (unlikely(code!=SQLITE_DONE))
1396+
if (unlikely(code!=SQLITE_DONE)){
13361397
debug(D_ERROR, "sqlite3_step returned error: %s: %s", sqlite3_errmsg(psync_db), res->sql);
1398+
code=-1;
1399+
transaction_failed=1;
1400+
}
1401+
else
1402+
code=0;
13371403
sqlite3_finalize(res->stmt);
13381404
psync_sql_res_unlock(res);
13391405
psync_free(res);
1406+
return code;
13401407
}
13411408

1342-
void psync_sql_run_free(psync_sql_res *res){
1409+
int psync_sql_run_free(psync_sql_res *res){
13431410
int code=sqlite3_step(res->stmt);
13441411
if (unlikely(code!=SQLITE_DONE || (code=sqlite3_reset(res->stmt))!=SQLITE_OK)){
13451412
debug(D_ERROR, "sqlite3_step returned error: %s: %s", sqlite3_errmsg(psync_db), res->sql);
13461413
sqlite3_finalize(res->stmt);
1414+
transaction_failed=1;
13471415
psync_sql_res_unlock(res);
13481416
psync_free(res);
1417+
return -1;
13491418
}
13501419
else{
13511420
psync_sql_res_unlock(res);
13521421
psync_cache_add(res->sql, res, PSYNC_QUERY_CACHE_SEC, psync_sql_free_cache, PSYNC_QUERY_MAX_CNT);
1422+
return 0;
13531423
}
13541424
}
13551425

plibs.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,9 @@ typedef int (*psync_list_builder_sql_callback)(psync_list_builder_t *, void *, p
181181

182182
typedef void (*psync_task_callback_t)(void *, void *);
183183

184+
185+
typedef void (*psync_transaction_callback_t)(void *);
186+
184187
extern int psync_do_run;
185188
extern int psync_recache_contacts;
186189
extern pstatus_t psync_status;
@@ -274,14 +277,16 @@ int psync_sql_sync();
274277
int psync_sql_commit_transaction();
275278
int psync_sql_rollback_transaction();
276279

280+
void psync_sql_transation_add_callbacks(psync_transaction_callback_t commit_callback, psync_transaction_callback_t rollback_callback, void *ptr);
281+
277282
char *psync_sql_cellstr(const char *sql) PSYNC_NONNULL(1);
278283
int64_t psync_sql_cellint(const char *sql, int64_t dflt) PSYNC_NONNULL(1);
279284
char **psync_sql_rowstr(const char *sql) PSYNC_NONNULL(1);
280285
psync_variant *psync_sql_row(const char *sql) PSYNC_NONNULL(1);
281-
void psync_sql_reset(psync_sql_res *res) PSYNC_NONNULL(1);
282-
void psync_sql_run(psync_sql_res *res) PSYNC_NONNULL(1);
283-
void psync_sql_run_free(psync_sql_res *res) PSYNC_NONNULL(1);
284-
void psync_sql_run_free_nocache(psync_sql_res *res) PSYNC_NONNULL(1);
286+
int psync_sql_reset(psync_sql_res *res) PSYNC_NONNULL(1);
287+
int psync_sql_run(psync_sql_res *res) PSYNC_NONNULL(1);
288+
int psync_sql_run_free(psync_sql_res *res) PSYNC_NONNULL(1);
289+
int psync_sql_run_free_nocache(psync_sql_res *res) PSYNC_NONNULL(1);
285290
void psync_sql_bind_uint(psync_sql_res *res, int n, uint64_t val) PSYNC_NONNULL(1);
286291
void psync_sql_bind_int(psync_sql_res *res, int n, int64_t val) PSYNC_NONNULL(1);
287292
void psync_sql_bind_double(psync_sql_res *res, int n, double val) PSYNC_NONNULL(1);

ppathstatus.c

Lines changed: 62 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,12 @@ typedef struct {
8080
path_sync_list_entry_t syncs[];
8181
} path_sync_list_t;
8282

83+
typedef struct {
84+
psync_folderid_t folderid;
85+
psync_folderid_t old_parent_folderid;
86+
psync_folderid_t new_parent_folderid;
87+
} folder_moved_params_t;
88+
8389
static char *drive_path=NULL;
8490
static size_t drive_path_len;
8591
static path_sync_list_t *syncs=NULL;
@@ -244,6 +250,8 @@ static psync_folderid_t get_parent_folder(psync_folderid_t folderid) {
244250
psync_uint_row row;
245251
parent_cache_entry_t *p;
246252
uint32_t h;
253+
if (folderid==0)
254+
return PSYNC_INVALID_FOLDERID;
247255
h=hash_folderid(folderid)%PARENT_HASH_SIZE;
248256
psync_list_for_each_element (p, &parent_cache_hash[h], parent_cache_entry_t, list_hash)
249257
if (p->folderid==folderid) {
@@ -255,9 +263,9 @@ static psync_folderid_t get_parent_folder(psync_folderid_t folderid) {
255263
psync_sql_bind_uint(res, 1, folderid);
256264
row=psync_sql_fetch_rowint(res);
257265
if (unlikely(!row)) {
258-
debug(D_ERROR, "can not find parent folder for folderid %lu", (unsigned long)folderid);
266+
debug(D_WARNING, "can not find parent folder for folderid %lu", (unsigned long)folderid);
259267
psync_sql_free_result(res);
260-
return 0;
268+
return PSYNC_INVALID_FOLDERID;
261269
}
262270
p=psync_list_remove_head_element(&parent_cache_lru, parent_cache_entry_t, list_lru);
263271
psync_list_del(&p->list_hash);
@@ -289,8 +297,7 @@ void psync_path_status_drive_folder_changed(psync_folderid_t folderid) {
289297
assert(!ft->own_tasks);
290298
assert(!ft->child_task_cnt);
291299
ft->own_tasks=1;
292-
while (folderid!=0) {
293-
folderid=get_parent_folder(folderid);
300+
while ((folderid=get_parent_folder(folderid))!=PSYNC_INVALID_FOLDERID) {
294301
ft=get_folder_tasks(folderid, 1);
295302
ft->child_task_cnt++;
296303
if (ft->child_task_cnt>1 || ft->own_tasks)
@@ -301,8 +308,7 @@ void psync_path_status_drive_folder_changed(psync_folderid_t folderid) {
301308
assert(!ft->child_task_cnt);
302309
assert(ft->own_tasks);
303310
free_folder_tasks(ft);
304-
while (folderid!=0) {
305-
folderid=get_parent_folder(folderid);
311+
while ((folderid=get_parent_folder(folderid))!=PSYNC_INVALID_FOLDERID) {
306312
ft=get_folder_tasks(folderid, 0);
307313
assert(ft); // if assert fails, the problem is not the assert, don't change it to "if (!ft) break;"
308314
ft->child_task_cnt--;
@@ -314,44 +320,71 @@ void psync_path_status_drive_folder_changed(psync_folderid_t folderid) {
314320
psync_sql_unlock();
315321
}
316322

317-
void psync_path_status_folder_moved(psync_folderid_t folderid, psync_folderid_t old_parent_folderid, psync_folderid_t new_parent_folderid) {
318-
parent_cache_entry_t *p;
319-
folder_tasks_t *ft, *pft;
320-
uint32_t h;
321-
if (old_parent_folderid==new_parent_folderid)
322-
return;
323-
h=hash_folderid(folderid)%PARENT_HASH_SIZE;
324-
psync_sql_lock();
325-
psync_list_for_each_element (p, &parent_cache_hash[h], parent_cache_entry_t, list_hash)
326-
if (p->folderid==folderid) {
327-
assert(p->parentfolderid==old_parent_folderid);
328-
p->parentfolderid=new_parent_folderid;
329-
}
330-
ft=get_folder_tasks(folderid, 0);
331-
if (!ft) {
332-
psync_sql_unlock();
333-
return;
334-
}
323+
static void folder_moved(psync_folderid_t folderid, psync_folderid_t old_parent_folderid, psync_folderid_t new_parent_folderid) {
324+
folder_tasks_t *pft;
335325
pft=get_folder_tasks(old_parent_folderid, 0);
336326
assert(pft);
337327
pft->child_task_cnt--;
338328
while (!pft->child_task_cnt && !pft->own_tasks) {
339329
free_folder_tasks(pft);
340-
if (old_parent_folderid==0)
341-
break;
342330
old_parent_folderid=get_parent_folder(old_parent_folderid);
331+
if (old_parent_folderid==PSYNC_INVALID_FOLDERID)
332+
break;
343333
pft=get_folder_tasks(old_parent_folderid, 0);
344334
assert(pft);
345335
pft->child_task_cnt--;
346336
}
347337
pft=get_folder_tasks(new_parent_folderid, 1);
348338
pft->child_task_cnt++;
349-
while (pft->child_task_cnt==1 && !pft->own_tasks && new_parent_folderid!=0) {
350-
new_parent_folderid=get_parent_folder(new_parent_folderid);
339+
while (pft->child_task_cnt==1 && !pft->own_tasks && (new_parent_folderid=get_parent_folder(new_parent_folderid))!=PSYNC_INVALID_FOLDERID) {
351340
pft=get_folder_tasks(new_parent_folderid, 1);
352341
pft->child_task_cnt++;
353342
}
354-
psync_sql_unlock();
343+
}
344+
345+
static void folder_moved_commit(void *ptr) {
346+
folder_moved_params_t *mp=(folder_moved_params_t *)ptr;
347+
folder_moved(mp->folderid, mp->old_parent_folderid, mp->new_parent_folderid);
348+
psync_free(mp);
349+
}
350+
351+
void psync_path_status_folder_moved(psync_folderid_t folderid, psync_folderid_t old_parent_folderid, psync_folderid_t new_parent_folderid) {
352+
parent_cache_entry_t *p;
353+
folder_moved_params_t *mp;
354+
uint32_t h;
355+
if (old_parent_folderid==new_parent_folderid)
356+
return;
357+
h=hash_folderid(folderid)%PARENT_HASH_SIZE;
358+
psync_list_for_each_element (p, &parent_cache_hash[h], parent_cache_entry_t, list_hash)
359+
if (p->folderid==folderid) {
360+
assert(p->parentfolderid==old_parent_folderid);
361+
p->parentfolderid=new_parent_folderid;
362+
break;
363+
}
364+
if (!get_folder_tasks(folderid, 0))
365+
return;
366+
mp=psync_new(folder_moved_params_t);
367+
mp->folderid=folderid;
368+
mp->old_parent_folderid=old_parent_folderid;
369+
mp->new_parent_folderid=new_parent_folderid;
370+
psync_sql_transation_add_callbacks(folder_moved_commit, psync_free, mp);
371+
}
372+
373+
void psync_path_status_folder_deleted(psync_folderid_t folderid) {
374+
folder_tasks_t *ft;
375+
ft=get_folder_tasks(folderid, 0);
376+
if (ft) {
377+
free_folder_tasks(ft);
378+
while ((folderid=get_parent_folder(folderid))!=PSYNC_INVALID_FOLDERID) {
379+
ft=get_folder_tasks(folderid, 0);
380+
assert(ft); // if assert fails, the problem is not the assert, don't change it to "if (!ft) break;"
381+
ft->child_task_cnt--;
382+
if (ft->child_task_cnt || ft->own_tasks)
383+
break;
384+
free_folder_tasks(ft);
385+
}
386+
}
387+
psync_path_status_del_from_parent_cache(folderid);
355388
}
356389

357390
static inline int is_slash(char ch) {

ppathstatus.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ void psync_path_status_del_from_parent_cache(psync_folderid_t folderid);
6262
void psync_path_status_drive_folder_changed(psync_folderid_t folderid);
6363

6464
void psync_path_status_folder_moved(psync_folderid_t folderid, psync_folderid_t old_parent_folderid, psync_folderid_t new_parent_folderid);
65+
void psync_path_status_folder_deleted(psync_folderid_t folderid);
6566

6667
psync_path_status_t psync_path_status_get(const char *path);
6768

0 commit comments

Comments
 (0)