#include <roken.h>
+
#include <afs/opr.h>
+#ifdef AFS_PTHREAD_ENV
+# include <opr/lock.h>
+#else
+# include <opr/lockstub.h>
+#endif
+
#include <lock.h>
#include <rx/rx.h>
#include <afs/cellconfig.h>
+
#define UBIK_INTERNALS
#include "ubik.h"
#include "ubik_int.h"
struct ubik_dbase *ubik_dbase = 0;
struct ubik_stats ubik_stats;
afs_uint32 ubik_host[UBIK_MAX_INTERFACE_ADDR];
-afs_int32 ubik_epochTime = 0;
afs_int32 urecovery_state = 0;
int (*ubik_SyncWriterCacheProc) (void);
struct ubik_server *ubik_servers;
struct version_data version_globals;
#define CStampVersion 1 /* meaning set ts->version */
+#define CCheckSyncAdvertised 2 /* check if the remote knows we are the sync-site */
static_inline struct rx_connection *
Quorum_StartIO(struct ubik_trans *atrans, struct ubik_server *as)
if (!(*ts))
return 1;
UBIK_BEACON_LOCK;
- if (!(*ts)->up || !(*ts)->currentDB) {
+ if (!(*ts)->up || !(*ts)->currentDB ||
+ /* do not call DISK_Begin until we know that lastYesState is set on the
+ * remote in question; otherwise, DISK_Begin will fail. */
+ ((aflags & CCheckSyncAdvertised) && !((*ts)->beaconSinceDown && (*ts)->lastVote))) {
UBIK_BEACON_UNLOCK;
(*ts)->currentDB = 0; /* db is no longer current; we just missed an update */
return 0; /* not up-to-date, don't bother. NULL conn will tell caller not to use */
if (okcalls + 1 >= ubik_quorum)
return 0;
else
- return rcode;
+ return (rcode != 0) ? rcode : UNOQUORUM;
}
/*!
memset(&tdb->version, 0, sizeof(struct ubik_version));
memset(&tdb->cachedVersion, 0, sizeof(struct ubik_version));
#ifdef AFS_PTHREAD_ENV
- MUTEX_INIT(&tdb->versionLock, "version lock", MUTEX_DEFAULT, 0);
- MUTEX_INIT(&beacon_globals.beacon_lock, "beacon lock", MUTEX_DEFAULT, 0);
- MUTEX_INIT(&vote_globals.vote_lock, "vote lock", MUTEX_DEFAULT, 0);
- MUTEX_INIT(&addr_globals.addr_lock, "address lock", MUTEX_DEFAULT, 0);
- MUTEX_INIT(&version_globals.version_lock, "version lock", MUTEX_DEFAULT, 0);
+ opr_mutex_init(&tdb->versionLock);
+ opr_mutex_init(&beacon_globals.beacon_lock);
+ opr_mutex_init(&vote_globals.vote_lock);
+ opr_mutex_init(&addr_globals.addr_lock);
+ opr_mutex_init(&version_globals.version_lock);
#else
Lock_Init(&tdb->versionLock);
#endif
ubik_dbase = tdb; /* for now, only one db per server; can fix later when we have names for the other dbases */
#ifdef AFS_PTHREAD_ENV
- CV_INIT(&tdb->version_cond, "version", CV_DEFAULT, 0);
- CV_INIT(&tdb->flags_cond, "flags", CV_DEFAULT, 0);
+ opr_cv_init(&tdb->version_cond);
+ opr_cv_init(&tdb->flags_cond);
#endif /* AFS_PTHREAD_ENV */
/* initialize RX */
/* if we're writing already, wait */
while (dbase->flags & DBWRITING) {
#ifdef AFS_PTHREAD_ENV
- CV_WAIT(&dbase->flags_cond, &dbase->versionLock);
+ opr_cv_wait(&dbase->flags_cond, &dbase->versionLock);
#else
DBRELE(dbase);
LWP_WaitProcess(&dbase->flags);
DBRELE(dbase);
return UNOTSYNC;
}
+ if (!ubeacon_SyncSiteAdvertised()) {
+ /* i am the sync-site but the remotes are not aware yet */
+ DBRELE(dbase);
+ return UNOQUORUM;
+ }
}
/* create the transaction */
}
}
/* label trans and dbase with new tid */
- tt->tid.epoch = ubik_epochTime;
+ tt->tid.epoch = version_globals.ubik_epochTime;
/* bump by two, since tidCounter+1 means trans id'd by tidCounter has finished */
tt->tid.counter = (dbase->tidCounter += 2);
if (transMode == UBIK_WRITETRANS) {
/* for a write trans, we have to keep track of the write tid counter too */
dbase->writeTidCounter = tt->tid.counter;
+ }
+
+ UBIK_VERSION_UNLOCK;
+ if (transMode == UBIK_WRITETRANS) {
/* next try to start transaction on appropriate number of machines */
- code = ContactQuorum_NoArguments(DISK_Begin, tt, 0);
+ code = ContactQuorum_NoArguments(DISK_Begin, tt, CCheckSyncAdvertised);
if (code) {
/* we must abort the operation */
udisk_abort(tt);
ContactQuorum_NoArguments(DISK_Abort, tt, 0); /* force aborts to the others */
udisk_end(tt);
- UBIK_VERSION_UNLOCK;
DBRELE(dbase);
return code;
}
}
*transPtr = tt;
- UBIK_VERSION_UNLOCK;
DBRELE(dbase);
return 0;
}
return 0;
}
#ifdef AFS_PTHREAD_ENV
- CV_WAIT(&adatabase->version_cond, &adatabase->versionLock);
+ opr_cv_wait(&adatabase->version_cond, &adatabase->versionLock);
#else
DBRELE(adatabase);
LWP_WaitProcess(&adatabase->version); /* same vers, just wait */
va_list ap;
va_start(ap, format);
- ubik_print("Ubik PANIC: ");
+ ubik_print("Ubik PANIC:\n");
ubik_vprint(format, ap);
va_end(ap);