Forum BigDB Problems Removing Item from DatabaseArray

Discussion and help relating to Player.IO's database solution, BigDB.

Problems Removing Item from DatabaseArray

Postby phil.peron » January 16th, 2011, 8:36 pm

Hi all,

I'm currently trying to use a DatabaseArray to track a group of players. Essentially this means that when a player joins, they're added to a BigDB object that contains an array. When they leave, they're removed. Here's an example of the server code that leads up to this point:

Code: Select all
public override void UserJoined(Player player) {
    PlayerIO.BigDB.Load("Groups", "testGroup", delegate(DatabaseObject group)
    {
        DatabaseArray characters = group.GetArray("characters");
        characters.Add(player.Id);
        group.Save();
    });
}

public override void UserLeft(Player player) {
    PlayerIO.BigDB.Load("Groups", "testGroup", delegate(DatabaseObject group)
    {
        DatabaseArray characters = group.GetArray("characters");
        for (var i = 0; i < characters.Count; i++)
        {
            if ((int)characters[i] == player.Id)
            {
                characters.RemoveAt(i);
            }
        }
        group.Save();
    });
}


At this point, I can connect a number of clients and see these values reflected in BigDB. Similarly, as each client is disconnected we see the value being removed in turn. Everything works as expected until...

Only one client remains.

If I call the DatabaseArray.RemoveAt() method on an array with only one value, the removal fails and I start to see the repeated warning, "Some code has been running for longer than will be allowed in the live enviroment. ..."

If anyone has any input on this, I'd greatly appreciate it. Thanks.
phil.peron
 
Posts: 35
Joined: September 24th, 2010, 7:50 pm

Re: Problems Removing Item from DatabaseArray

Postby Oliver » January 17th, 2011, 1:31 pm

Hey Phil,

Thank you very much for the great and detailed error report. It's a great catch, and it it's a bug on our end.

We've verified that it can be reproduced, added it to the unit tests, and have implemented a fix for it. (it was a loop that didn't terminate when hitting zero).

Now comes the tricky part: getting the fix out there.

We'll post an updated development server very soon (today or tomorrow), since we were going to do that anyway with some of the smaller bugfixes found since v2.1.

However, it will take some more time before we're ready to update the production servers. This is because we require more testing etc before pushing changes to live -- and we've already made changes in the upcoming release that will require more testing.

I'll let you know when it's out.

Best,
Oliver
User avatar
Oliver
.IO
 
Posts: 1136
Joined: January 12th, 2010, 8:29 am

Re: Problems Removing Item from DatabaseArray

Postby phil.peron » January 17th, 2011, 3:22 pm

Hi Oliver,

No problem. We've actually swapped out the DatabaseArray with a DataObject and with excellent results. Therefore, we're not losing any development cycles on the issue.

Thanks for the update!
phil.peron
 
Posts: 35
Joined: September 24th, 2010, 7:50 pm

Re: Problems Removing Item from DatabaseArray

Postby moosemouse » January 4th, 2012, 10:06 pm

I know this is an old thread, but I am having a problem that I think is related to this bug. Below is a snippet of code on the server that is triggered when a player buys a new car. He can also trade-in some of his old cars to pay for the new one. The problem is that the trade-ins do not always get removed. Specifically, when the trade-in is the first car in the DatabaseArray "listOfAllCarsOwned".. index = 0. However, if the trade-in is not the first car in the database array it gets removed. Is this a part of the bug mentioned, or am I just doing something stupid?

Code: Select all
case "myPlayerBoughtCarBTR2":
   uint indexOfNewCarType = message.GetUInt(0);

   float newCarRed = message.GetFloat(1);
   float newCarGreen = message.GetFloat(2);
   float newCarBlue = message.GetFloat(3);

   List<uint> tradeIns = new List<uint>();
   uint numTradeIns = message.Count - 4;
   for (uint i = 0; i < numTradeIns; i++)
   {
       tradeIns.Add(message.GetUInt(i+4));
   }
   
   DatabaseObject newCarObj = new DatabaseObject();
   newCarObj = SetupDefaultColorsOnCar(newCarObj);
   newCarObj.Set("indexOfCarType", indexOfNewCarType);

   DatabaseArray dbArrayOfNewCarCustomizations = new DatabaseArray();
   newCarObj.Set("customizations", dbArrayOfNewCarCustomizations);
   
   DatabaseArray newCarBodyArea1Color = new DatabaseArray();
   newCarBodyArea1Color.Add(newCarRed);
   newCarBodyArea1Color.Add(newCarGreen);
   newCarBodyArea1Color.Add(newCarBlue);
   newCarObj.Set("bodyArea1Color", newCarBodyArea1Color);

   DatabaseArray listOfAllCarsOwned = player.PlayerObject.GetArray("listOfAllCarsOwned");
   listOfAllCarsOwned.Add(newCarObj);
   
   // Remove cars that were traded in
   if (tradeIns.Count > 0)
   {
       for (int i = 0; i < listOfAllCarsOwned.Count; i++)
       {
           DatabaseObject carObj = (DatabaseObject) listOfAllCarsOwned[i];
           for (int j = 0; j < tradeIns.Count; j++)
           {
               if (tradeIns[j] == carObj.GetUInt("indexOfCarType"))
               {
                   listOfAllCarsOwned.RemoveAt(i);
                   i--;
               }
           }
       }
   }
   
   player.PlayerObject.Save(true); // I've tried with and without optimistic locking.
   break;
User avatar
moosemouse
 
Posts: 84
Joined: August 11th, 2010, 2:51 pm
Location: New Albany, Ohio USA

Re: Problems Removing Item from DatabaseArray

Postby moosemouse » January 5th, 2012, 3:11 am

Looks like if I use "full overwrite" it works.

from the DatabaseObject docs:
Save (bool useOptimisticLock, bool fullOverwrite)
Persist the object to the database, using optimistic locking and full overwrite if specified
User avatar
moosemouse
 
Posts: 84
Joined: August 11th, 2010, 2:51 pm
Location: New Albany, Ohio USA


Return to BigDB