private static bool TryCreateNewUpdate(SectorCache cache, TableWriteData data, bool tablesareempty, ref DateTime maxdate, ref int nextsectorid, out Sector t, bool makenew = false)
        {
            if (data.edsm.date > maxdate)                                   // for all, record last recorded date processed
            {
                maxdate = data.edsm.date;
            }

            Sector prev = null;

            t = null;

            if (!cache.SectorNameCache.ContainsKey(data.classifier.SectorName))   // if unknown to cache
            {
                if (!tablesareempty && !makenew)
                {
                    return(false);
                }

                cache.SectorNameCache[data.classifier.SectorName] = t = new Sector(data.classifier.SectorName, gridid: data.gridid);   // make a sector of sectorname and with gridID n , id == -1
            }
            else
            {
                t = cache.SectorNameCache[data.classifier.SectorName]; // find the first sector of name
                while (t != null && t.GId != data.gridid)              // if GID of sector disagrees
                {
                    prev = t;                                          // go thru list
                    t    = t.NextSector;
                }

                if (t == null)      // still not got it, its a new one.
                {
                    if (!tablesareempty && !makenew)
                    {
                        return(false);
                    }

                    prev.NextSector = t = new Sector(data.classifier.SectorName, gridid: data.gridid);   // make a sector of sectorname and with gridID n , id == -1
                }
            }

            if (t.Id == -1)                        // if unknown sector ID..
            {
                if (tablesareempty)                // if tables are empty, we can just presume its id
                {
                    t.Id        = nextsectorid++;  // insert the sector with the guessed ID
                    t.insertsec = true;
                    cache.SectorIDCache[t.Id] = t; // and cache
                    //System.Diagnostics.Debug.WriteLine("Made sector " + t.Name + ":" + t.GId);
                }
            }

            if (t.edsmdatalist == null)
            {
                t.edsmdatalist = new List <TableWriteData>(5000);
            }

            t.edsmdatalist.Add(data);                       // add to list of systems to process for this sector

            return(true);
        }
        private static void CreateNewUpdate(SectorCache cache, DbCommand selectSectorCmd, TableWriteData data, bool tablesareempty, ref DateTime maxdate, ref int nextsectorid)
        {
            TryCreateNewUpdate(cache, data, tablesareempty, ref maxdate, ref nextsectorid, out Sector t, true);

            if (t.Id == -1)   // if unknown sector ID..
            {
                selectSectorCmd.Parameters[0].Value = t.Name;
                selectSectorCmd.Parameters[1].Value = t.GId;

                using (DbDataReader reader = selectSectorCmd.ExecuteReader()) // find name:gid
                {
                    if (reader.Read())                                        // if found name:gid
                    {
                        t.Id = (long)reader[0];
                    }
                    else
                    {
                        t.Id        = nextsectorid++; // insert the sector with the guessed ID
                        t.insertsec = true;
                    }

                    cache.SectorIDCache[t.Id] = t;                // and cache
                    //  System.Diagnostics.Debug.WriteLine("Made sector " + t.Name + ":" + t.GId);
                }
            }
        }
        // create a new entry for insert in the sector tables
        private static void CreateNewUpdate(SectorCache cache, DbCommand selectSectorCmd, EDSMFileEntry d, int gid, bool tablesareempty, ref DateTime maxdate, ref int nextsectorid)
        {
            TableWriteData data = new TableWriteData()
            {
                edsm = d, classifier = new EliteNameClassifier(d.name), gridid = gid
            };

            CreateNewUpdate(cache, selectSectorCmd, data, tablesareempty, ref maxdate, ref nextsectorid);
        }
        // set tempostfix to use another set of tables

        public static long ParseEDSMJSON(TextReader textreader,
                                         bool[] grididallowed,      // null = all, else grid bool value
                                         ref DateTime maxdate,      // updated with latest date
                                         Func <bool> cancelRequested,
                                         Action <string> reportProgress,
                                         string tablepostfix,            // set to add on text to table names to redirect to another table
                                         bool tablesareempty    = false, // set to presume table is empty, so we don't have to do look up queries
                                         string debugoutputfile = null
                                         )
        {
            var cache = new SectorCache();

            long updates = 0;

            int          nextsectorid = GetNextSectorID();
            StreamWriter sw           = null;

            try
            {
#if DEBUG
                try
                {
                    if (debugoutputfile != null)
                    {
                        sw = new StreamWriter(debugoutputfile);
                    }
                }
                catch
                {
                }
#endif
                var parser     = new BaseUtils.StringParserQuickTextReader(textreader, 32768);
                var enumerator = JToken.ParseToken(parser, JToken.ParseOptions.None).GetEnumerator();       // Parser may throw note

                while (true)
                {
                    if (cancelRequested())
                    {
                        updates = -1;
                        break;
                    }

                    int recordstostore = ProcessBlock(cache, enumerator, grididallowed, tablesareempty, tablepostfix, ref maxdate, ref nextsectorid, out bool jr_eof);

                    System.Diagnostics.Debug.WriteLine("Process " + BaseUtils.AppTicks.TickCountLap("L1") + "   " + updates);

                    if (recordstostore > 0)
                    {
                        updates += StoreNewEntries(cache, tablepostfix, sw);

                        reportProgress?.Invoke("EDSM Star database updated " + updates);
                    }

                    if (jr_eof)
                    {
                        break;
                    }

                    System.Threading.Thread.Sleep(20);      // just sleepy for a bit to let others use the db
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine("Exception during EDSM parse " + ex);
            }
            finally
            {
                if (sw != null)
                {
                    sw.Close();
                }
            }

            System.Diagnostics.Debug.WriteLine("Process " + BaseUtils.AppTicks.TickCountLap("L1") + "   " + updates);
            reportProgress?.Invoke("EDSM Star database updated " + updates);

            PutNextSectorID(nextsectorid);    // and store back

            return(updates);
        }
        private static long StoreNewEntries(SectorCache cache, string tablepostfix = "",        // set to add on text to table names to redirect to another table
                                            StreamWriter sw = null
                                            )
        {
            ////////////////////////////////////////////////////////////// push all new data to the db without any selects

            return(SystemsDatabase.Instance.ExecuteWithDatabase(func: db =>
            {
                long updates = 0;

                DbTransaction txn = null;
                DbCommand replaceSectorCmd = null;
                DbCommand replaceSysCmd = null;
                DbCommand replaceNameCmd = null;
                try
                {
                    var cn = db.Connection;
                    txn = cn.BeginTransaction();

                    replaceSectorCmd = cn.CreateReplace("Sectors" + tablepostfix, new string[] { "name", "gridid", "id" }, new DbType[] { DbType.String, DbType.Int32, DbType.Int64 }, txn);

                    replaceSysCmd = cn.CreateReplace("Systems" + tablepostfix, new string[] { "sectorid", "nameid", "x", "y", "z", "edsmid" },
                                                     new DbType[] { DbType.Int64, DbType.Int64, DbType.Int32, DbType.Int32, DbType.Int32, DbType.Int64 }, txn);

                    replaceNameCmd = cn.CreateReplace("Names" + tablepostfix, new string[] { "name", "id" }, new DbType[] { DbType.String, DbType.Int64 }, txn);

                    foreach (var kvp in cache.SectorIDCache)                  // all sectors cached, id is unique so its got all sectors
                    {
                        Sector t = kvp.Value;

                        if (t.insertsec)                                   // if we have been told to insert the sector, do it
                        {
                            replaceSectorCmd.Parameters[0].Value = t.Name; // make a new one so we can get the ID
                            replaceSectorCmd.Parameters[1].Value = t.GId;
                            replaceSectorCmd.Parameters[2].Value = t.Id;   // and we insert with ID, managed by us, and replace in case there are any repeat problems (which there should not be)
                            replaceSectorCmd.ExecuteNonQuery();
                            //System.Diagnostics.Debug.WriteLine("Written sector " + t.GId + " " +t.Name);
                            t.insertsec = false;
                        }

                        if (t.edsmdatalist != null)       // if updated..
                        {
#if DEBUG
                            t.edsmdatalist.Sort(delegate(TableWriteData left, TableWriteData right) { return left.edsm.id.CompareTo(right.edsm.id); });
#endif

                            foreach (var data in t.edsmdatalist)            // now write the star list in this sector
                            {
                                try
                                {
                                    if (data.classifier.IsNamed)                                       // if its a named entry, we need a name
                                    {
                                        data.classifier.NameIdNumeric = data.edsm.id;                  // name is the edsm id
                                        replaceNameCmd.Parameters[0].Value = data.classifier.StarName; // insert a new name
                                        replaceNameCmd.Parameters[1].Value = data.edsm.id;             // we use edsmid as the nameid, and use replace to ensure that if a prev one is there, its replaced
                                        replaceNameCmd.ExecuteNonQuery();
                                        // System.Diagnostics.Debug.WriteLine("Make name " + data.classifier.NameIdNumeric);
                                    }

                                    replaceSysCmd.Parameters[0].Value = t.Id;
                                    replaceSysCmd.Parameters[1].Value = data.classifier.ID;
                                    replaceSysCmd.Parameters[2].Value = data.edsm.x;
                                    replaceSysCmd.Parameters[3].Value = data.edsm.y;
                                    replaceSysCmd.Parameters[4].Value = data.edsm.z;
                                    replaceSysCmd.Parameters[5].Value = data.edsm.id;       // in the event a new entry has the same edsmid, the system table edsmid is replace with new data
                                    replaceSysCmd.ExecuteNonQuery();

                                    if (sw != null)
                                    {
                                        sw.WriteLine(data.edsm.name + " " + data.edsm.x + "," + data.edsm.y + "," + data.edsm.z + ", EDSM:" + data.edsm.id + " Grid:" + data.gridid);
                                    }

                                    updates++;
                                }
                                catch (Exception ex)
                                {
                                    System.Diagnostics.Debug.WriteLine("general exception during insert - ignoring " + ex.ToString());
                                }
                            }
                        }

                        t.edsmdatalist = null;     // and delete back
                    }

                    txn.Commit();

                    return updates;
                }
                finally
                {
                    replaceSectorCmd?.Dispose();
                    replaceSysCmd?.Dispose();
                    replaceNameCmd?.Dispose();
                    txn?.Dispose();
                }
            }, warnthreshold: 5000));
        }
        private static int ProcessBlock(SectorCache cache,
                                        IEnumerator <JToken> enumerator,
                                        bool[] grididallowed,        // null = all, else grid bool value
                                        bool tablesareempty,
                                        string tablepostfix,
                                        ref DateTime maxdate,        // updated with latest date
                                        ref int nextsectorid,
                                        out bool jr_eof)
        {
            int       recordstostore  = 0;
            DbCommand selectSectorCmd = null;
            DateTime  cpmaxdate       = maxdate;
            int       cpnextsectorid  = nextsectorid;
            const int BlockSize       = 10000;
            int       Limit           = int.MaxValue;
            var       entries         = new List <TableWriteData>();

            jr_eof = false;

            while (true)
            {
                if (!enumerator.MoveNext())         // get next token, if not, stop eof
                {
                    jr_eof = true;
                    break;
                }

                JToken t = enumerator.Current;

                if (t.IsObject)                     // if start of object..
                {
                    EDSMFileEntry d = new EDSMFileEntry();

                    if (d.Deserialize(enumerator) && d.id >= 0 && d.name.HasChars() && d.z != int.MinValue)     // if we have a valid record
                    {
                        int gridid = GridId.Id128(d.x, d.z);
                        if (grididallowed == null || (grididallowed.Length > gridid && grididallowed[gridid]))    // allows a null or small grid
                        {
                            TableWriteData data = new TableWriteData()
                            {
                                edsm = d, classifier = new EliteNameClassifier(d.name), gridid = gridid
                            };

                            if (!TryCreateNewUpdate(cache, data, tablesareempty, ref cpmaxdate, ref cpnextsectorid, out Sector sector))
                            {
                                entries.Add(data);
                            }

                            recordstostore++;
                        }
                    }

                    if (--Limit == 0)
                    {
                        jr_eof = true;
                        break;
                    }

                    if (recordstostore >= BlockSize)
                    {
                        break;
                    }
                }
            }

            SystemsDatabase.Instance.ExecuteWithDatabase(action: db =>
            {
                try
                {
                    var cn = db.Connection;

                    selectSectorCmd = cn.CreateSelect("Sectors" + tablepostfix, "id", "name = @sname AND gridid = @gid", null,
                                                      new string[] { "sname", "gid" }, new DbType[] { DbType.String, DbType.Int32 });

                    foreach (var entry in entries)
                    {
                        CreateNewUpdate(cache, selectSectorCmd, entry, tablesareempty, ref cpmaxdate, ref cpnextsectorid);
                    }
                }
                finally
                {
                    if (selectSectorCmd != null)
                    {
                        selectSectorCmd.Dispose();
                    }
                }
            });

            maxdate      = cpmaxdate;
            nextsectorid = cpnextsectorid;

            return(recordstostore);
        }
        // take old system table and turn to new.  tablesarempty=false is normal, only set to true if using this code for checking replace algorithm

        public static long UpgradeDB102to200(Func <bool> cancelRequested, Action <string> reportProgress, string tablepostfix, bool tablesareempty = false, int maxgridid = int.MaxValue)
        {
            var cache = new SectorCache();

            int  nextsectorid = GetNextSectorID();
            long updates      = 0;

            long Limit = long.MaxValue;

            DateTime maxdate = DateTime.MinValue;       // we don't pass this back due to using the same date

            reportProgress?.Invoke("Begin System DB upgrade");
            List <int> gridids = DB.GridId.AllId();

            BaseUtils.AppTicks.TickCountLap("UTotal");

            //int debug_z = 0;

            foreach (int gridid in gridids)  // using grid id to keep chunks a good size.. can't read and write so can't just read the whole.
            {
                if (cancelRequested())
                {
                    updates = -1;
                    break;
                }

                if (gridid == maxgridid)        // for debugging
                {
                    break;
                }

                int       recordstostore  = 0;
                DbCommand selectSectorCmd = null;
                DbCommand selectPrev      = null;

                SystemsDatabase.Instance.ExecuteWithDatabase(db =>
                {
                    try
                    {
                        var cn = db.Connection;

                        selectSectorCmd = cn.CreateSelect("Sectors" + tablepostfix, "id", "name = @sname AND gridid = @gid", null,
                                                          new string[] { "sname", "gid" }, new DbType[] { DbType.String, DbType.Int32 });
                        selectPrev = cn.CreateSelect("EdsmSystems s", "s.EdsmId,s.x,s.y,s.z,n.Name,s.UpdateTimeStamp", "s.GridId = @gid", null,
                                                     new string[] { "gid" }, new DbType[] { DbType.Int32 },
                                                     joinlist: new string[] { "LEFT OUTER JOIN SystemNames n ON n.EdsmId=s.EdsmId" });

                        selectPrev.Parameters[0].Value = gridid;

                        using (DbDataReader reader = selectPrev.ExecuteReader())       // find name:gid
                        {
                            BaseUtils.AppTicks.TickCountLap("U1");

                            while (reader.Read())
                            {
                                try
                                {
                                    EDSMFileEntry d = new EDSMFileEntry();
                                    d.id            = (long)reader[0];
                                    d.x             = (int)(long)reader[1];
                                    d.y             = (int)(long)reader[2];
                                    d.z             = (int)(long)reader[3];
                                    d.name          = (string)reader[4];
                                    d.date          = new DateTime(2015, 1, 1, 0, 0, 0, DateTimeKind.Utc) + TimeSpan.FromSeconds((long)reader["UpdateTimestamp"]);
                                    int grididentry = GridId.Id128(d.x, d.z);  // because i don't trust the previous gridid - it should be the same as the outer loop, but lets recalc

                                    //if (!tablesareempty)  d.z = debug_z++;  // for debug checking

                                    CreateNewUpdate(cache, selectSectorCmd, d, grididentry, tablesareempty, ref maxdate, ref nextsectorid);      // not using gridid on purpose to double check it.
                                    recordstostore++;
                                }
                                catch (Exception ex)
                                {
                                    System.Diagnostics.Debug.WriteLine("Reading prev table" + ex);
                                }
                            }
                        }
                    }
                    finally
                    {
                        selectSectorCmd?.Dispose();
                    }
                }, 5000);

                //System.Diagnostics.Debug.WriteLine("Reader took " + BaseUtils.AppTicks.TickCountLap("U1") + " in " + gridid + "  " + recordpos + " total " + recordstostore);

                if (recordstostore >= 0)
                {
                    updates += StoreNewEntries(cache, tablepostfix, null);
                    reportProgress?.Invoke("System DB upgrade processed " + updates);

                    Limit -= recordstostore;

                    if (Limit <= 0)
                    {
                        break;
                    }

                    System.Threading.Thread.Sleep(20);      // just sleepy for a bit to let others use the db
                }

                var tres1 = BaseUtils.AppTicks.TickCountLapDelta("U1");
                var tres2 = BaseUtils.AppTicks.TickCountFrom("UTotal");
                System.Diagnostics.Debug.WriteLine("Sector " + gridid + " took " + tres1.Item1 + " store " + recordstostore + " total " + updates + " " + ((float)tres1.Item2 / (float)recordstostore) + " cumulative " + tres2);
            }

            reportProgress?.Invoke("System DB complete, processed " + updates);

            PutNextSectorID(nextsectorid);    // and store back

            return(updates);
        }
示例#8
0
        private static int ProcessBlock(SectorCache cache,
                                        JsonTextReader jr,
                                        bool[] grididallowed,        // null = all, else grid bool value
                                        bool tablesareempty,
                                        string tablepostfix,
                                        ref DateTime maxdate,        // updated with latest date
                                        ref int nextsectorid,
                                        ref bool jr_eof)
        {
            int       recordstostore  = 0;
            DbCommand selectSectorCmd = null;
            DateTime  cpmaxdate       = maxdate;
            int       cpnextsectorid  = nextsectorid;
            const int BlockSize       = 10000;
            int       Limit           = int.MaxValue;
            var       entries         = new List <TableWriteData>();

            while (jr_eof == false)
            {
                try
                {
                    if (jr.Read())
                    {
                        if (jr.TokenType == JsonToken.StartObject)
                        {
                            EDSMFileEntry d = new EDSMFileEntry();

                            if (d.Deserialize(jr) && d.id >= 0 && d.name.HasChars() && d.z != int.MinValue)     // if we have a valid record
                            {
                                int gridid = GridId.Id128(d.x, d.z);
                                if (grididallowed == null || (grididallowed.Length > gridid && grididallowed[gridid]))    // allows a null or small grid
                                {
                                    TableWriteData data = new TableWriteData()
                                    {
                                        edsm = d, classifier = new EliteNameClassifier(d.name), gridid = gridid
                                    };

                                    if (!TryCreateNewUpdate(cache, data, tablesareempty, ref cpmaxdate, ref cpnextsectorid, out Sector sector))
                                    {
                                        entries.Add(data);
                                    }

                                    recordstostore++;
                                }
                            }

                            if (--Limit == 0)
                            {
                                jr_eof = true;
                                break;
                            }

                            if (recordstostore >= BlockSize)
                            {
                                break;
                            }
                        }
                    }
                    else
                    {
                        jr_eof = true;
                        break;
                    }
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine("EDSM JSON file exception " + ex.ToString());
                    jr_eof = true;                                                                              // stop read, but let it continue to finish this section
                }
            }

            SystemsDatabase.Instance.ExecuteWithDatabase(action: db =>
            {
                try
                {
                    var cn = db.Connection;

                    selectSectorCmd = cn.CreateSelect("Sectors" + tablepostfix, "id", "name = @sname AND gridid = @gid", null,
                                                      new string[] { "sname", "gid" }, new DbType[] { DbType.String, DbType.Int32 });

                    foreach (var entry in entries)
                    {
                        CreateNewUpdate(cache, selectSectorCmd, entry, tablesareempty, ref cpmaxdate, ref cpnextsectorid);
                    }
                }
                finally
                {
                    if (selectSectorCmd != null)
                    {
                        selectSectorCmd.Dispose();
                    }
                }
            });

            maxdate      = cpmaxdate;
            nextsectorid = cpnextsectorid;

            return(recordstostore);
        }
示例#9
0
        // set tempostfix to use another set of tables

        public static long ParseEDSMJSON(JsonTextReader jr,
                                         bool[] grididallowed,      // null = all, else grid bool value
                                         ref DateTime maxdate,      // updated with latest date
                                         Func <bool> cancelRequested,
                                         Action <string> reportProgress,
                                         string tablepostfix,            // set to add on text to table names to redirect to another table
                                         bool tablesareempty    = false, // set to presume table is empty, so we don't have to do look up queries
                                         string debugoutputfile = null
                                         )
        {
            var cache = new SectorCache();

            long updates = 0;

            int          nextsectorid = GetNextSectorID();
            bool         jr_eof       = false;
            StreamWriter sw           = null;

            try
            {
#if DEBUG
                try
                {
                    if (debugoutputfile != null)
                    {
                        sw = new StreamWriter(debugoutputfile);
                    }
                }
                catch
                {
                }
#endif

                while (jr_eof == false)
                {
                    if (cancelRequested())
                    {
                        updates = -1;
                        break;
                    }

                    int recordstostore = ProcessBlock(cache, jr, grididallowed, tablesareempty, tablepostfix, ref maxdate, ref nextsectorid, ref jr_eof);

                    System.Diagnostics.Debug.WriteLine("Process " + BaseUtils.AppTicks.TickCountLap("L1") + "   " + updates);

                    if (recordstostore > 0)
                    {
                        updates += StoreNewEntries(cache, tablepostfix, sw);

                        reportProgress?.Invoke("EDSM Star database updated " + updates);
                    }

                    if (jr_eof)
                    {
                        break;
                    }

                    if (SQLiteConnectionSystem.IsReadWaiting)
                    {
                        System.Threading.Thread.Sleep(20);      // just sleepy for a bit to let others use the db
                    }
                }
            }
            finally
            {
                if (sw != null)
                {
                    sw.Close();
                }
            }

            System.Diagnostics.Debug.WriteLine("Process " + BaseUtils.AppTicks.TickCountLap("L1") + "   " + updates);
            reportProgress?.Invoke("EDSM Star database updated " + updates);


            PutNextSectorID(nextsectorid);    // and store back

            return(updates);
        }