Υποστήριξη συγχρονισμού

Το Eclipse περιλαμβάνει API για τη διαχείριση και την εμφάνιση της κατάστασης συγχρονισμού μεταξύ πόρων του χώρου εργασίας και πόρων που βρίσκονται σε άλλες θέσεις. Ένας πόρος που βρίσκεται εκτός του χώρου εργασίας αναφέρεται ως παραλλαγή. Ο συγχρονισμός είναι η εμφάνιση των αλλαγών μεταξύ των πόρων που βρίσκονται σε διαφορετικές θέσεις και η προαιρετική χορήγηση στον χρήστη της δυνατότητας να επηρεάζει την κατάσταση συγχρονισμού, εκτελώντας μια ενέργεια. Τα API συγχρονισμού είναι ορθογώνια ως προς τα RepositoryProvider API και μπορούν να χρησιμοποιούνται χωρίς παροχέα χώρου αποθήκευσης. Σκοπός του API συγχρονισμού είναι να διευκολύνει την εργασία υλοποίησης διαφορετικών τρόπων παρουσίασης της κατάστασης συγχρονισμού των πόρων. Έτσι, το API απαιτεί ένα μέσο για να θέτει ερωτήματα για την κατάσταση συγχρονισμού των πόρων, αλλά δεν απαιτεί κάποιο μέσο για να επηρεάζει την κατάσταση αυτή. Το μέσο για να επηρεάζεται η κατάσταση ανατίθεται στον υλοποιητή (παρόλο που το περιβάλλον χρήστη παρέχει ρουτίνες για την προσθήκη στα μενού συγκεκριμένων στοιχείων μενού του παροχέα).

Ορολογία

Πριν από την περιγραφή του API συγχρονισμού, θα ήταν χρήσιμο να παρουσιάσουμε κάποια ορολογία και ορισμένες έννοιες που εφαρμόζονται στην περιγραφή του συγχρονισμού χώρου εργασίας.

Παραλλαγή πόρου: Ένας τοπικός πόρος που αντιστοιχίζεται σε έναν πόρο ο οποίος βρίσκεται σε μια άλλη θέση, μπορεί να αναφέρεται ως μια παραλλαγή του δεύτερου. Αυτό σημαίνει ότι οι πόροι είναι παρόμοιοι, αλλά εμφανίζουν μικρές διαφορές (είτε λόγω τροποποιήσεων στον τοπικό πόρο είτε λόγω αλλαγών που έχουν πραγματοποιηθεί στο απομακρυσμένο αντίγραφο από άλλους χρήστες). Σε μια κεντρική προβολή του τοπικού χώρου εργασίας, θα αναφερόμαστε με τον όρο "πόρος" στο τοπικό αντίγραφο και με τον όρο "παραλλαγές πόρου" σε κάθε απομακρυσμένο αντίγραφο.

Συγχρονισμός: Ο συγχρονισμός αναφέρεται ως μια ενέργεια εμφάνισης στον χρήση των διαφορών που υπάρχουν μεταξύ παραλλαγών πόρου. Ο συγχρονισμός δεν επηρεάζει την κατάσταση των παραλλαγών, αλλά παρέχει μια προβολή για να βοηθήσει τον χρήστη να κατανοήσει τις διαφορές μεταξύ των διαφόρων συνόλων παραλλαγών. Ωστόσο συνηθίζεται, να επιτρέπεται στους χρήστες να επηρεάζουν τις καταστάσεις των παραλλαγών (π.χ. επιτρέποντας την επιστροφή ελέγχου ή την επαναφορά), κατά τη διάρκεια του συγχρονισμού.

Συγχρονισμός δύο εκδοχών και συγχρονισμός τριών εκδοχών: Υπάρχουν δύο βασικά είδη προσδιορισμού της κατάστασης συγχρονισμού: δύο εκδοχών και τριών εκδοχών. Μια σύγκριση δύο εκδοχών εξετάζει μόνο τον τοπικό πόρο και μία παραλλαγή του πόρου, η οποία αναφέρεται ως απομακρυσμένη παραλλαγή πόρου. Αυτό το είδος σύγκρισης μπορεί να εμφανίσει μόνο τις διαφορές μεταξύ δύο πόρων, αλλά δεν προσφέρει υποδείξεις για τον τρόπο αλληλοσυσχέτισης των αλλαγών. Τα περισσότερα συστήματα χώρων αποθήκευσης κώδικα υποστηρίζουν μια σύγκριση τριών εκδοχών για τον καθορισμό της κατάστασης συγχρονισμού. Αυτό το είδος σύγκρισης περιλαμβάνει τον τοπικό πόρο, μια απομακρυσμένη παραλλαγή πόρου και μια βασική παραλλαγή πόρου. Η βασική παραλλαγή πόρου εκφράζει μια κοινή εκδοχή προέλευσης για τους τοπικούς και τους απομακρυσμένους πόρους. Αυτό επιτρέπει πιο σύνθετες καταστάσεις συγχρονισμού, που υποδεικνύουν την κατεύθυνση των αλλαγών.

Πίνακας 1: Οι καταστάσεις συγχρονισμού

Δύο εκδοχών Τριών εκδοχών
Άλλαξε
Διαγράφηκε
Προστέθηκε
Εξερχόμενη αλλαγή
Εισερχόμενη αλλαγή
Εξερχόμενη διαγραφή
Εισερχόμενη διαγραφή
Εξερχόμενη προσθήκη
Εισερχόμενη προσθήκη
Αλλαγή σε διένεξη
Διαγραφή σε διένεξη
Προσθήκη σε διένεξη

Τα βασικά στοιχεία - SyncInfo

Οι κλάσεις του πακέτου org.eclipse.team.core.synchronize χρησιμοποιούνται για την περιγραφή της κατάστασης συγχρονισμού. Η πιο σημαντική κλάση είναι η SyncInfo διότι είναι η κλάση η οποία στην πραγματικότητα ορίζει την κατάσταση συγχρονισμού. Μπορεί να χρησιμοποιηθεί ως εξής:

SyncInfo info = getSyncInfo(resource); // this is a simulated method of obtaining the sync info for a resource
int changekind = info.getKind();
if(info.getResourceComparator().isThreeWay()) {
if((changeKind & SyncInfo.DIRECTION_MASK) == SyncInfo.INCOMING) {
// do something
}
} else if(changeKind == SyncInfo.CHANGE) {
// do something else
}

Η κλάση SyncInfo παρέχει αλγόριθμους σύγκρισης τόσο δύο εκδοχών όσο και τριών εκδοχών. Ένας πελάτης πρέπει να παρέχει τους πόρους και μια κλάση η οποία να μπορεί να συγκρίνει τους πόρους (IResourceVariantComparator). Παρακάτω δίνεται ένα παράδειγμα ρουτίνας σύγκρισης παραλλαγών:

public class TimestampVariantComparator implements IResourceVariantComparator {	
protected boolean compare(IResourceVariant e1, IResourceVariant e2) {
if(e1.isContainer()) {
if(e2.isContainer()) {
return true;
}
return false;
}
if(e1 instanceof MyResourceVariant && e2 instanceof MyResourceVariant) {
MyResourceVariant myE1 = (MyResourceVariant)e1;
MyResourceVariant myE2 = (MyResourceVariant)e2;
return myE1.getTimestamp().equals(myE2.getTimestamp());
}
return false;
}
protected boolean compare(IResource e1, IResourceVariant e2) {

}
public boolean isThreeWay() {
return true;
}
}

SyncInfo info = new SyncInfo(resource, variant1, variant2, new TimestampComparator());
info.init(); // calculate the sync info

Το πακέτο αυτό περιέχει επίσης συλλογές που έχουν σχεδιαστεί ειδικά ώστε να περιέχουν την κλάση SyncInfo και φίλτρα τα οποία μπορούν να εφαρμοστούν στις περιπτώσεις χρήσης της SyncInfo.

Διαχείριση της κατάστασης συγχρονισμού

Όπως είδαμε στα παραπάνω παραδείγματα, οι κλάσεις SyncInfo και IResourceVariantComparator παρέχουν πρόσβαση στην κατάσταση συγχρονισμού των πόρων. Αυτό που δεν έχουμε δει ακόμη είναι ο τρόπος διαχείρισης της κατάστασης. Μια κλάση Subscriber παρέχει πρόσβαση στην κατάσταση συγχρονισμού μεταξύ των πόρων του τοπικού χώρου εργασίας και ενός συνόλου παραλλαγών για τους πόρους αυτούς, χρησιμοποιώντας είτε τη σύγκριση δύο εκδοχών είτε τη σύγκριση τριών εκδοχών, ανάλογα με τη φύση του συνδρομητή. Ένας συνδρομητής παρέχει τις ακόλουθες δυνατότητες:

Τα API δεν ορίζουν τον τρόπο με τον οποίο δημιουργείται μια κλάση Subscriber, αυτό γίνεται από ειδικές υλοποιήσεις. Για παράδειγμα, η πρόσθετη λειτουργία CVS δημιουργεί μια κλάση Subscriber όταν πραγματοποιείται μια συγχώνευση και άλλη όταν πραγματοποιείται συγχρονισμός του τοπικού χώρου εργασίας με τον τρέχοντα κλάδο.

Έτσι, ας επιστρέψουμε στο πρώτο παράδειγμα χρήσης της SyncInfo για να δούμε τον τρόπο με τον οποίο η κλάση Subscriber μπορεί να χρησιμοποιηθεί για την πρόσβαση στην SyncInfo.

// Create a file system subscriber and specify that the
// subscriber will synchronize with the provided file system location
Subscriber subscriber = new FileSystemSubscriber("c:\temp\repo");

// Allow the subscriber to refresh its state
subscriber.refresh(subscriber.roots(), IResource.DEPTH_INFINITE, monitor);

// Collect all the synchronization states and print
IResource[] children = subscriber.roots();
for(int i=0; i < children.length; i++) {
printSyncState(children[i]);
}

...

void printSyncState(Subscriber subscriber, IResource resource) {
System.out.println(subscriber.getSyncInfo(resource).toString());
IResource[] children = subscriber.members(resource);
for(int i=0; i < children.length; i++) {
IResource child = children[i];
if(! child.exists()) {
System.out.println(resource.getFullPath() + " doesn't exist in the workspace");
}
printSyncState(subscriber, children[i]);
}
}

Το σημαντικό σημείο που πρέπει να θυμάστε είναι ότι η κλάση Subscriber γνωρίζει τους πόρους που δεν υπάρχουν στον χώρο εργασίας και οι πόροι αυτοί μπορούν να επιστραφούν από τη μέθοδο Subscriber#members() και τη SyncInfo#getLocal().

Εμφάνιση της κατάστασης συγχρονισμού στο περιβάλλον χρήστη

Θα μπορούσαμε να επεκταθούμε περισσότερο εξηγώντας τον τρόπο με τον οποίο γίνεται η διαχείριση της κατάστασης συγχρονισμού, αλλά ας δούμε καλύτερα πώς λαμβάνεται στην πράξη η κατάσταση που εμφανίζεται στον χρήστη. Η διεπαφή ISynchronizeParticipant είναι ένα συστατικό του περιβάλλοντος χρήστη που εμφανίζεται την κατάσταση συγχρονισμού και επιτρέπει στον χρήστη να επηρεάζει την κατάστασή του. Η προβολή "Συγχρονισμός" εμφανίζει τα συστατικά στοιχεία συμμετοχής του συγχρονισμού, αλλά μπορεί επίσης να τα εμφανίσει σε πλαίσια διαλόγου και οδηγούς. Προκειμένου να παρέχει υποστήριξη προς τους χρήστες για την εμφάνιση κάθε είδους κατάστασης συγχρονισμού, ακόμη και αυτών που δεν βασίζονται στις κλάσεις SyncInfo και Subscriber, ένα συστατικό στοιχείο συμμετοχής είναι ένα πολύ γενικό στοιχείο.

Υπάρχει επίσης ένα σημείο επέκτασης, το οποίο καλείται org.eclipse.team.ui.synchronizeWizards για την προσθήκη ενός οδηγού δημιουργίας συγχρονισμού. Αυτό θα τοποθετεί τον οδηγό σας σε μια καθολική ενέργεια συγχρονισμού και στην προβολή "Συγχρονισμός", έτσι ώστε οι χρήστες να μπορούν εύκολα να δημιουργούν έναν συγχρονισμό του είδους σας.

Ωστόσο, εάν έχετε υλοποιήσει μια κλάση Subscriber, μπορείτε να επωφεληθείτε από ένα κανονικό συστατικό στοιχείο συμμετοχής, που καλείται SubscriberParticipant το οποίο θα παρέχει την παρακάτω λειτουργικότητα:

Ο καλύτερος τρόπος για να εξηγήσουμε τις έννοιες αυτές είναι να τις δούμε να χρησιμοποιούνται στο περιβάλλον ενός απλού παραδείγματος. Ανατρέξτε στο παράδειγμα συγχρονισμός τοπικού ιστορικού για να δείτε με ποιό τρόπο όλα τα παραπάνω χρησιμοποιούνται μαζί. Ή, αν θέλετε κάποιες ενδείξεις για τον τρόπο με τον οποίο χρησιμοποιούνται τα πιο προηγμένα API, ανατρέξτε στην ενότητα Πέρα από τα βασικά στοιχεία.