vos-release-compare-update-timestamps-20050415
[openafs.git] / src / volser / vsprocs.c
index 6ca2273..9dfb885 100644 (file)
@@ -68,7 +68,8 @@ struct ubik_client *cstruct;
 int verbose = 0;
 
 struct release {
-    afs_int32 time;
+    afs_int32 crtime;
+    afs_int32 uptime;
     afs_int32 vldbEntryIndex;
 };
 
@@ -162,12 +163,11 @@ static int DelVol(struct rx_connection *conn, afs_int32 vid, afs_int32 part,
                  afs_int32 flags);
 static int GetTrans(struct nvldbentry *vldbEntryPtr, afs_int32 index,
                    struct rx_connection **connPtr, afs_int32 * transPtr,
-                   afs_int32 * timePtr);
+                   afs_int32 * crtimePtr, afs_int32 * uptimePtr);
 static int SimulateForwardMultiple(struct rx_connection *fromconn,
                                   afs_int32 fromtid, afs_int32 fromdate,
                                   manyDests * tr, afs_int32 flags,
                                   void *cookie, manyResults * results);
-static int rel_compar(struct release *r1, struct release *r2);
 static afs_int32 CheckVolume(volintInfo * volumeinfo, afs_int32 aserver,
                             afs_int32 apart, afs_int32 * modentry,
                             afs_uint32 * maxvolid);
@@ -406,6 +406,19 @@ PrintError(char *msg, afs_int32 errcode)
     return 0;
 }
 
+void init_volintInfo(struct volintInfo *vinfo) {
+    memset(vinfo, 0, sizeof(struct volintInfo));
+
+    vinfo->maxquota = -1;
+    vinfo->dayUse = -1;
+    vinfo->creationDate = -1;
+    vinfo->updateDate = -1;
+    vinfo->flags = -1;
+    vinfo->spare0 = -1;
+    vinfo->spare1 = -1;
+    vinfo->spare2 = -1;
+    vinfo->spare3 = -1;
+}
 
 static struct rx_securityClass *uvclass = 0;
 static int uvindex = -1;
@@ -532,9 +545,10 @@ SubEnumerateEntry(struct nvldbentry *entry)
            fprintf(STDOUT, "RO Site ");
        if (isMixed) {
            if (entry->serverFlags[i] & NEW_REPSITE)
-               fprintf(STDOUT, " -- New release");
+               fprintf(STDOUT," -- New release");
            else
-               fprintf(STDOUT, " -- Old release");
+               if (!(entry->serverFlags[i] & ITSRWVOL))
+                   fprintf(STDOUT," -- Old release");
        } else {
            if (entry->serverFlags[i] & RO_DONTUSE)
                fprintf(STDOUT, " -- Not released");
@@ -623,8 +637,8 @@ UV_CreateVolume2(afs_int32 aserver, afs_int32 apart, char *aname,
     tid = 0;
     aconn = (struct rx_connection *)0;
     error = 0;
-    memset(&tstatus, 0, sizeof(struct volintInfo));
-    tstatus.dayUse = -1;
+
+    init_volintInfo(&tstatus);
     tstatus.maxquota = aquota;
 
     aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
@@ -1337,6 +1351,8 @@ UV_MoveVolume2(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart,
 
     infop = (volintInfo *) volumeInfo.volEntries_val;
     infop->maxquota = -1;      /* Else it will replace the default quota */
+    infop->creationDate = -1;  /* Else it will use the source creation date */
+    infop->updateDate = -1;    /* Else it will use the source update date */
 #endif
 
     /* create a volume on the target machine */
@@ -2990,15 +3006,16 @@ DelVol(struct rx_connection *conn, afs_int32 vid, afs_int32 part,
 static int
 GetTrans(struct nvldbentry *vldbEntryPtr, afs_int32 index,
         struct rx_connection **connPtr, afs_int32 * transPtr,
-        afs_int32 * timePtr)
+        afs_int32 * crtimePtr, afs_int32 * uptimePtr)
 {
     afs_int32 volid;
     struct volser_status tstatus;
     int code, rcode, tcode;
 
     *connPtr = (struct rx_connection *)0;
-    *timePtr = 0;
     *transPtr = 0;
+    *crtimePtr = 0;
+    *uptimePtr = 0;
 
     /* get connection to the replication site */
     *connPtr = UV_Bind(vldbEntryPtr->serverNumber[index], AFSCONF_VOLUMEPORT);
@@ -3070,7 +3087,8 @@ GetTrans(struct nvldbentry *vldbEntryPtr, afs_int32 index,
                       code);
            goto fail;
        }
-       *timePtr = tstatus.creationDate - CLOCKSKEW;
+       *crtimePtr = tstatus.creationDate - CLOCKSKEW;
+       *uptimePtr = tstatus.updateDate - CLOCKSKEW;
     }
 
     return 0;
@@ -3105,12 +3123,6 @@ SimulateForwardMultiple(struct rx_connection *fromconn, afs_int32 fromtid,
 }
 
 
-static int
-rel_compar(struct release *r1, struct release *r2)
-{
-    return (r1->time - r2->time);
-}
-
 /* UV_ReleaseVolume()
  *    Release volume <afromvol> on <afromserver> <afrompart> to all
  *    its RO sites (full release). Unless the previous release was
@@ -3150,10 +3162,10 @@ UV_ReleaseVolume(afs_int32 afromvol, afs_int32 afromserver,
     manyDests tr;
     manyResults results;
     int rwindex, roindex, roclone, roexists;
-    afs_int32 rwcrdate, clcrdate;
+    afs_int32 rwcrdate, rwupdate, clcrdate;
     struct rtime {
        int validtime;
-       afs_uint32 time;
+       afs_uint32 uptime;
     } remembertime[NMAXNSERVERS];
     int releasecount = 0;
     struct volser_status volstatus;
@@ -3213,11 +3225,13 @@ UV_ReleaseVolume(afs_int32 afromvol, afs_int32 afromserver,
     }
 
     /* Will we be completing a previously unfinished release. -force overrides */
-    for (fullrelease = 1, i = 0; (fullrelease && (i < entry.nServers)); i++) {
-       if (entry.serverFlags[i] & NEW_REPSITE)
-           fullrelease = 0;
+    for (s = 0, m = 0, fullrelease=0, i=0; (i<entry.nServers); i++) {
+       if (entry.serverFlags[i] & ITSROVOL) {
+           m++;
+           if (entry.serverFlags[i] & NEW_REPSITE) s++;
+       }
     }
-    if (forceflag && !fullrelease)
+    if ((forceflag && !fullrelease) || (s == m) || (s == 0))
        fullrelease = 1;
 
     /* Determine which volume id to use and see if it exists */
@@ -3248,6 +3262,7 @@ UV_ReleaseVolume(afs_int32 afromvol, afs_int32 afromserver,
            ONERROR(code, afromvol,
                    "Failed to get the status of RW volume %u\n");
            rwcrdate = volstatus.creationDate;
+           rwupdate = volstatus.updateDate;
 
            /* End transaction on RW */
            code = AFSVolEndTrans(fromconn, fromtid, &rcode);
@@ -3268,11 +3283,11 @@ UV_ReleaseVolume(afs_int32 afromvol, afs_int32 afromserver,
                    "Failed to get the status of RW clone %u\n");
            clcrdate = volstatus.creationDate;
 
-           /* End transaction on RW */
+           /* End transaction on clone */
            code = AFSVolEndTrans(fromconn, clonetid, &rcode);
            clonetid = 0;
            ONERROR((code ? code : rcode), cloneVolId,
-                   "Failed to end transaction on RW volume %u\n");
+                   "Failed to end transaction on RW clone %u\n");
 
            if (rwcrdate > clcrdate)
                fullrelease = 2;/* Do a full release if RO clone older than RW */
@@ -3336,10 +3351,10 @@ UV_ReleaseVolume(afs_int32 afromvol, afs_int32 afromserver,
            if (roclone) {
                strcpy(vname, entry.name);
                strcat(vname, ".readonly");
-               VPRINT("Cloning RW volume %u to permanent RO...");
+               VPRINT1("Cloning RW volume %u to permanent RO...", afromvol);
            } else {
                strcpy(vname, "readonly-clone-temp");
-               VPRINT("Cloning RW volume %u to temporary RO...");
+               VPRINT1("Cloning RW volume %u to temporary RO...", afromvol);
            }
            code =
                AFSVolClone(fromconn, clonetid, 0, readonlyVolume, vname,
@@ -3349,18 +3364,19 @@ UV_ReleaseVolume(afs_int32 afromvol, afs_int32 afromserver,
        }
 
        /* Get the time the RW was created for future information */
-       VPRINT1("Getting status of RW volume %u...", cloneVolId);
+       VPRINT1("Getting status of RW volume %u...", afromvol);
        code = AFSVolGetStatus(fromconn, clonetid, &volstatus);
-       ONERROR(code, cloneVolId,
+       ONERROR(code, afromvol,
                "Failed to get the status of the RW volume %u\n");
        VDONE;
        rwcrdate = volstatus.creationDate;
+       rwupdate = volstatus.updateDate;
 
        /* End the transaction on the RW volume */
-       VPRINT1("Ending cloning transaction on RW volume %u...", cloneVolId);
+       VPRINT1("Ending cloning transaction on RW volume %u...", afromvol);
        code = AFSVolEndTrans(fromconn, clonetid, &rcode);
        clonetid = 0;
-       ONERROR((code ? code : rcode), cloneVolId,
+       ONERROR((code ? code : rcode), afromvol,
                "Failed to end cloning transaction on RW %u\n");
        VDONE;
 
@@ -3502,13 +3518,14 @@ UV_ReleaseVolume(afs_int32 afromvol, afs_int32 afromserver,
            code =
                GetTrans(&entry, vldbindex, &(toconns[volcount]),
                         &(replicas[volcount].trans),
-                        &(times[volcount].time));
+                        &(times[volcount].crtime),
+                        &(times[volcount].uptime));
            if (code)
                continue;
 
            /* Thisdate is the date from which we want to pick up all changes */
            if (forceflag || !fullrelease
-               || (rwcrdate > times[volcount].time)) {
+               || (rwcrdate > times[volcount].crtime)) {
                /* If the forceflag is set, then we want to do a full dump.
                 * If it's not a full release, we can't be sure that the creation
                 *  date is good (so we also do a full dump).
@@ -3523,14 +3540,14 @@ UV_ReleaseVolume(afs_int32 afromvol, afs_int32 afromserver,
                 * case time[volcount].time would be now instead of 0.
                 */
                thisdate =
-                   (remembertime[vldbindex].time <
-                    times[volcount].time) ? remembertime[vldbindex].
-                   time : times[volcount].time;
+                   (remembertime[vldbindex].uptime < times[volcount].uptime)
+                       ? remembertime[vldbindex].uptime
+                       : times[volcount].uptime;
            } else {
-               thisdate = times[volcount].time;
+               thisdate = times[volcount].uptime;
            }
            remembertime[vldbindex].validtime = 1;
-           remembertime[vldbindex].time = thisdate;
+           remembertime[vldbindex].uptime = thisdate;
 
            if (volcount == 0) {
                fromdate = thisdate;
@@ -3568,6 +3585,8 @@ UV_ReleaseVolume(afs_int32 afromvol, afs_int32 afromserver,
 
            if (fromdate == 0)
                fprintf(STDOUT, " (full release)");
+           else
+               fprintf(STDOUT, " (as of %.24s)", ctime((time_t *)&fromdate));
            fprintf(STDOUT, ".\n");
            fflush(STDOUT);
        }
@@ -4037,6 +4056,7 @@ UV_RestoreVolume(afs_int32 toserver, afs_int32 topart, afs_int32 tovolid,
     afs_int32 totid, code, rcode, vcode, terror = 0;
     afs_int32 rxError = 0;
     struct volser_status tstatus;
+    struct volintInfo vinfo;
     char partName[10];
     afs_int32 pvolid;
     afs_int32 temptid;
@@ -4046,7 +4066,8 @@ UV_RestoreVolume(afs_int32 toserver, afs_int32 topart, afs_int32 tovolid,
     int islocked;
     struct restoreCookie cookie;
     int reuseID;
-    afs_int32 newDate, volflag, voltype, volsertype;
+    afs_int32 volflag, voltype, volsertype;
+    afs_int32 oldCreateDate, oldUpdateDate, newCreateDate, newUpdateDate;
     int index, same, errcode;
     char apartName[10];
 
@@ -4126,6 +4147,13 @@ UV_RestoreVolume(afs_int32 toserver, afs_int32 topart, afs_int32 tovolid,
            EGOTO1(refail, code, "Failed to start transaction on %u\n",
                   pvolid);
 
+           code = AFSVolGetStatus(toconn, totid, &tstatus);
+           EGOTO1(refail, code, "Could not get timestamp from volume %u\n",
+                  pvolid);
+
+           oldCreateDate = tstatus.creationDate;
+           oldUpdateDate = tstatus.updateDate;
+
            code =
                AFSVolSetFlags(toconn, totid,
                               VTDeleteOnSalvage | VTOutOfService);
@@ -4147,8 +4175,6 @@ UV_RestoreVolume(afs_int32 toserver, afs_int32 topart, afs_int32 tovolid,
                AFSVolCreateVolume(toconn, topart, tovolname, volsertype, 0,
                                   &pvolid, &totid);
            EGOTO1(refail, code, "Could not create new volume %u\n", pvolid);
-
-           newDate = 0;
        } else {
            code =
                AFSVolTransCreate(toconn, pvolid, topart, ITOffline, &totid);
@@ -4158,9 +4184,15 @@ UV_RestoreVolume(afs_int32 toserver, afs_int32 topart, afs_int32 tovolid,
            code = AFSVolGetStatus(toconn, totid, &tstatus);
            EGOTO1(refail, code, "Could not get timestamp from volume %u\n",
                   pvolid);
-           newDate = tstatus.creationDate;
+
+           oldCreateDate = tstatus.creationDate;
+           oldUpdateDate = tstatus.updateDate;
        }
+    } else {
+       oldCreateDate = 0;
+       oldUpdateDate = 0;
     }
+
     cookie.parent = pvolid;
     cookie.type = voltype;
     cookie.clone = 0;
@@ -4201,12 +4233,33 @@ UV_RestoreVolume(afs_int32 toserver, afs_int32 topart, afs_int32 tovolid,
        error = code;
        goto refail;
     }
-    if (!newDate)
-       newDate = time(0);
-    code = AFSVolSetDate(toconn, totid, newDate);
+
+    if (flags & RV_CRDUMP)
+       newCreateDate = tstatus.creationDate;
+    else if (flags & RV_CRKEEP && oldCreateDate != 0)
+       newCreateDate = oldCreateDate;
+    else
+       newCreateDate = time(0);
+    if (flags & RV_LUDUMP)
+       newUpdateDate = tstatus.updateDate;
+    else if (flags & RV_LUKEEP)
+       newUpdateDate = oldUpdateDate;
+    else
+       newUpdateDate = time(0);
+    code = AFSVolSetDate(toconn,totid, newCreateDate);
+    if (code) {
+       fprintf(STDERR, "Could not set the 'creation' date on %u\n", pvolid);
+       error = code;
+       goto refail;
+    }
+
+    init_volintInfo(&vinfo);
+    vinfo.creationDate = newCreateDate;
+    vinfo.updateDate = newUpdateDate;
+    code = AFSVolSetInfo(toconn, totid, &vinfo);
     if (code) {
-       fprintf(STDERR, "Could not set the date on %lu\n",
-               (unsigned long)pvolid);
+       fprintf(STDERR, "Could not set the 'last updated' date on %u\n",
+               pvolid);
        error = code;
        goto refail;
     }