Oops, my fix to subdir.mk didn't work with existing symlinks. Fixed.
[wvapps.git] / wvsync / wvsyncobj.h
blobd787b41261c883ad336d8d0fd04e26210df20488
1 /*
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.
12 #ifndef __WVSYNCOBJ_H
13 #define __WVSYNCOBJ_H
15 #include <wvbuf.h>
16 #include <wvstring.h>
17 #include <wvlog.h>
18 #include <wvfile.h>
19 #include <uniconf.h>
21 class WvSyncObj;
22 typedef WvCallback<void, WvSyncObj&, WvBuf&> WvSyncCallback;
24 class WvSyncObj
26 public:
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
74 { return true; }
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
83 * block.
85 * Takes a buffer to put the data in, the offset we want, and the size
86 * we want.
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
95 * hasbeenmodified().
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
100 * overwrite it.
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()
116 { return ""; }
117 void setmeta()
118 { meta = findmeta(); }
119 WvString getmeta() const
120 { return meta; }
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
145 { return true; }
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
157 * you live in.
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
175 { return false; }
176 virtual bool isdir(WvStringParm somemeta) const
177 { return false; }
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
202 * temporary file.
204 * Returns true on success.
206 virtual bool installnew(WvStringParm fname, WvStringParm newmeta,
207 time_t newmtime) = 0;
209 private:
210 time_t lastmodtime;
211 WvString meta;
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
223 { return -1; }
225 protected:
226 WvLog log, err;
229 #endif // __WVSYNCOBJ_H