Browse Source

Revert "Fix dupe callbacks in VaultAddChildNode"

This reverts commit b393947cd5.

The commit was seemingly harmless, but it created or otherwise uncovered
stack corruption deep inside the vault voodoo. While I would like to know
what was up, I'm tired of dealing with it. The crash addressed here was
fixed in a subsequent moul-scripts commit, so let's just toss this one.
Adam Johnson 10 years ago
parent
commit
63af63574c
  1. 137
      Sources/Plasma/PubUtilLib/plVault/plVaultClientApi.cpp

137
Sources/Plasma/PubUtilLib/plVault/plVaultClientApi.cpp

@ -246,27 +246,18 @@ struct VaultAgeInitTrans {
); );
}; };
class AddChildNodeTrans { struct AddChildNodeFetchTrans {
FVaultAddChildNodeCallback callback; FVaultAddChildNodeCallback callback;
void * cbParam; void * cbParam;
ENetError result; ENetError result;
std::atomic<long> opCount; std::atomic<long> opCount;
void CompleteOp(); AddChildNodeFetchTrans()
: callback(nil), cbParam(nil), result(kNetSuccess), opCount(0) { }
public: AddChildNodeFetchTrans(FVaultAddChildNodeCallback _callback, void * _param)
AddChildNodeTrans()
: callback(nullptr), cbParam(nullptr), result(kNetSuccess), opCount(0) { }
AddChildNodeTrans(FVaultAddChildNodeCallback _callback, void * _param)
: callback(_callback), cbParam(_param), result(kNetSuccess), opCount(0) { } : callback(_callback), cbParam(_param), result(kNetSuccess), opCount(0) { }
void AddOp() { ++opCount; }
static void VaultNodeAdded (
ENetError result,
void * param
);
static void VaultNodeFetched ( static void VaultNodeFetched (
ENetError result, ENetError result,
void * param, void * param,
@ -1003,38 +994,18 @@ void VaultAgeInitTrans::AgeInitCallback (
/***************************************************************************** /*****************************************************************************
* *
* AddChildNodeTrans * AddChildNodeFetchTrans
* *
***/ ***/
//============================================================================ //============================================================================
void AddChildNodeTrans::CompleteOp() { void AddChildNodeFetchTrans::VaultNodeRefsFetched (
if ((--opCount) == 0) {
if (callback)
callback(result, cbParam);
delete this; // commit hara-kiri
}
}
//============================================================================
void AddChildNodeTrans::VaultNodeAdded(
ENetError result,
void* param
) {
AddChildNodeTrans* trans = static_cast<AddChildNodeTrans*>(param);
if (IS_NET_ERROR(result))
trans->result = result;
trans->CompleteOp();
}
//============================================================================
void AddChildNodeTrans::VaultNodeRefsFetched (
ENetError result, ENetError result,
void * param, void * param,
NetVaultNodeRef * refs, NetVaultNodeRef * refs,
unsigned refCount unsigned refCount
) { ) {
AddChildNodeTrans * trans = (AddChildNodeTrans *)param; AddChildNodeFetchTrans * trans = (AddChildNodeFetchTrans *)param;
if (IS_NET_ERROR(result)) { if (IS_NET_ERROR(result)) {
trans->result = result; trans->result = result;
@ -1044,27 +1015,45 @@ void AddChildNodeTrans::VaultNodeRefsFetched (
FetchNodesFromRefs( FetchNodesFromRefs(
refs, refs,
refCount, refCount,
AddChildNodeTrans::VaultNodeFetched, AddChildNodeFetchTrans::VaultNodeFetched,
param, param,
&incFetchCount &incFetchCount
); );
trans->opCount += incFetchCount; trans->opCount += incFetchCount;
} }
trans->CompleteOp();
// Make the callback now if there are no nodes to fetch, or if error
if (!(--trans->opCount)) {
if (trans->callback)
trans->callback(
trans->result,
trans->cbParam
);
delete trans;
}
} }
//============================================================================ //============================================================================
void AddChildNodeTrans::VaultNodeFetched ( void AddChildNodeFetchTrans::VaultNodeFetched (
ENetError result, ENetError result,
void * param, void * param,
NetVaultNode * node NetVaultNode * node
) { ) {
::VaultNodeFetched(result, param, node); ::VaultNodeFetched(result, param, node);
AddChildNodeTrans * trans = (AddChildNodeTrans *)param; AddChildNodeFetchTrans * trans = (AddChildNodeFetchTrans *)param;
if (IS_NET_ERROR(result)) if (IS_NET_ERROR(result))
trans->result = result; trans->result = result;
trans->CompleteOp();
if (!(--trans->opCount)) {
if (trans->callback)
trans->callback(
trans->result,
trans->cbParam
);
delete trans;
}
} }
@ -1748,6 +1737,9 @@ void VaultAddChildNode (
FVaultAddChildNodeCallback callback, FVaultAddChildNodeCallback callback,
void * param void * param
) { ) {
// Make sure we only do the callback once
bool madeCallback = false;
// Too much of the client relies on the assumption that the node will be immediately // Too much of the client relies on the assumption that the node will be immediately
// associated with its parent. THIS SUCKS, because there's no way to guarantee the // associated with its parent. THIS SUCKS, because there's no way to guarantee the
// association won't be circular (the db checks this in a comprehensive way). // association won't be circular (the db checks this in a comprehensive way).
@ -1756,14 +1748,14 @@ void VaultAddChildNode (
// This directly affects: New clothing items added to the avatar outfit folder, // This directly affects: New clothing items added to the avatar outfit folder,
// new chronicle entries in some ages, and I'm sure several other situations. // new chronicle entries in some ages, and I'm sure several other situations.
AddChildNodeTrans * trans = nullptr;
if (RelVaultNodeLink * parentLink = s_nodes.Find(parentId)) { if (RelVaultNodeLink * parentLink = s_nodes.Find(parentId)) {
RelVaultNodeLink * childLink = s_nodes.Find(childId); RelVaultNodeLink * childLink = s_nodes.Find(childId);
if (!childLink) { if (!childLink) {
childLink = new RelVaultNodeLink(false, ownerId, childId, new RelVaultNode); childLink = new RelVaultNodeLink(false, ownerId, childId, new RelVaultNode);
childLink->node->SetNodeId_NoDirty(childId); childLink->node->SetNodeId_NoDirty(childId);
s_nodes.Add(childLink); s_nodes.Add(childLink);
} else if (ownerId) { }
else if (ownerId) {
childLink->ownerId = ownerId; childLink->ownerId = ownerId;
} }
@ -1778,17 +1770,14 @@ void VaultAddChildNode (
// callback now with error code // callback now with error code
if (callback) if (callback)
callback(kNetErrCircularReference, param); callback(kNetErrCircularReference, param);
// I don't really care what Eric thinks, if we believe it's a circular reference, it's evil }
// to report a failure, then send it to the server anyway! That's just a bug WAITING else if (childLink->node->IsParentOf(parentId, 255)) {
// to be uncovered, and I don't want to deal with it!
return;
} else if (childLink->node->IsParentOf(parentId, 255)) {
LogMsg(kLogDebug, L"Node relationship would be circular: p:%u, c:%u", parentId, childId); LogMsg(kLogDebug, L"Node relationship would be circular: p:%u, c:%u", parentId, childId);
// callback now with error code // callback now with error code
if (callback) if (callback)
callback(kNetErrCircularReference, param); callback(kNetErrCircularReference, param);
return; }
} else { else {
NetVaultNodeRef refs[] = { NetVaultNodeRef refs[] = {
{ parentId, childId, ownerId } { parentId, childId, ownerId }
}; };
@ -1797,52 +1786,66 @@ void VaultAddChildNode (
ARRAY(unsigned) existingNodeIds; ARRAY(unsigned) existingNodeIds;
BuildNodeTree(refs, arrsize(refs), &newNodeIds, &existingNodeIds); BuildNodeTree(refs, arrsize(refs), &newNodeIds, &existingNodeIds);
trans = new AddChildNodeTrans(callback, param);
if (!childLink->node->GetNodeType() || !parentLink->node->GetNodeType()) { if (!childLink->node->GetNodeType() || !parentLink->node->GetNodeType()) {
// One or more nodes need to be fetched before the callback is made // One or more nodes need to be fetched before the callback is made
AddChildNodeFetchTrans * trans = new AddChildNodeFetchTrans(callback, param);
if (!childLink->node->GetNodeType()) { if (!childLink->node->GetNodeType()) {
trans->AddOp(); ++trans->opCount;
NetCliAuthVaultNodeFetch( NetCliAuthVaultNodeFetch(
childId, childId,
AddChildNodeTrans::VaultNodeFetched, AddChildNodeFetchTrans::VaultNodeFetched,
trans trans
); );
trans->AddOp(); ++trans->opCount;
NetCliAuthVaultFetchNodeRefs( NetCliAuthVaultFetchNodeRefs(
childId, childId,
AddChildNodeTrans::VaultNodeRefsFetched, AddChildNodeFetchTrans::VaultNodeRefsFetched,
trans trans
); );
} }
if (!parentLink->node->GetNodeType()) { if (!parentLink->node->GetNodeType()) {
trans->AddOp(); ++trans->opCount;
NetCliAuthVaultNodeFetch( NetCliAuthVaultNodeFetch(
parentId, parentId,
AddChildNodeTrans::VaultNodeFetched, AddChildNodeFetchTrans::VaultNodeFetched,
trans trans
); );
trans->AddOp(); ++trans->opCount;
NetCliAuthVaultFetchNodeRefs( NetCliAuthVaultFetchNodeRefs(
parentId, parentId,
AddChildNodeTrans::VaultNodeRefsFetched, AddChildNodeFetchTrans::VaultNodeRefsFetched,
trans trans
); );
} }
} }
else {
// We have both nodes already, so make the callback now.
if (callback) {
callback(kNetSuccess, param);
madeCallback = true;
}
}
}
}
else {
// Parent doesn't exist locally (and we may not want it to), just make the callback now.
if (callback) {
callback(kNetSuccess, param);
madeCallback = true;
} }
} }
// Send it off to the vault. Note that we're reusing the old fetch trans's opCount junk // Send it on up to the vault. The db server filters out duplicate and
// to ensure that we only ever callback once. May Jesus be with us all. // circular node relationships. We send the request up even if we think
if (trans) // the relationship would be circular since the db does a universal
trans->AddOp(); // check and is the only real authority in this matter.
NetCliAuthVaultNodeAdd( NetCliAuthVaultNodeAdd(
parentId, parentId,
childId, childId,
ownerId, ownerId,
trans ? AddChildNodeTrans::VaultNodeAdded : callback, madeCallback ? nil : callback,
trans ? trans : param madeCallback ? nil : param
); );
} }

Loading…
Cancel
Save