4.5 Componentes da arquitetura
4.7.1 Sincroniza¸c˜ ao sentido dispositivo m´ovel para servidor fixo
A sincroniza¸c˜ao no sentido dispositivo para servidor fixo ´e a primeira a ser realizada durante o processo de sincroniza¸c˜ao de dados. Durante esta etapa, as informa¸c˜oes do dispositivo s˜ao
enviadas para o servidor central. A figura 4.11 exibe o diagrama de seq¨uˆencia do processo
executado para cada elemento de sincroniza¸c˜ao. Para simplificar o diagrama, n˜ao est˜ao sendo exibidas as intera¸c˜oes entre as interfaces ISyncClient, ISyncServer, ISyncClientMetaDataPro- vider e os objetos que de fato as implementam, que s˜ao, respectivamente, o ClientSyncDAO, GenericServerAdapter e SyncClientMetaDataProvider. Os passos apresentados na figura 4.11 s˜ao detalhados a seguir:
No passo 1, o SyncAgent obt´em o valor da ˆancora referente a ´ultima sincroniza¸c˜ao (idSyncInsert), relacionada `a tabela sincronizada, com envio de novos registros para o servidor.
No passo 2, o SyncAgent, acionando a interface ISyncClient, obt´em a lista de registros inseridos no banco de dados local durante o per´ıodo de desconex˜ao.
No passo 3, os registros obtidos no passo 2 s˜ao enviados para serem aplicados no servidor por meio da interface ISyncServer. O valor do idSyncInsert, obtido no passo 1, ´e passado como parˆametro, permitindo que, conforme detalhado na Se¸c˜ao 4.4, o servidor verifique se o registro enviado ´e realmente novo, e deve ser inserido no servidor, ou se o registro j´a
foi inserido no servidor em uma sincroniza¸c˜ao anterior interrompida inesperadamente.
No passo 4, o ISyncClient ´e acionado para que os LUIDs, gerados no dispositivo, sejam
4. Framework mSync 58
3: *Add(se)
4: BeginSynchronize
1: SetSyncMetaDataProvider(syncMetadataProvider)
Para cada tabela sincronizada 2: se:= *Create(ISyncClient, ISyncServer)
5: *[SyncClientType<>None]:Synchronize DM ->SF 6: *[SyncServerType<>None]:Synchronize SF ->DM ClientApplication SyncAgent SyncElement 3: *Add(se) 4: BeginSynchronize 1: SetSyncMetaDataProvider(syncMetadataProvider)
2: se:= *Create(ISyncClient, ISyncServer)
5: *[SyncClientType<>None]:Synchronize DM ->SF
6: *[SyncServerType<>None]:Synchronize SF ->DM
Figura 4.10: Diagrama de seq¨uˆencia do in´ıcio do processo de sincroniza¸c˜ao
mapeamento entre os identificadores locais dos registros (LUIDs), gerados no disposi- tivo, e os identificadores globais, gerados no servidor (GUID), s˜ao obtidos por meio do resultado da fun¸c˜ao Insert, invocada no passo 3.
No passo 5, o SyncAgent aciona a interface ISyncServer para obter um novo valor para a ˆancora de sincroniza¸c˜ao (idSync).
No passo 6, a ˆancora de sincroniza¸c˜ao obtida no passo 5 ´e armazenada no dispositivo. No passo 7, o SyncAgent, por meio da interface ISyncClient, obt´em a lista de registros
modificados no banco de dados local durante o per´ıodo de desconex˜ao.
Nos passos 8 e 9, caso o tipo de sincroniza¸c˜ao seja refresh, os registros j´a sincroni- zados s˜ao obtidos e adicionados `a lista de registros modificados, pois, neste tipo de sincroniza¸c˜ao, todos os registros do dispositivo devem ser transmitidos para o servidor.
4. Framework mSync 59
2: lsInserted:= GetInserted
3[lsInserted.Count>0]: iResult:= Insert(lsInserted, idSyncInsert)
4[lsInserted.Count>0]: ChangeDMKey(iResult)
5[lsInserted.Count>0]: newIdSync:= GetNewIdSync
6[lsInserted.Count>0]: setIdSyncInsert(newIdSync)
7: lsUpdated:= GetUpdated
8[SyncClientType = Refresh]: lsSynchronized:= GetSynchronized
9[SyncClientType = Refresh]: lsUpdated = lsUpdated + lsSynchronized
10[lsUpdated.Count>0]: uResult:= Update(lsUpdated)
11[lsUpdated.Count>0]: SetStatusRegSynchronized(uResult)
12: lsDeleted:= GetDeleted
13[lsDeleted.Count>0]: dResult:= Delete(lsDeleted)
14[lsDeleted.Count>0]: Remove(dResult)
1: idSyncInsert:= getIdSyncInsert
SyncAgent ISyncClient ISyncServer ISyncClientMetaDataProvider
2: lsInserted:= GetInserted
3[lsInserted.Count>0]: iResult:= Insert(lsInserted, idSyncInsert)
4[lsInserted.Count>0]: ChangeDMKey(iResult)
5[lsInserted.Count>0]: newIdSync:= GetNewIdSync
6[lsInserted.Count>0]: setIdSyncInsert(newIdSync)
7: lsUpdated:= GetUpdated
8[SyncClientType = Refresh]: lsSynchronized:= GetSynchronized
9[SyncClientType = Refresh]: lsUpdated = lsUpdated + lsSynchronized
10[lsUpdated.Count>0]: uResult:= Update(lsUpdated)
11[lsUpdated.Count>0]: SetStatusRegSynchronized(uResult)
12: lsDeleted:= GetDeleted
13[lsDeleted.Count>0]: dResult:= Delete(lsDeleted)
14[lsDeleted.Count>0]: Remove(dResult)
1: idSyncInsert:= getIdSyncInsert
Figura 4.11: Diagrama de seq¨uˆencia do processo de sincroniza¸c˜ao sentido DM -> SF No passo 10, os registros modificados s˜ao transmitidos para serem aplicados no servidor
por meio da interface ISyncServer.
4. Framework mSync 60
atualizados para o estado Synchronized, conforme detalhado na Se¸c˜ao 4.3.1.
No passo 12, ´e obtida a lista de registros exclu´ıdos na base local do dispositivo durante o per´ıodo de desconex˜ao.
No passo 13, os registros exclu´ıdos s˜ao enviados para serem aplicados no servidor. No passo 14, os registros exclu´ıdos no servidor s˜ao fisicamente exclu´ıdos da base de
dados local do dispositivo por meio do m´etodo Remove da interface ISyncClient. Tratamento de Falhas
O ponto mais cr´ıtico em caso de falhas, no fluxo de sincroniza¸c˜ao apresentado na figura 4.11, ´e o passo 3. Se a comunica¸c˜ao for interrompida inesperadamente durante a opera¸c˜ao em que os novos registros criados no dispositivo s˜ao transmitidos para o servidor, o dispositivo n˜ao poder´a determinar, com certeza, se os mesmos foram ou n˜ao inseridos com sucesso na base de dados central. Neste caso, na pr´oxima tentativa de sincroniza¸c˜ao, estes registros ser˜ao transmitidos para o servidor e, se eles j´a tiverem sido inseridos no banco de dados central na ´
ultima tentativa, ser˜ao criados em duplicidade.
O framework mSync, conforme detalhado na Se¸c˜ao 4.4, prop˜oe um esquema para evitar
a situa¸c˜ao descrita. Antes que qualquer registro seja inserido no banco de dados central,
o ServerSyncDAO (ver Se¸c˜ao 4.5.11) verifica se, na tabela de controle idMapping (figura
4.7), existe uma entrada associada `a chave idSync, codTable e LUId referente ao registro sincronizado. Caso a entrada exista, significa que, na sincroniza¸c˜ao anterior, o registro foi transmitido e inserido com sucesso no banco de dados central, e, neste caso, o registro n˜ao ´e inserido novamente, mas apenas atualizado utilizando como chave o identificador ´unico global
(GUID) correspondente armazenado na tabela idMapping. A situa¸c˜ao contr´aria, quando a
entrada na tabela idMapping n˜ao ´e localizada, significa que o registro ´e realmente novo, devendo ser inserido no banco de dados central e a entrada correspondente registrada na tabela idMapping.
Caso a comunica¸c˜ao entre o dispositivo e o servidor seja interrompida em outros pontos, a consistˆencia das informa¸c˜oes tamb´em n˜ao ´e comprometida. Conforme pode ser observado nos passos 11 e 14 da figura 4.11, as a¸c˜oes de atualizar os flags de estado dos registros e remover fisicamente as linhas marcadas para serem exclu´ıdas, respectivamente, s´o s˜ao efetuadas depois que o dispositivo recebe do servidor o resultado da opera¸c˜ao indicando se a mesma foi ou n˜ao conclu´ıda com sucesso. A interrup¸c˜ao da comunica¸c˜ao durante os passos 10 e 13, quando os registros modificados e exclu´ıdos no dispositivo s˜ao transmitidos para o servidor, pode fazer com que as modifica¸c˜oes e exclus˜oes j´a aplicadas no servidor sejam retransmitidas durante a pr´oxima tentativa, por´em essa situa¸c˜ao n˜ao traz problemas relacionados `a consistˆencia dos dados.
Para simplificar o diagrama de seq¨uˆencia, os eventos utilizados pelo framework para no- tificar a aplica¸c˜ao sobre a ocorrˆencia de erros e conflitos n˜ao foram apresentados na figura 4.11. A Se¸c˜ao 4.2 detalha como estas situa¸c˜oes s˜ao detectadas e resolvidas pelo framework.
4. Framework mSync 61