Forum BigDB Property does not exist

Discussion and help relating to the PlayerIO database solution, BigDB.

Property does not exist

Postby FulaFisken » April 23rd, 2012, 10:42 am

Occasionally we get these kinds of errors. They are really strange since in this case, every weapon in our database has a type property, I have double checked and tripple checked. I can of course add a default value, obj.getString("type", ""), but it should not be required since we are certain it already has a value.

Code: Select all
Property does not exist: type
First seen 9 hours ago, latest 2 hours ago. (Delete 1 error)

   at Game.Factory.<>c__DisplayClass2e.b__2c(DatabaseObject obj)
   at Game.data.DataManager.GetData(String table, String key, Callback`1 callback)
   at Game.Factory.CreateWeapon(String key, Unit unit, Int32 techLevel, Callback`1 successCallback)
Fula Fisken
website blog twitter
Play Game
Astroflux
User avatar
FulaFisken
Paid Member
 
Posts: 139
Joined: March 2nd, 2011, 10:15 am

Re: Property does not exist

Postby Benjaminsen » May 1st, 2012, 12:40 pm

Ugh that sounds bad, can you show a bit more of your code? Where is the type property located on the Object compared to the root etc?

- Chris
Benjaminsen
.IO
 
Posts: 1444
Joined: January 12th, 2010, 11:54 am
Location: Denmark

Re: Property does not exist

Postby FulaFisken » May 1st, 2012, 4:54 pm

There is a possibility that we had some bad code before. We just changed a lot of stuff, the game loads all world data from a JSON file now. So even if the bug exist it wont happen that often now. Our old code loaded all world data from the database, which was very good while we were building our game, but now its better to be able to edit our database without interupting the live version. Also, getting rid of all the database calls have saved us a lot of headache since we don't have to synchronize our code and get better perfomance during runtime and room creation.

The old datamanager loaded an object from the database if it wasn't cached. This was happening throughout the game, so its hard to tell if this error happend due to other issues, like aborts. But anyways, here is a piece of the old weapon factory code from our github and the current DataManager.

Weapon factory (old version):
Code: Select all
private void CreateWeapon(string key, Unit unit, int techLevel, Callback<Weapon> successCallback)
        {
            g.dataManager.GetData(Table.WEAPONS(), key, delegate(DatabaseObject obj)
            {
                Weapon w;

                switch (obj.GetString("type", ""))
                {
                    case "blaster":
                        w = new Blaster(g);
                        break;
                    case "beam":
                        w = new Beam(g, obj, techLevel);
                        break;
                    default:
                        w = new ProjectileGun(g);
                        break;
                }
                w.name = obj.GetString("name", "");
                w.key = key;
                w.projectileFunction = obj.GetString("projectile", "");
                w.SetDamage(obj.GetInt("dmg", 0), obj.GetInt("damageType", 0));
                if (obj.Contains("debuffType") && obj.Contains("dot") && obj.Contains("dotDamageType") && obj.Contains("dotDuration"))
                {
                    w.debuffType = obj.GetInt("debuffType", 0);
                    w.SetDebuffValue(obj.GetInt("dot", 0), obj.GetInt("dotDamageType", 0));
                    w.debuffDuration = obj.GetInt("dotDuration", 0);
                    w.debuffEffect = obj.GetString("dotEffect", "");
                }
                else
                {
                    w.debuffType = -1;
                    w.SetDebuffValue(0, 0);
                    w.debuffDuration = 0;
                    w.debuffEffect = "";
                }
               
                w.numberOfHits = obj.GetInt("numberOfHits", 1);
                w.speed = obj.GetInt("speed", 0);
                w.reloadTime = obj.GetInt("reloadTime", 0);
                w.ttl = obj.GetInt("ttl", 0);
                w.range = obj.GetInt("range", 0);
                w.acceleration = GetDouble(obj, "acceleration");
                w.friction = GetDouble(obj, "friction");
                w.rotationSpeed = GetDouble(obj, "rotationSpeed");
                w.positionVariance = obj.GetInt("positionVariance", 0);
                w.positionOffset = obj.GetInt("positionOffset", 0);
                w.maxProjectiles =  obj.GetInt("maxProjectiles",0);
              w.multiNrOfP =  obj.GetInt("multiNrOfP",1);
              w.multiOffset =  obj.GetInt("multiOffset",1);
              w.multiAngleOffset = Utils.degreesToRadians(GetDouble(obj, "multiAngleOffset"));
                w.angleVariance = GetDouble(obj, "angleVariance");
                w.unit = unit;
             w.dmgRadius = obj.GetInt("radius", 0);

                w.heatCost = (double)(obj.GetInt("heatCost",0))/1000d;

                if (techLevel > 0)
                    addTechStatsToWeapon(w, obj, techLevel);

                if (w.projectileFunction != "")
                {
                    g.dataManager.GetData(Table.PROJECTILES(), w.projectileFunction, delegate(DatabaseObject cachedProjectile)
                    {
                        SetWeapon(w, obj, successCallback);
                    });
                }
                else
                {
                    SetWeapon(w, obj, successCallback);
                }
            });
        }


Datamanager (current version, the BigDB function should be the same as before, ie. GetData()):
Code: Select all
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using PlayerIO.GameLibrary;
using Game.generics;
using Game.players;

namespace Game.data
{
    public class DataManager
    {
        private BaseRoom g;
        private Hashtable tables;
        private Hashtable callbackQueue;
        private Hashtable json;

        private int cacheCount;
        public bool cacheLoaded = false;

        private readonly object callbackLock = new object();

        public DataManager(BaseRoom g)
        {
            this.g = g;
            tables = new Hashtable();
            callbackQueue = new Hashtable();
        }

        /*
        public void LoadCache()
        {
            double startTime = g.GameTime();
            json = new Hashtable();
            //g.PlayerIO.BigDB.LoadRange("json", "ByName", null, null, null, 100, delegate(DatabaseObject[] array)
            string[] keys = { Table.BASICTECHS(), Table.BODIES(), Table.BODY_AREAS(), Table.BOSSES(), Table.COMMODITIES(), Table.CREW_DATA(), Table.DROPS(), Table.ENEMIES(), Table.ENGINES(), Table.IMAGES(), Table.PROJECTILES(), Table.SHIPS(), Table.SOLAR_SYSTEMS(), Table.SOUNDS(), Table.SPAWNERS(), Table.TURRETS(), Table.WARP_PATHS(), Table.WEAPONS() };
            g.PlayerIO.BigDB.LoadKeys("json", keys, delegate(DatabaseObject[] array)
                     {
                         Console.WriteLine("load range time: " + (g.GameTime() - startTime) + " ms");
                         cacheCount = array.Length;
                         process(array, 0);
                     });
        }

        private void process(DatabaseObject[] array, int i)
        {
            Parse(array[i]);
            i++;

            if (i < array.Length)
            {
                g.ScheduleCallback(delegate()
                {
                    process(array, i);
                }, 25);
            }
        }

        private void Parse(DatabaseObject obj)
        {
            double startTime = g.GameTime();
            JSON jsonHelper = new JSON();
            Hashtable result = (Hashtable)jsonHelper.JsonDecode(obj.GetString("json"));
            lock (json)
            {
                if (!json.ContainsKey(obj.Key))
                {
                    json.Add(obj.Key, result);
                    cacheCount--;

                    if (cacheCount == 0)
                    {
                        cacheLoaded = true;
                    }
                }
            }
            Console.WriteLine("parse " + obj.Key + " time: " + (g.GameTime() - startTime) + " ms");
        }
        */

        public void LoadCache()
        {
            double start = g.GameTime();
            string url = g.PlayerIO.GameFS.GetUrl("/cache.json");
            g.PlayerIO.Web.Get(url, delegate(HttpResponse response)
            {
                Console.WriteLine("gameFS load time: " + (g.GameTime() - start) + " ms");

                start = g.GameTime();
                g.ScheduleCallback(delegate()
                {
                    JSON jsonHelper = new JSON();
                    Hashtable result = (Hashtable)jsonHelper.JsonDecode(response.Text);

                    json = result;
                    Console.WriteLine("parse time: " + (g.GameTime() - start) + " ms");
                    cacheLoaded = true;
                }, 25);
            });
        }


        public JSONObject LoadKey(string table, string key)
        {
            if (!json.ContainsKey(table))
            {
                g.PlayerIO.ErrorLog.WriteError("LoadKey table is null, table: " + table);
                return null;
            }

            Hashtable t = (Hashtable)json[table];
            if (!t.ContainsKey(key))
            {
                g.PlayerIO.ErrorLog.WriteError("LoadKey key is null, key: " + key);
                return null;
            }
            //Console.WriteLine("loading json table: " + table + ", key: " + key);
            return new JSONObject(t[key]);
        }

        public Hashtable LoadRange(string table, string prop, string compareValue)
        {
            if (!json.ContainsKey(table))
            {
                g.PlayerIO.ErrorLog.WriteError("LoadRange table is null, table: " + table);
                return null;
            }

            Hashtable t = (Hashtable)json[table];
            Hashtable result = new Hashtable();
            foreach (DictionaryEntry pair in t)
            {
                JSONObject obj = new JSONObject(pair.Value);
                string value = obj.GetString(prop, "");

                if (value == compareValue)
                {
                    result[pair.Key] = pair.Value;
                }
            }

            return result;
        }

        public Hashtable LoadTable(string table)
        {
            return (Hashtable)json[table];
        }

        private void AddData(string table, string key, DatabaseObject obj)
        {
            Hashtable objects;

            if (tables.ContainsKey(table))
                objects = tables[table] as Hashtable;
            else
                objects = new Hashtable();

            objects[key] = obj;

            tables[table] = objects;
        }

        public void GetData(string table, string key, Callback<DatabaseObject> callback)
        {
            if (tables.ContainsKey(table))
            {
                Hashtable objectHash = tables[table] as Hashtable;

                if (String.IsNullOrWhiteSpace(key) || String.IsNullOrEmpty(key))
                {
                    g.PlayerIO.ErrorLog.WriteError("GetData key is null or empty... key: " + key + " table: " + table);
                    return;
                }

                if (objectHash != null && objectHash.ContainsKey(key))
                {
                    //Console.WriteLine("FROM Cache - TABLE: " + table + ", KEY: " + key);
                    DatabaseObject obj = (tables[table] as Hashtable)[key] as DatabaseObject;

                    if (obj == null)
                    {
                        g.PlayerIO.ErrorLog.WriteError("CACHED CALLBACK FAIL - TABLE: " + table + " KEY: " + key, new NullReferenceException());
                    }

                    callback(obj);

                    return;
                }
            }


            Hashtable callbackKeys;

            lock (callbackLock)
            {

                if (callbackQueue.ContainsKey(table))
                {
                    callbackKeys = (callbackQueue[table] as Hashtable);
                }
                else
                {
                    callbackKeys = new Hashtable();
                    callbackQueue[table] = callbackKeys;
                }

                List<Callback<DatabaseObject>> callbacks;
                if (callbackKeys.ContainsKey(key))
                {
                    callbacks = (callbackKeys[key] as List<Callback<DatabaseObject>>);

                    if (callbacks == null)
                    {
                        callbacks = new List<Callback<DatabaseObject>>();
                        callbacks.Add(callback);
                        callbackKeys[key] = callbacks;
                        LoadFromBigDB(table, key);
                    }
                    else
                    {
                        callbacks.Add(callback);
                        //Console.WriteLine("IN BigDB - Added callback to existing queue. TABLE: " + table + " KEY: " + key);
                    }
                }
                else
                {
                    callbacks = new List<Callback<DatabaseObject>>();
                    callbacks.Add(callback);
                    callbackKeys[key] = callbacks;
                    LoadFromBigDB(table, key);
                }
            }
        }

        private void LoadFromBigDB(String table, String key)
        {
            g.PlayerIO.BigDB.Load(table, key, delegate(DatabaseObject obj)
            {
                lock (callbackLock)
                {
                    if (obj == null)
                    {
                        g.PlayerIO.ErrorLog.WriteError("FAILED DATA - TABLE: " + table + " KEY: " + key, new NullReferenceException());
                    }

                    //Console.WriteLine("FROM BigDB - TABLE: " + table + ", KEY: " + key);
                    AddData(table, key, obj);

                    if (!callbackQueue.ContainsKey(table))
                    {
                        g.PlayerIO.ErrorLog.WriteError("DATA QUEUE FAIL - TABLE: " + table + " KEY: " + key, new NullReferenceException());
                    }

                    Hashtable callbackTableQueue = callbackQueue[table] as Hashtable;

                    if (!callbackTableQueue.ContainsKey(key))
                    {
                        g.PlayerIO.ErrorLog.WriteError("DATA QUEUE FAIL 2 - TABLE: " + table + " KEY: " + key, new NullReferenceException());
                    }

                    List<Callback<DatabaseObject>> callbacks = callbackTableQueue[key] as List<Callback<DatabaseObject>>;

                    if (callbacks != null)
                    {
                        foreach (Callback<DatabaseObject> callback in callbacks)
                        {
                            callback(obj);
                        }
                    }
                }

            },
            delegate(PlayerIOError error)
            {
                g.PlayerIO.ErrorLog.WriteError("FAILED DATA - TABLE: " + table + " KEY: " + key + " ERROR: " + error);
            });
        }

        public void LoadRangeFromBigDB(string table, string index, object[] indexPath = null, Callback<DatabaseObject[]> callback = null)
        {
            g.PlayerIO.BigDB.LoadRange(table, index, indexPath, null, null, 100, delegate(DatabaseObject[] array)
            {
                foreach (DatabaseObject obj in array)
                {
                    AddData(obj.Table, obj.Key, obj);
                }

                callback(array);
            },
            delegate(PlayerIOError error)
            {
                g.PlayerIO.ErrorLog.WriteError("FAILED DATA - TABLE: " + table + " INDEX: " + index + " INDEX_PATH: " + indexPath + " ERROR: " + error);
            });
        }
    }
}
Fula Fisken
website blog twitter
Play Game
Astroflux
User avatar
FulaFisken
Paid Member
 
Posts: 139
Joined: March 2nd, 2011, 10:15 am

Re: Property does not exist

Postby Benjaminsen » May 2nd, 2012, 11:10 am

Great, doing internal followup on this as well.
Benjaminsen
.IO
 
Posts: 1444
Joined: January 12th, 2010, 11:54 am
Location: Denmark


Return to BigDB