You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1049 lines
26 KiB

/*
* sync.c: Implement generic synchronization algorithm
*
* Documentation of the sync cases is at:
* http://www.palmos.com/dev/tech/docs/conduits/win/Intro_CondBasics.html#928692
*
* Copyright (c) 2000-2001, Ximian Inc.
*
* Author: JP Rosevear <jpr@helixcode.com>
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library
* General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <stdlib.h>
#include <string.h>
#include "pi-dlp.h"
#include "pi-sync.h"
typedef enum {
PILOT,
DESKTOP,
BOTH
} RecordModifier;
typedef struct _RecordQueueList RecordQueueList;
typedef struct _RecordQueue RecordQueue;
struct _RecordQueueList {
DesktopRecord *drecord;
PilotRecord *precord;
RecordQueueList *next;
};
struct _RecordQueue {
int count;
RecordQueueList *rql;
};
#define PilotCheck(func) if (rec_mod == PILOT || rec_mod == BOTH) if ((result = func) < 0) return result;
#define DesktopCheck(func) if (rec_mod == DESKTOP || rec_mod == BOTH) if ((result = func) < 0) return result;
#define ErrorCheck(func) if ((result = func) < 0) return result;
/***********************************************************************
*
* Function: sync_NewPilotRecord
*
* Summary: Create a new, empty device record with the given buffer
* size
*
* Parameters: None
*
* Returns: The new device record
*
***********************************************************************/
PilotRecord *sync_NewPilotRecord(int buf_size)
{
PilotRecord *precord;
precord = (PilotRecord *) malloc(sizeof(PilotRecord));
memset(precord, 0, sizeof(PilotRecord));
precord->buffer = malloc(buf_size);
return precord;
}
/***********************************************************************
*
* Function: sync_CopyPilotRecord
*
* Summary: Copies the given device record
*
* Parameters: None
*
* Returns: The device record passed by sync_NewPilotRecord
*
***********************************************************************/
PilotRecord *sync_CopyPilotRecord(const PilotRecord * precord)
{
PilotRecord *new_record;
new_record = sync_NewPilotRecord(sizeof(precord->buffer));
new_record->recID = precord->recID;
new_record->catID = precord->catID;
new_record->flags = precord->flags;
memcpy(new_record->buffer, precord->buffer, precord->len);
new_record->len = precord->len;
return new_record;
}
/***********************************************************************
*
* Function: sync_FreePilotRecord
*
* Summary: Free the memory of the given device record
*
* Parameters: The device record to free
*
* Returns: Nothing
*
***********************************************************************/
void sync_FreePilotRecord(PilotRecord * precord)
{
if (precord->buffer)
free(precord->buffer);
free(precord);
}
/***********************************************************************
*
* Function: sync_NewDesktopRecord
*
* Summary: Create a new, empty, desktop record
*
* Parameters: None
*
* Returns: The new, empty desktop record
*
***********************************************************************/
DesktopRecord *sync_NewDesktopRecord(void)
{
DesktopRecord *drecord;
drecord = (DesktopRecord *) malloc(sizeof(DesktopRecord));
memset(drecord, 0, sizeof(DesktopRecord));
return drecord;
}
/***********************************************************************
*
* Function: sync_CopyDesktopRecord
*
* Summary: Copies the given desktop record
*
* Parameters: None
*
* Returns: The new desktop record (DesktopRecord)
*
***********************************************************************/
DesktopRecord *sync_CopyDesktopRecord(const DesktopRecord * drecord)
{
DesktopRecord *new_record;
new_record = sync_NewDesktopRecord();
*new_record = *drecord;
return new_record;
}
/***********************************************************************
*
* Function: sync_FreeDesktopRecord
*
* Summary: Free the memory of the given desktop record
*
* Parameters: None
*
* Returns: Nothing
*
***********************************************************************/
void sync_FreeDesktopRecord(DesktopRecord * drecord)
{
free(drecord);
}
/***********************************************************************
*
* Function: add_record_queue
*
* Summary: Add records to process to the queue, until no more
* records exist
*
* Parameters: None
*
* Returns: Nothing
*
***********************************************************************/
static void
add_record_queue(RecordQueue * rq, PilotRecord * precord,
DesktopRecord * drecord)
{
RecordQueueList *item;
item = malloc(sizeof(RecordQueueList));
if (drecord != NULL) {
item->drecord = drecord;
item->precord = NULL;
} else {
item->drecord = NULL;
item->precord = sync_CopyPilotRecord(precord);
}
if (rq) {
item->next = rq->rql;
rq->rql = item;
} else {
item->next = NULL;
}
rq->count++;
}
/***********************************************************************
*
* Function: free_record_queue_list
*
* Summary: Free the list
*
* Parameters: None
*
* Returns: Nothing
*
***********************************************************************/
static int free_record_queue_list(SyncHandler * sh, RecordQueueList * rql)
{
int result = 0;
RecordQueueList *item;
while (rql != NULL) {
item = rql;
rql = rql->next;
if (item->drecord)
ErrorCheck(sh->FreeMatch(sh, item->drecord));
if (item->precord)
sync_FreePilotRecord(item->precord);
free(item);
}
return 0;
}
/***********************************************************************
*
* Function: delete_both
*
* Summary: Delete records from both Palm and desktop, same time
*
* Parameters: None
*
* Returns: negative number if error, otherwise 0 to indicate
* success
*
***********************************************************************/
static int
delete_both(SyncHandler * sh, int dbhandle, DesktopRecord * drecord,
PilotRecord * precord, RecordModifier rec_mod)
{
int result = 0;
if (drecord != NULL)
DesktopCheck(sh->DeleteRecord(sh, drecord));
if (precord != NULL)
PilotCheck(dlp_DeleteRecord
(sh->sd, dbhandle, 0, precord->recID));
return result;
}
/***********************************************************************
*
* Function: store_record_on_pilot
*
* Summary: Store the new/modified record on the Palm
*
* Parameters: None
*
* Returns: 0 if success, otherwise negative number
*
***********************************************************************/
static int
store_record_on_pilot(SyncHandler * sh, int dbhandle,
DesktopRecord * drecord, RecordModifier rec_mod)
{
int result = 0;
PilotRecord precord;
recordid_t id_;
memset(&precord, 0, sizeof(PilotRecord));
result = sh->Prepare(sh, drecord, &precord);
if (result != 0)
return result;
PilotCheck(dlp_WriteRecord(sh->sd, dbhandle, precord.flags & dlpRecAttrSecret,
precord.recID, precord.catID,
precord.buffer, precord.len, &id_));
DesktopCheck(sh->SetPilotID(sh, drecord, id_));
return result;
}
/***********************************************************************
*
* Function: open_db
*
* Summary: Open a given database by handle for operation
*
* Parameters: None
*
* Returns: Nothing
*
***********************************************************************/
static int open_db(SyncHandler * sh, int *dbhandle)
{
if (sh->secret)
return dlp_OpenDB(sh->sd, 0, dlpOpenReadWrite
&& dlpOpenSecret, sh->name, dbhandle);
else
return dlp_OpenDB(sh->sd, 0, dlpOpenReadWrite, sh->name,
dbhandle);
}
/***********************************************************************
*
* Function: close_db
*
* Summary: Close a given database by handle
*
* Parameters: None
*
* Returns: Nothing
*
***********************************************************************/
static int close_db(SyncHandler * sh, int dbhandle)
{
dlp_CleanUpDatabase(sh->sd, dbhandle);
dlp_ResetSyncFlags(sh->sd, dbhandle);
dlp_CloseDB(sh->sd, dbhandle);
return 0;
}
/***********************************************************************
*
* Function: sync_record
*
* Summary: Synchronize a record to the Palm
*
* Parameters: None
*
* Returns: 0 if success, otherwise return a negative number
*
***********************************************************************/
static int
sync_record(SyncHandler * sh, int dbhandle,
DesktopRecord * drecord, PilotRecord * precord,
RecordQueue * rq, RecordModifier rec_mod)
{
int parch = 0,
pdel = 0,
pchange = 0,
darch = 0,
ddel = 0,
dchange = 0,
result = 0;
/* The state is calculated like this because the deleted and dirty
pilot flags are not mutually exclusive */
if (precord) {
parch = precord->flags & dlpRecAttrArchived;
pdel = precord->flags & dlpRecAttrDeleted;
pchange = (precord->flags & dlpRecAttrDirty) && (!pdel);
}
if (drecord) {
darch = drecord->flags & dlpRecAttrArchived;
ddel = drecord->flags & dlpRecAttrDeleted;
dchange = (drecord->flags & dlpRecAttrDirty) && (!ddel);
}
/* Bail if the pilot record was created and deleted between syncs */
if (drecord == NULL && !parch && pdel)
return 0;
/* Sync logic */
if (precord != NULL && !parch && !pdel && drecord == NULL) {
DesktopCheck(sh->AddRecord(sh, precord));
} else if (precord == NULL && drecord != NULL) {
add_record_queue(rq, NULL, drecord);
} else if (parch && ddel) {
DesktopCheck(sh->ReplaceRecord(sh, drecord, precord));
DesktopCheck(sh->ArchiveRecord(sh, drecord, 1));
DesktopCheck(sh->SetStatusCleared(sh, drecord));
} else if (parch && !darch && !dchange && drecord != NULL) {
DesktopCheck(sh->ArchiveRecord(sh, drecord, 1));
} else if (parch && drecord == NULL) {
DesktopCheck(sh->AddRecord(sh, precord));
ErrorCheck(sh->Match(sh, precord, &drecord));
if (drecord == NULL)
return -1;
DesktopCheck(sh->ArchiveRecord(sh, drecord, 1));
ErrorCheck(sh->FreeMatch(sh, drecord));
} else if (parch && pchange && !darch && dchange) {
int comp;
comp = sh->Compare(sh, precord, drecord);
if (comp == 0) {
DesktopCheck(sh->ArchiveRecord(sh, drecord, 1));
PilotCheck(dlp_DeleteRecord
(sh->sd, dbhandle, 0, precord->recID));
DesktopCheck(sh->SetStatusCleared(sh, drecord));
} else {
PilotCheck(dlp_WriteRecord(sh->sd, dbhandle, 0, 0,
precord->catID,
precord->buffer,
precord->len,
&precord->recID));
DesktopCheck(sh->AddRecord(sh, precord));
add_record_queue(rq, NULL, drecord);
DesktopCheck(sh->SetStatusCleared(sh, drecord));
}
} else if (parch && !pchange && !darch && dchange) {
PilotCheck(dlp_DeleteRecord
(sh->sd, dbhandle, 0, precord->recID));
add_record_queue(rq, NULL, drecord);
DesktopCheck(sh->SetStatusCleared(sh, drecord));
} else if (pchange && darch && dchange) {
int comp;
comp = sh->Compare(sh, precord, drecord);
if (comp == 0) {
PilotCheck(dlp_DeleteRecord
(sh->sd, dbhandle, 0, precord->recID));
} else {
DesktopCheck(sh->ArchiveRecord(sh, drecord, 0));
DesktopCheck(sh->
ReplaceRecord(sh, drecord, precord));
}
DesktopCheck(sh->SetStatusCleared(sh, drecord));
} else if (pchange && darch && !dchange) {
DesktopCheck(sh->ArchiveRecord(sh, drecord, 0));
DesktopCheck(sh->ReplaceRecord(sh, drecord, precord));
DesktopCheck(sh->SetStatusCleared(sh, drecord));
} else if (pchange && dchange) {
int comp;
comp = sh->Compare(sh, precord, drecord);
if (comp != 0) {
DesktopCheck(sh->AddRecord(sh, precord));
drecord->recID = 0;
add_record_queue(rq, NULL, drecord);
}
DesktopCheck(sh->SetStatusCleared(sh, drecord));
} else if (pchange && ddel) {
DesktopCheck(sh->ReplaceRecord(sh, drecord, precord));
DesktopCheck(sh->SetStatusCleared(sh, drecord));
} else if (pchange && !dchange) {
DesktopCheck(sh->ReplaceRecord(sh, drecord, precord));
DesktopCheck(sh->SetStatusCleared(sh, drecord));
} else if (pdel && dchange) {
add_record_queue(rq, NULL, drecord);
DesktopCheck(sh->SetStatusCleared(sh, drecord));
} else if (pdel && !dchange) {
DesktopCheck(delete_both
(sh, dbhandle, drecord, precord, rec_mod));
DesktopCheck(sh->SetStatusCleared(sh, drecord));
} else if (!pchange && darch) {
PilotCheck(dlp_DeleteRecord
(sh->sd, dbhandle, 0, precord->recID));
DesktopCheck(sh->SetStatusCleared(sh, drecord));
} else if (!pchange && dchange) {
PilotCheck(dlp_DeleteRecord
(sh->sd, dbhandle, 0, precord->recID));
add_record_queue(rq, NULL, drecord);
DesktopCheck(sh->SetStatusCleared(sh, drecord));
} else if (!pchange && ddel) {
DesktopCheck(delete_both
(sh, dbhandle, drecord, precord, rec_mod));
DesktopCheck(sh->SetStatusCleared(sh, drecord));
}
return result;
}
/***********************************************************************
*
* Function: sync_CopyToPilot
*
* Summary: Copy all desktop records to the Palm
*
* Parameters: None
*
* Returns: 0 on success, non-zero otherwise
*
***********************************************************************/
int sync_CopyToPilot(SyncHandler * sh)
{
int dbhandle,
slow = 0,
result = 0;
DesktopRecord *drecord = NULL;
result = open_db(sh, &dbhandle);
if (result < 0)
goto cleanup;
result = sh->Pre(sh, dbhandle, &slow);
if (result < 0)
goto cleanup;
result = dlp_DeleteRecord(sh->sd, dbhandle, 1, 0);
if (result < 0)
goto cleanup;
while (sh->ForEach(sh, &drecord) == 0 && drecord) {
result =
store_record_on_pilot(sh, dbhandle, drecord, BOTH);
if (result < 0)
goto cleanup;
}
result = sh->Post(sh, dbhandle);
cleanup:
close_db(sh, dbhandle);
return result;
}
/***********************************************************************
*
* Function: sync_CopyFromPilot
*
* Summary: Copy all device records from the Palm to the desktop
*
* Parameters: None
*
* Returns: 0 on success, non-zero otherwise
*
***********************************************************************/
int sync_CopyFromPilot(SyncHandler * sh)
{
int dbhandle,
i,
slow = 0,
result = 0;
pi_buffer_t *recbuf;
DesktopRecord *drecord = NULL;
PilotRecord *precord = sync_NewPilotRecord(DLP_BUF_SIZE);
result = open_db(sh, &dbhandle);
if (result < 0)
goto cleanup;
result = sh->Pre(sh, dbhandle, &slow);
if (result < 0)
goto cleanup;
while (sh->ForEach(sh, &drecord) == 0 && drecord) {
result = sh->DeleteRecord(sh, drecord);
if (result < 0)
goto cleanup;
}
i = 0;
recbuf = pi_buffer_new(DLP_BUF_SIZE);
while (dlp_ReadRecordByIndex(sh->sd, dbhandle, i, recbuf, &precord->recID,
&precord->flags, &precord->catID) > 0) {
precord->len = recbuf->used;
if (precord->len > DLP_BUF_SIZE)
precord->len = DLP_BUF_SIZE;
memcpy(precord->buffer, recbuf->data, precord->len);
result = sh->AddRecord(sh, precord);
if (result < 0) {
pi_buffer_free(recbuf);
goto cleanup;
}
i++;
}
pi_buffer_free (recbuf);
result = sh->Post(sh, dbhandle);
cleanup:
close_db(sh, dbhandle);
sync_FreePilotRecord (precord);
return result;
}
/***********************************************************************
*
* Function: sync_MergeFromPilot_process
*
* Summary: Try to be intelligent about merging data in a record
*
* Parameters: None
*
* Returns: Nothing
*
***********************************************************************/
static int
sync_MergeFromPilot_process(SyncHandler * sh, int dbhandle,
RecordQueue * rq, RecordModifier rec_mod)
{
int result = 0;
RecordQueueList *item;
for (item = rq->rql; item != NULL; item = item->next) {
if (item->drecord != NULL) {
store_record_on_pilot(sh, dbhandle, item->drecord,
rec_mod);
} else {
PilotCheck(dlp_WriteRecord(sh->sd, dbhandle, 0, 0,
item->precord->catID,
item->precord->buffer,
item->precord->len,
&item->precord->recID));
}
}
free_record_queue_list(sh, rq->rql);
return result;
}
/***********************************************************************
*
* Function: sync_MergeFromPilot_fast
*
* Summary: er, fast merge from Palm to desktop
*
* Parameters: None
*
* Returns: 0 if success, nonzero otherwise
*
***********************************************************************/
static int
sync_MergeFromPilot_fast(SyncHandler * sh, int dbhandle,
RecordModifier rec_mod)
{
int result = 0;
PilotRecord *precord = sync_NewPilotRecord(DLP_BUF_SIZE);
DesktopRecord *drecord = NULL;
RecordQueue rq = { 0, NULL };
pi_buffer_t *recbuf = pi_buffer_new(DLP_BUF_SIZE);
while (dlp_ReadNextModifiedRec(sh->sd, dbhandle, recbuf,
&precord->recID, NULL,
&precord->flags,
&precord->catID) >= 0) {
int count = rq.count;
precord->len = recbuf->used;
if (precord->len > DLP_BUF_SIZE)
precord->len = DLP_BUF_SIZE;
memcpy(precord->buffer, recbuf->data, precord->len);
ErrorCheck(sh->Match(sh, precord, &drecord));
ErrorCheck(sync_record
(sh, dbhandle, drecord, precord, &rq, rec_mod));
if (drecord && rq.count == count)
ErrorCheck(sh->FreeMatch(sh, drecord));
}
pi_buffer_free(recbuf);
sync_FreePilotRecord(precord);
result = sync_MergeFromPilot_process(sh, dbhandle, &rq, rec_mod);
return result;
}
/***********************************************************************
*
* Function: sync_MergeFromPilot_slow
*
* Summary: uh, slow merge from Palm to desktop
*
* Parameters: None
*
* Returns: 0 if success, nonzero otherwise
*
***********************************************************************/
static int
sync_MergeFromPilot_slow(SyncHandler * sh, int dbhandle,
RecordModifier rec_mod)
{
int i,
parch,
psecret,
result = 0;
pi_buffer_t *recbuf;
PilotRecord *precord = sync_NewPilotRecord(DLP_BUF_SIZE);
DesktopRecord *drecord = NULL;
RecordQueue rq = { 0, NULL };
i = 0;
recbuf = pi_buffer_new(DLP_BUF_SIZE);
while (dlp_ReadRecordByIndex
(sh->sd, dbhandle, i, recbuf, &precord->recID,
&precord->flags, &precord->catID) > 0) {
int count = rq.count;
precord->len = recbuf->used;
if (precord->len > DLP_BUF_SIZE)
precord->len = DLP_BUF_SIZE;
memcpy(precord->buffer, recbuf->data, precord->len);
ErrorCheck(sh->Match(sh, precord, &drecord));
/* Since this is a slow sync, we must calculate the flags */
parch = precord->flags & dlpRecAttrArchived;
psecret = precord->flags & dlpRecAttrSecret;
precord->flags = 0;
if (drecord == NULL) {
precord->flags = precord->flags | dlpRecAttrDirty;
} else {
int comp;
comp = sh->Compare(sh, precord, drecord);
if (comp != 0) {
precord->flags =
precord->flags | dlpRecAttrDirty;
}
}
if (parch)
precord->flags =
precord->flags | dlpRecAttrArchived;
if (psecret)
precord->flags = precord->flags | dlpRecAttrSecret;
ErrorCheck(sync_record
(sh, dbhandle, drecord, precord, &rq, rec_mod));
if (drecord && rq.count == count)
ErrorCheck(sh->FreeMatch(sh, drecord));
i++;
}
pi_buffer_free(recbuf);
sync_FreePilotRecord(precord);
result = sync_MergeFromPilot_process(sh, dbhandle, &rq, rec_mod);
return result;
}
/***********************************************************************
*
* Function: sync_MergeFromPilot
*
* Summary: Synchronize the device records to the desktop, but do
* not alter the device records
*
* Parameters: None
*
* Returns: 0 on success, non-zero otherwise
*
***********************************************************************/
int sync_MergeFromPilot(SyncHandler * sh)
{
int dbhandle,
slow = 0,
result = 0;
result = open_db(sh, &dbhandle);
if (result < 0)
goto cleanup;
result = sh->Pre(sh, dbhandle, &slow);
if (result < 0)
goto cleanup;
if (!slow) {
result = sync_MergeFromPilot_fast(sh, dbhandle, DESKTOP);
if (result < 0)
goto cleanup;
} else {
result = sync_MergeFromPilot_slow(sh, dbhandle, DESKTOP);
if (result < 0)
goto cleanup;
}
result = sh->Post(sh, dbhandle);
cleanup:
close_db(sh, dbhandle);
return result;
}
/***********************************************************************
*
* Function: sync_MergeToPilot_fast
*
* Summary: Fast merge from desktop to Palm
*
* Parameters: None
*
* Returns: 0 on success, non-zero otherwise
*
***********************************************************************/
static int
sync_MergeToPilot_fast(SyncHandler * sh, int dbhandle,
RecordModifier rec_mod)
{
int result = 0;
PilotRecord *precord = NULL;
DesktopRecord *drecord = NULL;
RecordQueue rq = { 0, NULL };
pi_buffer_t *recbuf = pi_buffer_new(DLP_BUF_SIZE);
while (sh->ForEachModified(sh, &drecord) == 0 && drecord) {
if (drecord->recID != 0) {
precord = sync_NewPilotRecord(DLP_BUF_SIZE);
precord->recID = drecord->recID;
PilotCheck(dlp_ReadRecordById(sh->sd, dbhandle,
precord->recID,
recbuf,
NULL,
&precord->flags,
&precord->catID));
precord->len = recbuf->used;
if (precord->len > DLP_BUF_SIZE)
precord->len = DLP_BUF_SIZE;
memcpy(precord->buffer, recbuf->data, precord->len);
}
ErrorCheck(sync_record
(sh, dbhandle, drecord, precord, &rq, rec_mod));
if (precord)
sync_FreePilotRecord (precord);
precord = NULL;
}
pi_buffer_free(recbuf);
result = sync_MergeFromPilot_process(sh, dbhandle, &rq, rec_mod);
return result;
}
/***********************************************************************
*
* Function: sync_MergeToPilot_slow
*
* Summary: Slow merge from desktop to Palm
*
* Parameters: None
*
* Returns: 0 on success, non-zero otherwise
*
***********************************************************************/
static int
sync_MergeToPilot_slow(SyncHandler * sh, int dbhandle,
RecordModifier rec_mod)
{
int darch,
dsecret,
result = 0;
PilotRecord *precord = NULL;
DesktopRecord *drecord = NULL;
RecordQueue rq = { 0, NULL };
pi_buffer_t *recbuf = pi_buffer_new(DLP_BUF_SIZE);
while (sh->ForEach(sh, &drecord) == 0 && drecord) {
if (drecord->recID != 0) {
precord = sync_NewPilotRecord(DLP_BUF_SIZE);
precord->recID = drecord->recID;
PilotCheck(dlp_ReadRecordById(sh->sd, dbhandle,
precord->recID,
recbuf,
NULL,
&precord->flags,
&precord->catID));
precord->len = recbuf->used;
if (precord->len > DLP_BUF_SIZE)
precord->len = DLP_BUF_SIZE;
memcpy(precord->buffer, recbuf->data, precord->len);
}
/* Since this is a slow sync, we must calculate the flags */
darch = drecord->flags & dlpRecAttrArchived;
dsecret = drecord->flags & dlpRecAttrSecret;
drecord->flags = 0;
if (precord == NULL) {
drecord->flags = drecord->flags | dlpRecAttrDirty;
} else {
int comp;
comp = sh->Compare(sh, precord, drecord);
if (comp != 0) {
drecord->flags =
drecord->flags | dlpRecAttrDirty;
}
}
if (darch)
drecord->flags =
drecord->flags | dlpRecAttrArchived;
if (dsecret)
drecord->flags = drecord->flags | dlpRecAttrSecret;
ErrorCheck(sync_record
(sh, dbhandle, drecord, precord, &rq, rec_mod));
if (precord)
sync_FreePilotRecord (precord);
precord = NULL;
}
pi_buffer_free(recbuf);
result = sync_MergeFromPilot_process(sh, dbhandle, &rq, rec_mod);
return result;
}
/***********************************************************************
*
* Function: sync_MergeToPilot
*
* Summary: Synchronize the desktop records to the pilot, but do
* not alter the desktop records
*
* Parameters: None
*
* Returns: 0 on success, non-zero otherwise
*
***********************************************************************/
int sync_MergeToPilot(SyncHandler * sh)
{
int dbhandle,
slow = 0,
result = 0;
result = open_db(sh, &dbhandle);
if (result < 0)
goto cleanup;
result = sh->Pre(sh, dbhandle, &slow);
if (result < 0)
goto cleanup;
if (!slow) {
sync_MergeToPilot_fast(sh, dbhandle, PILOT);
if (result < 0)
goto cleanup;
} else {
sync_MergeToPilot_slow(sh, dbhandle, PILOT);
if (result < 0)
goto cleanup;
}
result = sh->Post(sh, dbhandle);
cleanup:
close_db(sh, dbhandle);
return result;
}
/***********************************************************************
*
* Function: sync_Synchronize
*
* Summary: Synchronizes the pilot database and the desktop database
*
* Parameters: None
*
* Returns: 0 on success, non-zero otherwise
*
***********************************************************************/
int sync_Synchronize(SyncHandler * sh)
{
int dbhandle,
slow = 0,
result = 0;
result = open_db(sh, &dbhandle);
if (result < 0)
goto cleanup;
result = sh->Pre(sh, dbhandle, &slow);
if (result != 0)
goto cleanup;
if (!slow) {
result = sync_MergeFromPilot_fast(sh, dbhandle, BOTH);
if (result < 0)
goto cleanup;
result = sync_MergeToPilot_fast(sh, dbhandle, BOTH);
if (result < 0)
goto cleanup;
} else {
result = sync_MergeFromPilot_slow(sh, dbhandle, BOTH);
if (result < 0)
goto cleanup;
result = sync_MergeToPilot_slow(sh, dbhandle, BOTH);
if (result < 0)
goto cleanup;
}
result = sh->Post(sh, dbhandle);
cleanup:
close_db(sh, dbhandle);
return result;
}