868 lines
21 KiB
C
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;
|
|
}
|