Files
ncpfs/lib/ds/partops.c
2026-04-28 20:56:03 +02:00

868 lines
21 KiB
C

/*
partops.c
Copyright (C) 2000 Petr Vandrovec
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Revision history:
1.00 2000, April 26 Petr Vandrovec <vandrove@vc.cvut.cz>
Initial version, NWDSAbortPartitionOperation.
1.01 2000, April 27 Petr Vandrovec <vandrove@vc.cvut.cz>
Added NWDSJoinPartitions.
Added NWDSListPartitions.
1.02 2000, April 28 Petr Vandrovec <vandrove@vc.cvut.cz>
Added NWDSListPartitionsExtInfo.
Added NWDSGetPartitionInfo.
Added NWDSGetPartitionExtInfoPtr.
Added NWDSGetPartitionExtInfo.
Added NWDSSplitPartition.
Added NWDSRemovePartition.
1.03 2000, April 29 Petr Vandrovec <vandrove@vc.cvut.cz>
Added NWDSAddReplica.
Added NWDSRemoveReplica.
Added NWDSChangeReplicaType.
1.04 2000, April 30 Petr Vandrovec <vandrove@vc.cvut.cz>
Added NWDSPartitionReceiveAllUpdates.
Added NWDSPartitionSendAllUpdates.
Added NWDSSyncPartition.
Added NWDSGetPartitionRoot.
1.05 2000, May 1 Petr Vandrovec <vandrove@vc.cvut.cz>
Added NWDSRepairTimeStamps.
*/
#include <ncp/nwcalls.h>
#include "nwnet_i.h"
static NWDSCCODE __NWDSAbortPartitionOperationV3(
NWCONN_HANDLE conn,
nflag32 flags,
NWObjectID partitionID
) {
NW_FRAGMENT rq_frag[1];
nuint8 rq_b[12];
DSET_LH(rq_b, 0, 3);
DSET_LH(rq_b, 4, flags);
DSET_HL(rq_b, 8, partitionID);
rq_frag[0].fragAddr.ro = rq_b;
rq_frag[0].fragSize = 12;
return NWCFragmentRequest(conn, DSV_ABORT_PARTITION_OPERATION,
1, rq_frag, 0, NULL, NULL);
}
NWDSCCODE NWDSAbortPartitionOperation(
NWDSContextHandle ctx,
const NWDSChar* partitionRoot
) {
NWCONN_HANDLE conn;
NWObjectID partitionID;
NWDSCCODE dserr;
dserr = NWDSResolveName2DR(ctx, partitionRoot,
DS_RESOLVE_DEREF_ALIASES | DS_RESOLVE_MASTER,
&conn, &partitionID);
if (dserr)
return dserr;
dserr = __NWDSAbortPartitionOperationV3(conn, 0, partitionID);
NWCCCloseConn(conn);
return dserr;
}
static NWDSCCODE __NWDSJoinPartitionsV0(
NWCONN_HANDLE conn,
nflag32 flags,
NWObjectID partitionID
) {
NW_FRAGMENT rq_frag[1];
nuint8 rq_b[12];
DSET_LH(rq_b, 0, 0);
DSET_LH(rq_b, 4, flags);
DSET_HL(rq_b, 8, partitionID);
rq_frag[0].fragAddr.ro = rq_b;
rq_frag[0].fragSize = 12;
return NWCFragmentRequest(conn, DSV_JOIN_PARTITIONS,
1, rq_frag, 0, NULL, NULL);
}
NWDSCCODE NWDSJoinPartitions(
NWDSContextHandle ctx,
const NWDSChar* subordinatePartition,
nflag32 flags
) {
NWCONN_HANDLE conn;
NWObjectID partitionID;
NWDSCCODE dserr;
dserr = NWDSResolveName2DR(ctx, subordinatePartition,
DS_RESOLVE_DEREF_ALIASES | DS_RESOLVE_MASTER,
&conn, &partitionID);
if (dserr)
return dserr;
dserr = __NWDSJoinPartitionsV0(conn, flags, partitionID);
NWCCCloseConn(conn);
return dserr;
}
static NWDSCCODE __NWDSSplitPartitionV0(
NWCONN_HANDLE conn,
nflag32 flags,
NWObjectID partitionID
) {
NW_FRAGMENT rq_frag[1];
nuint8 rq_b[12];
DSET_LH(rq_b, 0, 0);
DSET_LH(rq_b, 4, flags);
DSET_HL(rq_b, 8, partitionID);
rq_frag[0].fragAddr.ro = rq_b;
rq_frag[0].fragSize = 12;
return NWCFragmentRequest(conn, DSV_SPLIT_PARTITION,
1, rq_frag, 0, NULL, NULL);
}
NWDSCCODE NWDSSplitPartition(
NWDSContextHandle ctx,
const NWDSChar* subordinatePartition,
nflag32 flags
) {
NWCONN_HANDLE conn;
NWObjectID partitionID;
NWDSCCODE dserr;
dserr = NWDSResolveName2DR(ctx, subordinatePartition,
/* FIXME: master or read-write? */
DS_RESOLVE_DEREF_ALIASES | DS_RESOLVE_MASTER,
&conn, &partitionID);
if (dserr)
return dserr;
dserr = __NWDSSplitPartitionV0(conn, flags, partitionID);
NWCCCloseConn(conn);
return dserr;
}
static NWDSCCODE __NWDSRemovePartitionV0(
NWCONN_HANDLE conn,
nflag32 flags,
NWObjectID partitionID
) {
NW_FRAGMENT rq_frag[1];
nuint8 rq_b[12];
DSET_LH(rq_b, 0, 0);
DSET_LH(rq_b, 4, flags);
DSET_HL(rq_b, 8, partitionID);
rq_frag[0].fragAddr.ro = rq_b;
rq_frag[0].fragSize = 12;
return NWCFragmentRequest(conn, DSV_REMOVE_PARTITION,
1, rq_frag, 0, NULL, NULL);
}
NWDSCCODE NWDSRemovePartition(
NWDSContextHandle ctx,
const NWDSChar* partitionRoot
) {
NWCONN_HANDLE conn;
NWObjectID partitionID;
NWDSCCODE dserr;
dserr = NWDSResolveName2DR(ctx, partitionRoot,
/* FIXME: master or read-write? */
DS_RESOLVE_DEREF_ALIASES | DS_RESOLVE_MASTER,
&conn, &partitionID);
if (dserr)
return dserr;
dserr = __NWDSRemovePartitionV0(conn, 0, partitionID);
NWCCCloseConn(conn);
return dserr;
}
static NWDSCCODE __NWDSListPartitionsV0(
NWCONN_HANDLE conn,
nuint32 qflags,
nuint32* iterHandle,
Buf_T* partitions
) {
NW_FRAGMENT rq_frag[1];
NW_FRAGMENT rp_frag[2];
nuint8 rq_b[12];
nuint8 rp_b[4];
NWDSCCODE dserr;
DSET_LH(rq_b, 0, 0);
DSET_LH(rq_b, 4, qflags);
DSET_LH(rq_b, 8, *iterHandle);
rq_frag[0].fragAddr.ro = rq_b;
rq_frag[0].fragSize = 12;
rp_frag[0].fragAddr.rw = rp_b;
rp_frag[0].fragSize = 4;
NWDSBufStartPut(partitions, DSV_LIST_PARTITIONS);
NWDSBufSetDSIFlags(partitions, DSP_PARTITION_DN | DSP_REPLICA_TYPE);
rp_frag[1].fragAddr.rw = NWDSBufPutPtrLen(partitions, &rp_frag[1].fragSize);
dserr = NWCFragmentRequest(conn, DSV_LIST_PARTITIONS, 1, rq_frag,
2, rp_frag, NULL);
if (dserr)
return dserr;
if (rp_frag[1].fragSize < 1)
return ERR_INVALID_SERVER_RESPONSE;
*iterHandle = DVAL_LH(rp_b, 0);
NWDSBufPutSkip(partitions, rp_frag[1].fragSize);
NWDSBufFinishPut(partitions);
return 0;
}
static NWDSCCODE __NWDSListPartitionsV1(
NWCONN_HANDLE conn,
nuint32 qflags,
nflag32 dspFlags,
nuint32* iterHandle,
Buf_T* partitions
) {
NW_FRAGMENT rq_frag[1];
NW_FRAGMENT rp_frag[2];
nuint8 rq_b[16];
nuint8 rp_b[4];
NWDSCCODE dserr;
DSET_LH(rq_b, 0, 1);
DSET_LH(rq_b, 4, qflags);
DSET_LH(rq_b, 8, *iterHandle);
DSET_LH(rq_b, 12, dspFlags);
rq_frag[0].fragAddr.ro = rq_b;
rq_frag[0].fragSize = 16;
rp_frag[0].fragAddr.rw = rp_b;
rp_frag[0].fragSize = 4;
NWDSBufStartPut(partitions, DSV_LIST_PARTITIONS);
NWDSBufSetDSIFlags(partitions, dspFlags);
rp_frag[1].fragAddr.rw = NWDSBufPutPtrLen(partitions, &rp_frag[1].fragSize);
dserr = NWCFragmentRequest(conn, DSV_LIST_PARTITIONS, 1, rq_frag,
2, rp_frag, NULL);
if (dserr)
return dserr;
if (rp_frag[1].fragSize < 1)
return ERR_INVALID_SERVER_RESPONSE;
*iterHandle = DVAL_LH(rp_b, 0);
NWDSBufPutSkip(partitions, rp_frag[1].fragSize);
NWDSBufFinishPut(partitions);
return 0;
}
NWDSCCODE NWDSListPartitionsExtInfo(
NWDSContextHandle ctx,
nuint32* iterHandle,
const NWDSChar* server,
nflag32 dspFlags,
Buf_T* partitions
) {
struct wrappedIterationHandle* ih = NULL;
NWCONN_HANDLE conn;
nuint32 lh;
NWDSCCODE dserr;
nuint32 qflags = 0;
nuint32 ctxflags;
dserr = NWDSGetContext(ctx, DCK_FLAGS, &ctxflags);
if (dserr)
return dserr;
if (ctxflags & DCV_TYPELESS_NAMES)
qflags |= 0x0001;
qflags |= ctx->dck.name_form << 1;
if (*iterHandle == NO_MORE_ITERATIONS) {
dserr = NWDSOpenConnToNDSServer(ctx, server, &conn);
if (dserr)
return dserr;
lh = NO_MORE_ITERATIONS;
} else {
ih = __NWDSIHLookup(*iterHandle, DSV_LIST_PARTITIONS);
if (!ih)
return ERR_INVALID_HANDLE;
conn = ih->conn;
lh = ih->iterHandle;
}
dserr = __NWDSListPartitionsV1(conn, qflags, dspFlags, &lh, partitions);
if (dserr == ERR_INVALID_API_VERSION && dspFlags == (DSP_PARTITION_DN | DSP_REPLICA_TYPE)) {
dserr = __NWDSListPartitionsV0(conn, qflags, &lh, partitions);
}
if (ih)
return __NWDSIHUpdate(ih, dserr, lh, iterHandle);
return __NWDSIHCreate(dserr, conn, 0, lh, DSV_LIST_PARTITIONS, iterHandle);
}
NWDSCCODE NWDSListPartitions(
NWDSContextHandle ctx,
nuint32* iterHandle,
const NWDSChar* server,
Buf_T* partitions
) {
return NWDSListPartitionsExtInfo(ctx, iterHandle, server,
DSP_PARTITION_DN | DSP_REPLICA_TYPE, partitions);
}
NWDSCCODE NWDSGetPartitionExtInfoPtr(
UNUSED( NWDSContextHandle ctx),
Buf_T* partitions,
char** infoPtr,
char** infoPtrEnd
) {
nuint32 fields;
NWDSCCODE dserr;
if (!partitions)
return ERR_NULL_POINTER;
if (partitions->bufFlags & NWDSBUFT_INPUT)
return ERR_BAD_VERB;
switch (partitions->operation) {
case DSV_LIST_PARTITIONS:
break;
default:
return ERR_BAD_VERB;
}
fields = partitions->dsiFlags;
if (fields & DSP_OUTPUT_FIELDS) {
*infoPtr = (char*)partitions->curPos;
dserr = NWDSBufGetLE32(partitions, &fields);
if (dserr)
return dserr;
} else {
*infoPtr = (char*)partitions->curPos - 4;
DSET_LH(partitions->curPos - 4, 0, fields);
}
if (fields & DSP_PARTITION_ID)
NWDSBufGetSkip(partitions, 4);
if (fields & DSP_REPLICA_STATE)
NWDSBufGetSkip(partitions, 4);
if (fields & DSP_MODIFICATION_TIMESTAMP)
NWDSBufGetSkip(partitions, 8);
if (fields & DSP_PURGE_TIME)
NWDSBufGetSkip(partitions, 4);
if (fields & DSP_LOCAL_PARTITION_ID)
NWDSBufGetSkip(partitions, 4);
if (fields & DSP_PARTITION_DN) {
dserr = NWDSBufSkipBuffer(partitions);
if (dserr)
return dserr;
}
if (fields & DSP_REPLICA_TYPE)
NWDSBufGetSkip(partitions, 4);
if (fields & DSP_PARTITION_BUSY)
NWDSBufGetSkip(partitions, 4);
if (fields & 0x0200)
NWDSBufGetSkip(partitions, 4);
if (fields & 0xFFFFFC00)
return NWE_PARAM_INVALID;
if (partitions->curPos > partitions->dataend)
return ERR_BUFFER_EMPTY;
*infoPtrEnd = (char*)partitions->curPos;
return 0;
}
NWDSCCODE NWDSGetPartitionExtInfo(
NWDSContextHandle ctx,
char* infoPtr,
char* infoPtrEnd,
nflag32 infoFlag,
size_t* len,
void* data
) {
Buf_T buf;
nuint32 flags;
nuint32 val;
nuint32 bit;
NWDSCCODE err;
size_t tmplen;
if (!infoPtr || !infoPtrEnd)
return ERR_NULL_POINTER;
if (infoPtr + 4 > infoPtrEnd)
return NWE_PARAM_INVALID;
if (!infoFlag || (infoFlag & (infoFlag - 1)))
return NWE_PARAM_INVALID;
if (!len)
len = &tmplen;
NWDSSetupBuf(&buf, infoPtr, infoPtrEnd - infoPtr);
err = NWDSBufGetLE32(&buf, &flags);
if (err)
return err;
if (!(flags & infoFlag))
return NWE_PARAM_INVALID;
val = flags;
if (infoFlag == DSP_OUTPUT_FIELDS)
goto bytes4;
for (bit = DSP_PARTITION_ID; bit; bit <<= 1) {
if (flags & bit) {
if (bit == infoFlag) {
switch (bit) {
case DSP_PARTITION_ID:
{
NWObjectID id;
err = NWDSBufGetID(&buf, &id);
if (err)
return err;
if (data)
*(NWObjectID*)data = id;
*len = sizeof(NWObjectID);
}
return 0;
case DSP_MODIFICATION_TIMESTAMP:
{
void* p;
p = NWDSBufGetPtr(&buf, 8);
if (!p)
return ERR_BUFFER_EMPTY;
if (data) {
((TimeStamp_T*)data)->wholeSeconds = DVAL_LH(p, 0);
((TimeStamp_T*)data)->replicaNum = WVAL_LH(p, 4);
((TimeStamp_T*)data)->eventID = WVAL_LH(p, 6);
}
*len = sizeof(TimeStamp_T);
}
return 0;
case DSP_PARTITION_DN:
return NWDSBufCtxDN(ctx, &buf, data, len);
default:;
err = NWDSBufGetLE32(&buf, &val);
if (err)
return err;
bytes4:;
if (data)
*(nuint32*)data = val;
*len = sizeof(nuint32);
return 0;
}
} else {
switch (bit) {
case DSP_MODIFICATION_TIMESTAMP:
NWDSBufGetSkip(&buf, 8);
break;
case DSP_PARTITION_DN:
err = NWDSBufSkipBuffer(&buf);
if (err)
return err;
break;
default:
NWDSBufGetSkip(&buf, 4);
break;
}
}
}
}
return NWE_PARAM_INVALID;
}
NWDSCCODE NWDSGetPartitionInfo(
NWDSContextHandle ctx,
Buf_T* partitions,
NWDSChar* partitionName,
nuint32* replicaType
) {
NWDSCCODE dserr;
char* start;
char* stop;
dserr = NWDSGetPartitionExtInfoPtr(ctx, partitions, &start, &stop);
if (dserr)
return dserr;
if (partitionName) {
dserr = NWDSGetPartitionExtInfo(ctx, start, stop,
DSP_PARTITION_DN, NULL, partitionName);
if (dserr)
return dserr;
}
if (replicaType) {
dserr = NWDSGetPartitionExtInfo(ctx, start, stop,
DSP_REPLICA_TYPE, NULL, replicaType);
if (dserr)
return dserr;
}
return 0;
}
static NWDSCCODE __NWDSAddReplicaV0(
NWCONN_HANDLE conn,
nflag32 flags,
NWObjectID partitionID,
nuint32 replicaType,
Buf_T* serverDN
) {
NW_FRAGMENT rq_frag[2];
nuint8 rq_b[16];
DSET_LH(rq_b, 0, 0);
DSET_LH(rq_b, 4, flags);
DSET_HL(rq_b, 8, partitionID);
DSET_LH(rq_b, 12, replicaType);
rq_frag[0].fragAddr.ro = rq_b;
rq_frag[0].fragSize = 16;
rq_frag[1].fragAddr.ro = NWDSBufRetrieve(serverDN, &rq_frag[1].fragSize);
return NWCFragmentRequest(conn, DSV_ADD_REPLICA, 2, rq_frag,
0, NULL, NULL);
}
NWDSCCODE NWDSAddReplica(
NWDSContextHandle ctx,
const NWDSChar* server,
const NWDSChar* partitionRoot,
nuint32 replicaType
) {
NWCONN_HANDLE conn;
NWObjectID partitionID;
NWDSCCODE dserr;
Buf_T buf;
char spare[4 + MAX_DN_BYTES];
dserr = NWDSResolveName2DR(ctx, partitionRoot,
/* FIXME: master or read-write? */
DS_RESOLVE_DEREF_ALIASES | DS_RESOLVE_MASTER,
&conn, &partitionID);
if (dserr)
return dserr;
NWDSSetupBuf(&buf, spare, sizeof(spare));
dserr = NWDSCtxBufDN(ctx, &buf, server);
if (!dserr) {
dserr = __NWDSAddReplicaV0(conn, 0, partitionID, replicaType,
&buf);
}
NWCCCloseConn(conn);
return dserr;
}
static NWDSCCODE __NWDSRemoveReplicaV0(
NWCONN_HANDLE conn,
nflag32 flags,
NWObjectID partitionID,
Buf_T* serverDN
) {
NW_FRAGMENT rq_frag[2];
nuint8 rq_b[12];
DSET_LH(rq_b, 0, 0);
DSET_LH(rq_b, 4, flags);
DSET_HL(rq_b, 8, partitionID);
rq_frag[0].fragAddr.ro = rq_b;
rq_frag[0].fragSize = 12;
rq_frag[1].fragAddr.ro = NWDSBufRetrieve(serverDN, &rq_frag[1].fragSize);
return NWCFragmentRequest(conn, DSV_REMOVE_REPLICA, 2, rq_frag,
0, NULL, NULL);
}
NWDSCCODE NWDSRemoveReplica(
NWDSContextHandle ctx,
const NWDSChar* server,
const NWDSChar* partitionRoot
) {
NWCONN_HANDLE conn;
NWObjectID partitionID;
NWDSCCODE dserr;
Buf_T buf;
char spare[4 + MAX_DN_BYTES];
dserr = NWDSResolveName2DR(ctx, partitionRoot,
/* FIXME: master or read-write? */
DS_RESOLVE_DEREF_ALIASES | DS_RESOLVE_MASTER,
&conn, &partitionID);
if (dserr)
return dserr;
NWDSSetupBuf(&buf, spare, sizeof(spare));
dserr = NWDSCtxBufDN(ctx, &buf, server);
if (!dserr) {
dserr = __NWDSRemoveReplicaV0(conn, 0, partitionID, &buf);
}
NWCCCloseConn(conn);
return dserr;
}
static NWDSCCODE __NWDSChangeReplicaTypeV0(
NWCONN_HANDLE conn,
nflag32 flags,
NWObjectID partitionID,
nuint32 newReplicaType,
Buf_T* serverDN
) {
NW_FRAGMENT rq_frag[2];
nuint8 rq_b[16];
DSET_LH(rq_b, 0, 0);
DSET_LH(rq_b, 4, flags);
DSET_HL(rq_b, 8, partitionID);
DSET_LH(rq_b, 12, newReplicaType);
rq_frag[0].fragAddr.ro = rq_b;
rq_frag[0].fragSize = 16;
rq_frag[1].fragAddr.ro = NWDSBufRetrieve(serverDN, &rq_frag[1].fragSize);
return NWCFragmentRequest(conn, DSV_CHANGE_REPLICA_TYPE, 2, rq_frag,
0, NULL, NULL);
}
NWDSCCODE NWDSChangeReplicaType(
NWDSContextHandle ctx,
const NWDSChar* partitionRoot,
const NWDSChar* server,
nuint32 newReplicaType
) {
NWCONN_HANDLE conn;
NWObjectID partitionID;
NWDSCCODE dserr;
Buf_T buf;
char spare[4 + MAX_DN_BYTES];
dserr = NWDSResolveName2DR(ctx, partitionRoot,
/* FIXME: master or read-write? */
DS_RESOLVE_DEREF_ALIASES | DS_RESOLVE_MASTER,
&conn, &partitionID);
if (dserr)
return dserr;
NWDSSetupBuf(&buf, spare, sizeof(spare));
dserr = NWDSCtxBufDN(ctx, &buf, server);
if (!dserr) {
dserr = __NWDSChangeReplicaTypeV0(conn, 0, partitionID, newReplicaType,
&buf);
}
NWCCCloseConn(conn);
return dserr;
}
static NWDSCCODE __NWDSPartitionReceiveAllUpdatesV0(
NWCONN_HANDLE conn,
NWObjectID partitionID,
NWObjectID serverID
) {
NW_FRAGMENT rq_frag[1];
nuint8 rq_b[16];
DSET_LH(rq_b, 0, 0);
DSET_LH(rq_b, 4, 1);
DSET_HL(rq_b, 8, partitionID);
DSET_HL(rq_b, 12, serverID);
rq_frag[0].fragAddr.ro = rq_b;
rq_frag[0].fragSize = 16;
return NWCFragmentRequest(conn, DSV_PARTITION_FUNCTIONS,
1, rq_frag, 0, NULL, NULL);
}
NWDSCCODE NWDSPartitionReceiveAllUpdates(
NWDSContextHandle ctx,
const NWDSChar* partitionRoot,
const NWDSChar* serverName
) {
NWCONN_HANDLE conn;
NWObjectID partitionID;
NWObjectID serverID;
NWDSCCODE dserr;
dserr = NWDSResolveName2DR(ctx, partitionRoot,
/* FIXME: master or read-write? */
DS_RESOLVE_DEREF_ALIASES | DS_RESOLVE_MASTER,
&conn, &partitionID);
if (dserr)
return dserr;
dserr = NWDSMapNameToID(ctx, conn, serverName, &serverID);
if (!dserr) {
dserr = __NWDSPartitionReceiveAllUpdatesV0(conn, partitionID, serverID);
}
NWCCCloseConn(conn);
return dserr;
}
static NWDSCCODE __NWDSPartitionSendAllUpdatesV0(
NWCONN_HANDLE conn,
NWObjectID partitionID
) {
NW_FRAGMENT rq_frag[1];
nuint8 rq_b[12];
DSET_LH(rq_b, 0, 0);
DSET_LH(rq_b, 4, 1);
DSET_HL(rq_b, 8, partitionID);
rq_frag[0].fragAddr.ro = rq_b;
rq_frag[0].fragSize = 12;
return NWCFragmentRequest(conn, DSV_PARTITION_FUNCTIONS,
1, rq_frag, 0, NULL, NULL);
}
NWDSCCODE NWDSPartitionSendAllUpdates(
NWDSContextHandle ctx,
const NWDSChar* partitionRoot,
const NWDSChar* serverName
) {
NWCONN_HANDLE conn;
NWObjectID partitionID;
NWDSCCODE dserr;
dserr = NWDSOpenConnToNDSServer(ctx, serverName, &conn);
if (dserr)
return dserr;
dserr = NWDSMapNameToID(ctx, conn, partitionRoot, &partitionID);
if (!dserr) {
dserr = __NWDSPartitionSendAllUpdatesV0(conn, partitionID);
if (!dserr) {
dserr = NWDSSyncPartition(ctx, serverName, partitionRoot, 3);
}
}
NWCCCloseConn(conn);
return dserr;
}
static NWDSCCODE __NWDSSyncPartitionV1(
NWCONN_HANDLE conn,
nuint32 flags,
nuint32 seconds,
NWObjectID partitionID
) {
NW_FRAGMENT rq_frag[1];
nuint8 rq_b[16];
DSET_LH(rq_b, 0, 1);
DSET_LH(rq_b, 4, flags);
DSET_LH(rq_b, 8, seconds);
DSET_HL(rq_b, 12, partitionID);
rq_frag[0].fragAddr.ro = rq_b;
rq_frag[0].fragSize = 16;
return NWCFragmentRequest(conn, DSV_SYNC_PARTITION,
1, rq_frag, 0, NULL, NULL);
}
NWDSCCODE NWDSSyncPartition(
NWDSContextHandle ctx,
const NWDSChar* serverName,
const NWDSChar* partitionRoot,
nuint32 seconds
) {
NWCONN_HANDLE conn;
NWObjectID partitionID;
NWDSCCODE dserr;
dserr = NWDSOpenConnToNDSServer(ctx, serverName, &conn);
if (dserr)
return dserr;
dserr = NWDSMapNameToID(ctx, conn, partitionRoot, &partitionID);
if (!dserr) {
dserr = __NWDSSyncPartitionV1(conn, 0, seconds, partitionID);
}
NWCCCloseConn(conn);
return dserr;
}
static NWDSCCODE __NWDSGetPartitionRootV0(
NWCONN_HANDLE conn,
NWObjectID objectID,
NWObjectID* partitionRootID
) {
NW_FRAGMENT rq_frag[1];
NW_FRAGMENT rp_frag[1];
nuint8 rq_b[8];
nuint8 rp_b[4];
NWDSCCODE dserr;
DSET_LH(rq_b, 0, 0);
DSET_HL(rq_b, 4, objectID);
rq_frag[0].fragAddr.ro = rq_b;
rq_frag[0].fragSize = 8;
rp_frag[0].fragAddr.rw = rp_b;
rp_frag[0].fragSize = 4;
dserr = NWCFragmentRequest(conn, DSV_PARTITION_FUNCTIONS,
1, rq_frag, 1, rp_frag, NULL);
if (dserr)
return dserr;
if (rp_frag[0].fragSize < 4)
return ERR_INVALID_SERVER_RESPONSE;
if (partitionRootID)
*partitionRootID = DVAL_LH(rp_b, 0);
return 0;
}
NWDSCCODE NWDSGetPartitionRoot(
NWDSContextHandle ctx,
const NWDSChar* objectName,
NWDSChar* partitionRoot
) {
NWCONN_HANDLE conn;
NWObjectID objectID;
NWObjectID partitionID;
NWDSCCODE dserr;
Buf_T buf;
char spare[MAX_DN_BYTES + 4];
if (!partitionRoot)
return ERR_NULL_POINTER;
dserr = NWDSResolveName2DR(ctx, objectName,
DS_RESOLVE_DEREF_ALIASES | DS_RESOLVE_READABLE,
&conn, &objectID);
if (dserr)
return dserr;
NWDSSetupBuf(&buf, spare, sizeof(spare));
dserr = __NWDSReadObjectDSIInfo(ctx, conn, objectID,
DSI_PARTITION_ROOT_DN, &buf);
if (!dserr)
goto storeName;
dserr = __NWDSGetPartitionRootV0(conn, objectID, &partitionID);
if (dserr)
goto quit;
NWDSSetupBuf(&buf, spare, sizeof(spare));
dserr = __NWDSReadObjectDSIInfo(ctx, conn, partitionID,
DSI_ENTRY_DN, &buf);
if (dserr)
goto quit;
storeName:;
dserr = NWDSBufCtxDN(ctx, &buf, partitionRoot, NULL);
quit:;
NWCCCloseConn(conn);
return dserr;
}
static NWDSCCODE __NWDSRepairTimeStampsV0(
NWCONN_HANDLE conn,
nflag32 flags,
NWObjectID partitionID
) {
NW_FRAGMENT rq_frag[1];
nuint8 rq_b[12];
DSET_LH(rq_b, 0, 0);
DSET_LH(rq_b, 4, flags);
DSET_HL(rq_b, 8, partitionID);
rq_frag[0].fragAddr.ro = rq_b;
rq_frag[0].fragSize = 12;
return NWCFragmentRequest(conn, DSV_REPAIR_TIMESTAMPS,
1, rq_frag, 0, NULL, NULL);
}
NWDSCCODE NWDSRepairTimeStamps(
NWDSContextHandle ctx,
const NWDSChar* partitionRoot
) {
NWCONN_HANDLE conn;
NWObjectID partitionID;
NWDSCCODE dserr;
dserr = NWDSResolveName2DR(ctx, partitionRoot,
/* FIXME: master or read-write? */
DS_RESOLVE_DEREF_ALIASES | DS_RESOLVE_MASTER,
&conn, &partitionID);
if (dserr)
return dserr;
dserr = __NWDSRepairTimeStampsV0(conn, 0, partitionID);
NWCCCloseConn(conn);
return dserr;
}