2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2004 Net Integration Technologies, Inc.
5 * WvSyncObj is the base-class interface for a named object that can be
6 * replicated using WvSync and its protocol. You can't actually make a
7 * WvSyncObj, nor would it be enough; you have to derive a subclass for
8 * each type of object you plan on synchronizing, and instantiate those.
22 typedef WvCallback
<void, WvSyncObj
&, WvBuf
&> WvSyncCallback
;
27 WvSyncObj(WvStringParm _name
);
28 virtual ~WvSyncObj() {}
30 WvString name
; // every replicable object has a name
32 /** getsig() generates a librsync signature for the object. It
33 * currently doesn't block; it'll only return when the entire signature
34 * has been calculated.
36 * Returns 0 on success, else error.
38 * The signature is placed in the "out" buffer. Please make sure your
39 * buffer is big enough! Using WvDynBuf might be best.
41 int getsig(WvBuf
&out
);
43 /** makedelta() generates a librsync delta, based on a signature
44 * received from the remote side (in the "in" buffer).
46 * The delta, placed into the "out" buffer, when passed back to the
47 * remote side, can transform its copy of the object into a duplicate
48 * of the copy we have on this side.
50 * If cb is given, it will be called when the output buffer is getting
51 * pretty full and you might want to do something with it.
53 * Returns 0 on success, else error.
55 int makedelta(WvBuf
&in
, WvBuf
&out
, WvSyncCallback cb
= 0);
57 /** applydelta() takes a librsync delta received from the remote side
58 * in the "in" buffer, applies it to the local version of the data, and
59 * places the updated data in the "out" buffer.
61 * If cb is given, it will be called when the output buffer is getting
62 * pretty full and you might want to do something with it.
64 * Returns 0 on success, else error.
66 * The second variant of applydelta() takes a file instead of an input
67 * buffer. If your makedelta callback decided the delta was huge and
68 * wrote it to a file, you can apply it directly with this.
70 int applydelta(WvBuf
&in
, WvBuf
&out
, WvSyncCallback cb
= 0);
71 int applydelta(WvStringParm in
, WvBuf
&out
, WvSyncCallback cb
= 0);
73 virtual bool isok() const
76 /** getdata() is used by WvSyncObj as a means of requesting a
77 * specific block of data from a subclass that implements this.
78 * librsync in particular uses this when reconstructing updated data
79 * from a delta, but we might as well also use it to get data when
80 * generating a signature or a delta.
82 * Returns a bool indicating whether there's any data left after this
85 * Takes a buffer to put the data in, the offset we want, and the size
88 * Subclasses must implement this.
90 virtual bool getdata(WvBuf
&out
, off_t ofs
, size_t size
) = 0;
92 /** findlastmodtime() determines the last-modified time of the object.
93 * This must be implemented in a subclass, so that WvSync knows how to
94 * synchronize things. Called by setlastmodtime() and
97 * hasbeenmodified() determines the last-modified time of the object
98 * again, and returns true if it has changed. This is used to decide
99 * whether the object was stable during the sync, so that we can
102 virtual time_t findlastmodtime() const = 0;
103 void setlastmodtime()
104 { lastmodtime
= findlastmodtime(); }
105 time_t getlastmodtime() const
106 { return lastmodtime
; }
107 bool hasbeenmodified() const
108 { return findlastmodtime() != getlastmodtime(); }
110 /** findmeta() fetches, serializes, and returns any metadata that we
111 * want to send to the other side along with the delta. For files,
112 * this would be the mode, uid, etc. For other things, this could be
113 * anything. The default is just empty.
115 virtual WvString
findmeta()
118 { meta
= findmeta(); }
119 WvString
getmeta() const
122 /** applymeta() is called from arbremote() and friends when new meta
123 * information is received from the remote end, and we had nothing else
124 * to do. Apply the meta information to the data.
126 virtual void applymeta(WvStringParm newmeta
, time_t newmtime
)
129 /** isunchanged() checks the given mtime and meta information with the
130 * stuff stored in the object now, and returns true if they are the
131 * same. This function can be overridden to accommodate special cases,
132 * such as symlinks, where you can't change the mtime, and directories,
133 * where the time doesn't matter.
135 virtual bool isunchanged(time_t sometime
, WvStringParm somemeta
) const
136 { return sometime
== getlastmodtime() && somemeta
== getmeta(); }
138 /** issyncable() returns true if this is an object that can be
139 * synchronized. If you don't override this, it will always be true.
141 * This is mainly useful for WvSyncFile, so that we can make sure it's
142 * a regular file or symlink.
144 virtual bool issyncable() const
147 /** makecopy() makes a copy of the current object under a new name.
148 * Used when there is a conflict, so the entire thing doesn't
149 * necessarily have to be transmitted twice.
151 * You must override this.
153 virtual void makecopy(WvStringParm newname
) const = 0;
155 /** conflictname() invents a new name for an object in the event of a
156 * conflict. You can override this to accommodate whatever namespace
159 virtual WvString
conflictname(time_t sometime
) const
160 { return WvString("%s.%s", name
, sometime
); }
162 /** isdir() is true if the object is a directory that contains other
163 * objects, instead of having its own contents to synchronize.
164 * Directories have their own metadata, but that's all. They have
165 * special properties like winning all conflicts.
167 * This is sort of an ugly hack for synchronizing a filesystem. For
168 * most other applications, you can leave this set to always return
169 * false, and never think about it.
171 * The second variant analyzes metadata received from a remote object,
172 * and determines whether IT is a directory.
174 virtual bool isdir() const
176 virtual bool isdir(WvStringParm somemeta
) const
179 /** forget, revert, and revertible are used by the protocol and the
180 * scanner if they decide that the current synchronization should be
181 * aborted, and the old information should be restored.
183 * forget() erases the "old %s" entries for a given UniConf handle
184 * corresponding to an object. This should only be called when we're
185 * sure we don't need the information anymore, obviously.
187 * revert() takes the "old %s" entries and overwrites their newer
188 * counterparts. This effectively puts back the state that was present
189 * before we started synchronizing.
191 * revertible() is true if there are any "old %s" entries.
193 static void forget(UniConf
&cfg
);
194 static void revert(UniConf
&cfg
);
195 static bool revertible(UniConf
&cfg
);
197 /** installnew() is called when the protocol receives a delta and
198 * produces a patched version of the object. It's your job to do the
199 * right thing with the data, the metadata, and the mtime.
201 * FIXME: It would be nice if there was one of these that didn't use a
204 * Returns true on success.
206 virtual bool installnew(WvStringParm fname
, WvStringParm newmeta
,
207 time_t newmtime
) = 0;
213 /** approxsize() is called when generating a signature, to determine
214 * the optimal blocksize to use. If you don't override this, the
215 * default librsync blocksize (currently 2 kb) will be used. That's
216 * likely OK, but less than optimal for big files, of course. It is
217 * recommended that you override this and at least guess.
219 * A smaller blocksize gives bigger signatures, but smaller deltas.
220 * A bigger blocksize gives smaller signatures, but bigger deltas.
222 virtual off_t
approxsize() const
229 #endif // __WVSYNCOBJ_H