/// <summary> /// [R1 is deprecated use R2] Reads or regenerates an index for a field in a table /// </summary> /// <param name="TableName"></param> /// <param name="f"></param> /// <param name="bForceRegen"></param> /// <value></value> Index GetIndex(string TableName, Field f, bool bForceRegen) { const string FuncErrCode=ClassErrCode+".0015"; try { lock(this.TableBlocking) { if(!this.TableBlocking.Contains(TableName)) this.TableBlocking[TableName] = new SortedList();// index cache } lock(this.TableBlocking[TableName]) { if((this.TableBlocking[TableName] as SortedList)[f.seq]!=null) return (this.TableBlocking[TableName] as SortedList)[f.seq] as Index; bool bRegen=true; if(!bForceRegen) { string indexname = TableName+".hi"+f.seq.ToString(); if(IndexFileExists(indexname)) { FileStream fs = FileStream2.NewFileStream(System.IO.Path.GetDirectoryName(DatabaseFilePath)+"\\"+indexname,FileMode.Open,FileAccess.ReadWrite,FileShare.None); BinaryReader br = new BinaryReader(fs); bool flag = br.ReadBoolean(); if(flag) { bRegen=true; } else { bRegen=false; // SoapFormatter formatter = new SoapFormatter(); // Index ndx = (Index)formatter.Deserialize(fs); Index ndx = Index.ReadIndexData(this,new BinaryReader(fs)); (this.TableBlocking[TableName] as SortedList)[f.seq]=ndx; } fs.Close(); } } if(bRegen) {// unique key if(!f.bIndexed) throw new Exception("Not indexed field"); if(f.bUnique) { Index ndx = new Index(); ndx.bUnique=true; CheckTable_FixContent(TableName,f); // por si las moscas FileStream fs = FileStream2.NewFileStream(System.IO.Path.GetDirectoryName(DatabaseFilePath)+"\\"+TableName+".hc"+f.seq.ToString(),FileMode.Open,FileAccess.Read,FileShare.None); BinaryReader br = new BinaryReader(fs); bool flag = br.ReadBoolean(); if(flag) { throw new Exception("Database corruption"); } else { HFI hfi = HFI.Read(TableName,DatabaseFilePath); for(long n=0;n<hfi.rowseq;n++) { object o = f.ReadData(this,br); ndx.ht[o]=n; } (this.TableBlocking[TableName] as SortedList)[f.seq]=ndx; } br.Close(); } else {// not unique key Index ndx = new Index(); ndx.bUnique=false; CheckTable_FixContent(TableName,f); // por si las moscas FileStream fs = FileStream2.NewFileStream(System.IO.Path.GetDirectoryName(DatabaseFilePath)+"\\"+TableName+".hc"+f.seq.ToString(),FileMode.Open,FileAccess.Read,FileShare.None); BinaryReader br = new BinaryReader(fs); bool flag = br.ReadBoolean(); if(flag) { throw new Exception("Database corruption"); } else { HFI hfi = HFI.Read(TableName,DatabaseFilePath); for(long n=0;n<hfi.rowseq;n++) { object o = f.ReadData(this,br); if(ndx.ht[o]==null) ndx.ht[o]=new ArrayList(); (ndx.ht[o] as ArrayList).Add(n); } (this.TableBlocking[TableName] as SortedList)[f.seq]=ndx; } br.Close(); } } return (this.TableBlocking[TableName] as SortedList)[f.seq] as Index; } } catch(Exception ex) { throw new Exception(ex.Message+"\n"+FuncErrCode+": Inner exception."); } }
/// <summary> /// [R1 is deprecated use R2] Adds a field if it not exists /// </summary> public void AddFieldIfNotExist(string TableName, Field f) { const string FuncErrCode=ClassErrCode+".0018"; try { lock(this.TableBlocking) { Field[] flds = this.GetFields(TableName); foreach(Field i in flds) { if(i.Name==f.Name) return; } this.AddField(TableName,f); } } catch(Exception ex) { throw new Exception(ex.Message+"\n"+FuncErrCode+": Inner exception."); } }
/// <summary> /// [R1 is deprecated use R2] Fixes unfinished writes in a previous table grow /// </summary> /// <param name="TableName"></param> /// <param name="f"></param> unsafe internal void CheckTable_FixContent(string TableName, Field f) { const string FuncErrCode=ClassErrCode+".0013"; try { lock(this.TableBlocking) { if(!this.TableBlocking.Contains(TableName)) this.TableBlocking[TableName] = new SortedList();// index cache } lock(this.TableBlocking[TableName]) { // Check content if(true) { FileStream fs = FileStream2.NewFileStream(System.IO.Path.GetDirectoryName(DatabaseFilePath)+"\\"+TableName+".hc"+f.seq.ToString(),FileMode.Open,FileAccess.ReadWrite,FileShare.None); BinaryReader br = new BinaryReader(fs); bool flag = br.ReadBoolean(); if(flag) //if(true) { HFI hfi = HFI.Read(TableName,DatabaseFilePath); long supposedLen = (f.DataSize()*hfi.rowseq)+sizeof(bool); long offset=fs.Length-supposedLen; if(fs.Length<supposedLen) { // Recovering corrupt data long start = (fs.Length-sizeof(bool))/f.DataSize(); fs.Position=start*f.DataSize()+sizeof(bool); BinaryWriter bw = new BinaryWriter(fs); for(long n=start;n<hfi.rowseq;n++) { f.WriteDefaultData(bw,false); } bw.Flush(); bw.BaseStream.Position=0; bw.Write((bool)false); // edition flag bw.Flush(); // Destroy the index if(f.bIndexed) { (TableBlocking[TableName] as SortedList)[f.seq]=null; SetDirtyIndexInDisc(TableName,f); } try { LogToFile("Warning","Recovering unfinished column.'"+TableName+"' by "+offset.ToString()+" bytes"); } catch { } } } fs.Flush(); fs.Close(); } } } catch(Exception ex) { throw new Exception(ex.Message+"\n"+FuncErrCode+": Inner exception."); } }
/// <summary> /// Invoked when in memory index is modified /// </summary> void SetDirtyIndexInDisc(string TableName, Field f) { const string FuncErrCode=ClassErrCode+".0012"; try { string indexname = System.IO.Path.GetDirectoryName(DatabaseFilePath)+"\\"+TableName+".hi"+f.seq.ToString(); FileStream fs = FileStream2.NewFileStream(indexname,FileMode.Open,FileAccess.Write,FileShare.None); BinaryWriter bw = new BinaryWriter(fs); bw.Write((bool)true); bw.Flush(); bw.Close(); // // if(!Table2DeletedIndex.ContainsKey(indexname)) // { // FileStream2.CloseHandle(indexname); // File.Delete(indexname); // Table2DeletedIndex[indexname]=0; // set the flag // } } catch(Exception ex) { throw new Exception(ex.Message+"\n"+FuncErrCode+": Inner exception."); } }
/// <summary> /// [R1 is deprecated use R2] Get fieldnames of a table /// </summary> internal Field[] GetFields(string Name) { const string FuncErrCode=ClassErrCode+".0011"; try { lock(this.TableBlocking) { if(FieldsCache[Name]==null) { string[] tblnames; GetTableNames(out tblnames); if(!new ArrayList(tblnames).Contains(Name)) throw new Exception("HyperNetDatabase error: Table not present."); string tbl = Name;//Path.GetDirectoryName(DatabaseFilePath)+"\\"+Name; long fatid; if(true) { FileStream fs = FileStream2.NewFileStream(System.IO.Path.GetDirectoryName(DatabaseFilePath)+"\\"+tbl+".hfi",FileMode.Open,FileAccess.Read,FileShare.None); BinaryReader br = new BinaryReader(fs); if(br.ReadInt64()!=magic) throw new Exception("HyperNetDatabase error: Magic failed."); fatid = br.ReadInt64(); br.Close(); } if(true) { FileStream fs = FileStream2.NewFileStream(System.IO.Path.GetDirectoryName(DatabaseFilePath)+"\\"+tbl+".hf"+fatid.ToString(),FileMode.Open,FileAccess.Read,FileShare.None); BinaryReader br = new BinaryReader(fs,System.Text.Encoding.UTF8); br.ReadInt64(); // read magic long fields = br.ReadInt64(); Field[] rv = new Field[fields]; for(int n=0;n<fields;n++) { rv[n]=new Field(); rv[n].Read(br); } br.Close(); FieldsCache[Name]=rv; return rv; } } else { return (Field[])FieldsCache[Name]; } } } catch(Exception ex) { throw new Exception(ex.Message+"\n"+FuncErrCode+": Inner exception."); } }
/// <summary> /// [R1 is deprecated use R2] Adds a table /// </summary> public void AddField(string TableName, Field f) { const string FuncErrCode=ClassErrCode+".0010"; try { lock(this.TableBlocking) { string[] tblnames; GetTableNames(out tblnames); if(!new ArrayList(tblnames).Contains(TableName)) throw new Exception("HyperNetDatabase error: Table not present."); // set entry if(!this.TableBlocking.Contains(TableName)) this.TableBlocking[TableName] = new SortedList(); } lock(this.TableBlocking[TableName]) { string tbl = TableName; QueryCacheDestroy(TableName); Field[] flds = GetFields(TableName); foreach(Field i in flds) { if(f.Name==i.Name) throw new Exception("HyperNetDatabase error: Column already present."); } FieldsCache[TableName]=null; // cancel Field Cache long fatid,rownum,fseq; HFI hfi = HFI.Read(tbl,DatabaseFilePath); fatid = hfi.fatid; rownum = hfi.rowseq; // gets new field seq fseq = hfi.fieldseq; hfi.fieldseq++; hfi.Write(tbl,DatabaseFilePath); fatid = (fatid + 1) % 2; if(true)// Fat { // Create fat file FileStream fs = FileStream2.NewFileStream(System.IO.Path.GetDirectoryName(DatabaseFilePath)+"\\"+tbl+".hf"+fatid.ToString(),FileMode.Create,FileAccess.Write,FileShare.None); BinaryWriter bw = new BinaryWriter(fs,System.Text.Encoding.UTF8); bw.Write(magic); bw.Write((long)(flds.Length+1)); for(int n=0;n<flds.Length;n++) flds[n].Write(bw); f.seq=fseq; f.Write(bw); bw.Flush(); bw.Close(); // try // { // // string fileName = System.IO.Path.GetDirectoryName(DatabaseFilePath)+"\\"+tbl+".hf"+((fatid + 1) % 2).ToString(); //// FileStream2.CloseHandle(fileName); // File.Delete(fileName); // } // catch // { // } // Create column data fs = FileStream2.NewFileStream(System.IO.Path.GetDirectoryName(DatabaseFilePath)+"\\"+tbl+".hc"+fseq.ToString(),FileMode.Create,FileAccess.Write,FileShare.None); bw = new BinaryWriter(fs,System.Text.Encoding.UTF8); bw.Write((bool)true); // edition flag bw.Flush(); for(int n=0;n<rownum;n++) { f.WriteDefaultData(bw,false); } bw.Flush(); bw.BaseStream.Position=0; bw.Write((bool)false); // edition flag bw.Flush(); bw.Close(); // Change fat pointer hfi.fatid=fatid; hfi.Write(tbl,DatabaseFilePath); } } } catch(Exception ex) { throw new Exception(ex.Message+"\n"+FuncErrCode+": Inner exception."); } }
/// <summary> /// Adds a table /// </summary> public void AddTable(string Name) { const string FuncErrCode=ClassErrCode+".0008"; try { lock(this.TableBlocking) { string[] tblnames; GetTableNames(out tblnames); if(new ArrayList(tblnames).Contains(Name)) throw new Exception("HyperNetDatabase error: Table already present."); string tbl = Name;//Path.GetDirectoryName(DatabaseFilePath)+"\\"+Name; if(true)// Fat0 { FileStream fs = FileStream2.NewFileStream(System.IO.Path.GetDirectoryName(DatabaseFilePath)+"\\"+tbl+".hf0",FileMode.Create,FileAccess.Write,FileShare.None); BinaryWriter bw = new BinaryWriter(fs); bw.Write(magic); bw.Write((long)0); // zero fields bw.Write((long)0); // FieldSeq number bw.Flush(); bw.Close(); } // Create field defs file (HyperFieldIndex) new HFI().Write(tbl,DatabaseFilePath); Field f = new Field(DeletedFieldName,true,FieldIndexing.IndexedNotUnique); AddField(tbl,f); } } catch(Exception ex) { throw new Exception(ex.Message+"\n"+FuncErrCode+": Inner exception."); } }