#ifdef AFS_NT40_ENV
#include <winsock2.h>
#include <time.h>
+#include <fcntl.h>
#else
#include <sys/file.h>
#include <netinet/in.h>
struct timeval tv;
int length, tlen, offset, file, nbytes;
struct rx_call *rxcall;
- char tbuffer[256];
+ char tbuffer[1024];
struct ubik_stat ubikstat;
struct in_addr inAddr;
+#ifndef OLD_URECOVERY
+ char pbuffer[1028];
+ int flen, fd = -1;
+#endif
/* otherwise, begin interaction */
urecovery_state = 0;
urecovery_state |= UBIK_RECHAVEDB;
} else {
/* we don't have the best version; we should fetch it. */
-#if defined(UBIK_PAUSE)
DBHOLD(ubik_dbase);
-#else
- ObtainWriteLock(&ubik_dbase->versionLock);
-#endif /* UBIK_PAUSE */
urecovery_AbortAll(ubik_dbase);
/* Rx code to do the Bulk fetch */
goto FetchEndCall;
}
- /* Truncate the file firest */
+#ifdef OLD_URECOVERY
+ /* Truncate the file first */
code = (*ubik_dbase->truncate) (ubik_dbase, file, 0);
if (code) {
ubik_dprint("truncate io error=%d\n", code);
ubik_dprint("setlabel io error=%d\n", code);
goto FetchEndCall;
}
+#else
+ flen = length;
+ afs_snprintf(pbuffer, sizeof(pbuffer), "%s.DB0.TMP", ubik_dbase->pathName);
+ fd = open(pbuffer, O_CREAT | O_RDWR | O_TRUNC, 0600);
+ if (fd < 0) {
+ code = errno;
+ goto FetchEndCall;
+ }
+ code = lseek(fd, HDRSIZE, 0);
+ if (code != HDRSIZE) {
+ close(fd);
+ goto FetchEndCall;
+ }
+#endif
while (length > 0) {
tlen = (length > sizeof(tbuffer) ? sizeof(tbuffer) : length);
if (nbytes != tlen) {
ubik_dprint("Rx-read bulk error=%d\n", code = BULK_ERROR);
code = EIO;
+ close(fd);
goto FetchEndCall;
}
+#ifdef OLD_URECOVERY
nbytes =
(*ubik_dbase->write) (ubik_dbase, file, tbuffer, offset,
tlen);
+#else
+ nbytes = write(fd, tbuffer, tlen);
+#endif
if (nbytes != tlen) {
code = UIOERROR;
+ close(fd);
goto FetchEndCall;
}
offset += tlen;
length -= tlen;
}
+#ifndef OLD_URECOVERY
+ code = close(fd);
+ if (code)
+ goto FetchEndCall;
+#endif
code = EndDISK_GetFile(rxcall, &tversion);
FetchEndCall:
tcode = rx_EndCall(rxcall, code);
urecovery_state |= UBIK_RECHAVEDB;
memcpy(&ubik_dbase->version, &tversion,
sizeof(struct ubik_version));
+#ifdef OLD_URECOVERY
(*ubik_dbase->sync) (ubik_dbase, 0); /* get data out first */
+#else
+ afs_snprintf(tbuffer, sizeof(tbuffer), "%s.DB0", ubik_dbase->pathName);
+#ifdef AFS_NT40_ENV
+ afs_snprintf(pbuffer, sizeof(pbuffer), "%s.DB0.OLD", ubik_dbase->pathName);
+ code = unlink(pbuffer);
+ if (!code)
+ code = rename(tbuffer, pbuffer);
+ afs_snprintf(pbuffer, sizeof(pbuffer), "%s.DB0.TMP", ubik_dbase->pathName);
+#endif
+ if (!code)
+ code = rename(pbuffer, tbuffer);
+ if (!code)
+#endif
/* after data is good, sync disk with correct label */
code =
(*ubik_dbase->setlabel) (ubik_dbase, 0,
&ubik_dbase->version);
+#ifndef OLD_URECOVERY
+#ifdef AFS_NT40_ENV
+ afs_snprintf(pbuffer, sizeof(pbuffer), "%s.DB0.OLD", ubik_dbase->pathName);
+ unlink(pbuffer);
+#endif
+#endif
}
if (code) {
+#ifndef OLD_URECOVERY
+ unlink(pbuffer);
+#endif
ubik_dbase->version.epoch = 0;
ubik_dbase->version.counter = 0;
ubik_print("Ubik: Synchronize database failed (error = %d)\n",
}
udisk_Invalidate(ubik_dbase, 0); /* data has changed */
LWP_NoYieldSignal(&ubik_dbase->version);
-#if defined(UBIK_PAUSE)
DBRELE(ubik_dbase);
-#else
- ReleaseWriteLock(&ubik_dbase->versionLock);
-#endif /* UBIK_PAUSE */
}
#if defined(UBIK_PAUSE)
if (!(urecovery_state & UBIK_RECSYNCSITE))
* database and overwrite this one.
*/
if (ubik_dbase->version.epoch == 1) {
-#if defined(UBIK_PAUSE)
DBHOLD(ubik_dbase);
-#else
- ObtainWriteLock(&ubik_dbase->versionLock);
-#endif /* UBIK_PAUSE */
urecovery_AbortAll(ubik_dbase);
ubik_epochTime = 2;
ubik_dbase->version.epoch = ubik_epochTime;
(*ubik_dbase->setlabel) (ubik_dbase, 0, &ubik_dbase->version);
udisk_Invalidate(ubik_dbase, 0); /* data may have changed */
LWP_NoYieldSignal(&ubik_dbase->version);
-#if defined(UBIK_PAUSE)
DBRELE(ubik_dbase);
-#else
- ReleaseWriteLock(&ubik_dbase->versionLock);
-#endif /* UBIK_PAUSE */
}
/* Check the other sites and send the database to them if they
/* now propagate out new version to everyone else */
dbok = 1; /* start off assuming they all worked */
-#if defined(UBIK_PAUSE)
DBHOLD(ubik_dbase);
-#else
- ObtainWriteLock(&ubik_dbase->versionLock);
-#endif /* UBIK_PAUSE */
/*
* Check if a write transaction is in progress. We can't send the
* db when a write is in progress here because the db would be
tv.tv_sec = 0;
tv.tv_usec = 50000;
while ((ubik_dbase->flags & DBWRITING) && (safety < 500)) {
-#if defined(UBIK_PAUSE)
DBRELE(ubik_dbase);
-#else
- ReleaseWriteLock(&ubik_dbase->versionLock);
-#endif /* UBIK_PAUSE */
/* sleep for a little while */
IOMGR_Select(0, 0, 0, 0, &tv);
tv.tv_usec += 10000;
safety++;
-#if defined(UBIK_PAUSE)
DBHOLD(ubik_dbase);
-#else
- ObtainWriteLock(&ubik_dbase->versionLock);
-#endif /* UBIK_PAUSE */
}
}
ts->currentDB = 1;
}
}
-#if defined(UBIK_PAUSE)
DBRELE(ubik_dbase);
-#else
- ReleaseWriteLock(&ubik_dbase->versionLock);
-#endif /* UBIK_PAUSE */
if (dbok)
urecovery_state |= UBIK_RECSENTDB;
}
#include <sys/types.h>
#ifdef AFS_NT40_ENV
#include <winsock2.h>
+#include <fcntl.h>
#else
#include <sys/file.h>
#include <netinet/in.h>
#include <lock.h>
#include <rx/xdr.h>
#include <rx/rx.h>
+#include <errno.h>
#include <afs/afsutil.h>
#define UBIK_INTERNALS
{
register afs_int32 code;
register struct ubik_dbase *dbase;
- char tbuffer[256];
+ char tbuffer[1024];
afs_int32 offset;
struct ubik_version tversion;
register int tlen;
struct rx_peer *tpeer;
struct rx_connection *tconn;
afs_uint32 otherHost;
+#ifndef OLD_URECOVERY
+ char pbuffer[1028];
+ int flen, fd = -1;
+#endif
/* send the file back to the requester */
afs_inet_ntoa(otherHost));
offset = 0;
+#ifdef OLD_URECOVERY
(*dbase->truncate) (dbase, file, 0); /* truncate first */
tversion.epoch = 0; /* start off by labelling in-transit db as invalid */
tversion.counter = 0;
(*dbase->setlabel) (dbase, file, &tversion); /* setlabel does sync */
+#else
+ flen = length;
+ afs_snprintf(pbuffer, sizeof(pbuffer), "%s.DB0.TMP", ubik_dbase->pathName);
+ fd = open(pbuffer, O_CREAT | O_RDWR | O_TRUNC, 0600);
+ if (fd < 0) {
+ code = errno;
+ goto failed;
+ }
+ code = lseek(fd, HDRSIZE, 0);
+ if (code != HDRSIZE) {
+ close(fd);
+ goto failed;
+ }
+#endif
memcpy(&ubik_dbase->version, &tversion, sizeof(struct ubik_version));
while (length > 0) {
tlen = (length > sizeof(tbuffer) ? sizeof(tbuffer) : length);
DBRELE(dbase);
ubik_dprint("Rx-read length error=%d\n", code);
code = BULK_ERROR;
+ close(fd);
goto failed;
}
+#ifdef OLD_URECOVERY
code = (*dbase->write) (dbase, file, tbuffer, offset, tlen);
+#else
+ code = write(fd, tbuffer, tlen);
+#endif
if (code != tlen) {
DBRELE(dbase);
ubik_dprint("write failed error=%d\n", code);
code = UIOERROR;
+ close(fd);
goto failed;
}
offset += tlen;
length -= tlen;
}
+#ifndef OLD_URECOVERY
+ code = close(fd);
+ if (code)
+ goto failed;
+#endif
/* sync data first, then write label and resync (resync done by setlabel call).
* This way, good label is only on good database. */
+#ifdef OLD_URECOVERY
(*ubik_dbase->sync) (dbase, file);
+#else
+ afs_snprintf(tbuffer, sizeof(tbuffer), "%s.DB0", ubik_dbase->pathName);
+#ifdef AFS_NT40_ENV
+ afs_snprintf(pbuffer, sizeof(pbuffer), "%s.DB0.OLD", ubik_dbase->pathName);
+ code = unlink(pbuffer);
+ if (!code)
+ code = rename(tbuffer, pbuffer);
+ afs_snprintf(pbuffer, sizeof(pbuffer), "%s.DB0.TMP", ubik_dbase->pathName);
+#endif
+ if (!code)
+ code = rename(pbuffer, tbuffer);
+ if (!code)
+#endif
code = (*ubik_dbase->setlabel) (dbase, file, avers);
+#ifndef OLD_URECOVERY
+#ifdef AFS_NT40_ENV
+ afs_snprintf(pbuffer, sizeof(pbuffer), "%s.DB0.OLD", ubik_dbase->pathName);
+ unlink(pbuffer);
+#endif
+#endif
memcpy(&ubik_dbase->version, avers, sizeof(struct ubik_version));
udisk_Invalidate(dbase, file); /* new dbase, flush disk buffers */
LWP_NoYieldSignal(&dbase->version);
DBRELE(dbase);
failed:
if (code) {
+#ifndef OLD_URECOVERY
+ unlink(pbuffer);
+#endif
ubik_print
("Ubik: Synchronize database with server %s failed (error = %d)\n",
afs_inet_ntoa(otherHost), code);