/// <summary> /// Delete existing index /// </summary> /// <param name="name"></param> /// <returns></returns> public void DeleteIndex(string name) { if (IndexSpace != null) { IndexSpace.DeleteIndex(DEFS.PrepareFullIndexName(this.Name, name)); } else { VSIndex x = this.get_index(name); if (x == null) { throw new VSException(DEFS.E0052_DELETE_INDEX_ERROR_CODE, "- index is not found - '" + name + "'"); } // Remove all references VSIndex ref_x = get_index(DEFS.PrepareFullIndexName(DEFS.ParseIndexSpace(name), DEFS.INDEX_CROSS_REFERENCES)); x.Reset(); while (x.Next()) { long[] refs = x.CurrentRefs; for (int i = 0; i < refs.Length; i++) { byte[] key = VSLib.ConvertLongToByte(refs[i]); ref_x.delete_node(key, x.CurrentAvlNode.ID); } } index_list.Remove(x); index_list_full.Remove(x); x.purge(); } }
/// <summary> /// Write FBQE /// </summary> /// <param name="f"></param> private void SerializeFBQE(FBQE f) { VSLib.CopyBytes(buffer, VSLib.ConvertStringToByte(DEFS.FBQE_SIGNATURE), f.address + SG_POS, SG_LEN); VSLib.CopyBytes(buffer, VSLib.ConvertLongToByte(f.ADDRESS_START), f.address + ADDRESS_START_POS, ADDRESS_START_LEN); VSLib.CopyBytes(buffer, VSLib.ConvertLongToByte(f.ADDRESS_END), f.address + ADDRESS_END_POS, ADDRESS_END_LEN); VSLib.CopyBytes(buffer, VSLib.ConvertLongToByte(f.LENGTH), f.address + LENGTH_POS, LENGTH_LEN); VSLib.CopyBytes(buffer, VSLib.ConvertIntToByte(f.PREV), f.address + PREV_POS, PREV_LEN); VSLib.CopyBytes(buffer, VSLib.ConvertIntToByte(f.NEXT), f.address + NEXT_POS, NEXT_LEN); F_Object.Write(f.address, VSLib.GetByteArray(buffer, f.address, FBQE_LENGTH), FBQE_LENGTH); }
/// <summary> /// Delete reference /// </summary> /// <param name="rf"></param> /// <returns></returns> internal bool delete_ref(long rf) { int x = -1; List <long> refs = REFS.ToList <long>(); int count = refs.Count; for (int i = 0; i < count; i++) { int i2 = count - 1 - i; if (i > i2) { break; } if (refs[i] == rf) { x = i; } else if (refs[i2] == rf) { x = i2; } if (x > 0) { break; } } if (x < 0) { return(false); } else { refs.RemoveAt(x); } byte[] refs_new = new byte[refs.Count * 8]; for (int i = 0; i < refs.Count; i++) { VSLib.CopyBytes(refs_new, VSLib.ConvertLongToByte(refs[i]), (i * 8), 8); } ALLOCATION.Write(this.REF_POS, refs_new, refs_new.Length); // Write REF_COUNT = refs.Count; return(true); }
/// <summary> /// Lock current directory(all spaces) /// </summary> /// <returns></returns> private bool Lock() { if (IMO) { return(true); } byte[] shared_code = { 0x0F, 0, 0, 0, 0, 0, 0, 0 }; byte[] exclusive_code = { 0xFF, 0, 0, 0, 0, 0, 0, 0 }; long exclusive_lock_offset = 0; string lock_fn = root_path + "\\" + DEFS.LOCK_FILE_NAME; if (fslck == null) { lock_number = -1; if (!File.Exists(lock_fn)) { byte[] b = new byte[8192]; fslck = File.Create(lock_fn); fslck.Write(b, 0, b.Length); fslck.Close(); fslck = null; } fslck = File.Open(lock_fn, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite); long number = fslck.Length / lock_length; try { fslck.Lock(exclusive_lock_offset, fslck.Length); // Lock for both read/write exclusively lock_number = 0; fslck.Seek(lock_number, SeekOrigin.Begin); fslck.Write(exclusive_code, 0, exclusive_code.Length); fslck.Write(VSLib.ConvertLongToByte(DateTime.Now.ToBinary()), 0, 8); } catch (IOException e) { this.Error = e.Message; fslck.Close(); fslck = null; } return(lock_number >= 0); } else { return(true); } }
/// <summary> /// Convert long to byte array /// </summary> /// <param name="value"></param> /// <returns></returns> private static string GetAddressSignature(long value) { //string s = VSLib.ConvertLongToHexString(value); byte[] b = VSLib.ConvertLongToByte(value); int n = 0; for (int i = 0; i < b.Length; i++) { n += b[i] + (i * 8); if (n > 9999) { n -= 9999; } } return(n.ToString("D4")); }
/// <summary> /// Write DateTime /// </summary> /// <param name="address"></param> /// <param name="data"></param> /// <returns></returns> public void Write(long address, DateTime data) { Write(address, VSLib.ConvertLongToByte(data.Ticks), 8); }
/// <summary> /// Write data (long) /// </summary> /// <param name="address"></param> /// <param name="data"></param> /// <returns></returns> public void Write(long address, long data) { Write(address, VSLib.ConvertLongToByte(data), 8); }
/// <summary> /// Serialize all fields to object fields space /// Free excessive chunks if needed /// </summary> private void serialize() { // If no fields if (FCache.Count == 0) { set_alloc(ALLOC_RESET); FIELDS_SIZE = 0; FreeSpace = -1; FCache = null; return; } byte[] b = null; int old_size = (int)(FIELDS_SIZE); // Current used size (number of fields + all fields size) // 1. Calculate new size int new_size = FIRST_FIELD_OFFSET_REL; for (int i = 0; i < FCache.Count; i++) { new_size += FCache[i].FULL_LENGTH; } // 2. Check if space is availabe, extend if required if (new_size > (old_size + FreeSpace)) { sp.Extend(this, (new_size - old_size)); } // 3. Check if only value update is required List <FieldCache> afc = FCache; FCache = new List <FieldCache>(32); int array_size = (new_size > old_size) ? new_size : old_size; byte[] data = new byte[array_size]; int data_pos = FIRST_FIELD_OFFSET_REL; VSLib.CopyBytes(data, VSLib.ConvertIntToByte(new_size), FIELDS_SIZE_POS, FIELDS_SIZE_LEN); // Size VSLib.CopyBytes(data, VSLib.ConvertShortToByte((short)afc.Count), FIELDS_NUMBER_POS, FIELDS_NUMBER_LEN); // Fields number FCache.Clear(); for (int i = 0; i < afc.Count; i++) { FieldCache fc_element = afc[i]; if (!fc_element.DELETED) { fc_element.OFFSET = data_pos; // Type data[data_pos] = fc_element.TYPE; data_pos++; // Name length data[data_pos] = (byte)(fc_element.NAME.Length); data_pos++; // Name b = VSLib.ConvertStringToByte(fc_element.NAME); VSLib.CopyBytes(data, b, data_pos, b.Length); data_pos += b.Length; // Value if (FIELD_COMPRESS[fc_element.TYPE]) // int/long/decimal { data[data_pos] = (byte)(fc_element.LENGTH); data_pos++; } else if ((fc_element.TYPE == FIELD_TYPE_BYTES) | (fc_element.TYPE == FIELD_TYPE_STRING)) { b = compress(VSLib.ConvertLongToByte(fc_element.LENGTH), FIELD_TYPE_LONG); data[data_pos] = (byte)b.Length; data_pos++; if (b.Length > 0) { VSLib.CopyBytes(data, b, data_pos, b.Length); data_pos += b.Length; } } // Write value if (fc_element.VALUE.Length > 0) { VSLib.CopyBytes(data, fc_element.VALUE, data_pos, fc_element.VALUE.Length); data_pos += afc[i].LENGTH; } // Shift offset and add to cache fc_element.OLDLENGTH = afc[i].LENGTH; fc_element.STATE = STATE_LOADED; FCacheTree.Insert(fc_element.NAME, FCache.Count); FCache.Add(fc_element); } } base.Write(base.FIXED, data, data.Length); set_alloc(ALLOC_RENEW); // Fill the rest by zeros if le length < old length if (new_size < old_size) { long full_used_size = base.FIXED + new_size; b = new byte[old_size - new_size]; base.Write(full_used_size, b, b.Length); // Fill be zeros unused space // Multiple chunks, chech if there are exessive if (base.Chunk > 0) { sp.ShrinkObject(this, full_used_size); } } FreeSpace = (int)(this.Size - base.FIXED - new_size); }
/// <summary> /// Generic Set /// </summary> /// <param name="serialize">false = do not write (for multiple values at once)</param> /// <returns></returns> private void set_field(string name, byte type, byte[] data, bool serialize = true) { string nm = name.Trim(); if ((nm.Length < 1) | (nm.Length > 255)) { throw new VSException(DEFS.E0027_FIELD_WRITE_ERROR_CODE, "- " + name + " : name length shall be between 1 and 255"); } FieldCache fc; int index; byte[] compressed_length = null; // Compressed length // Initialize fields structure if (base.ALLOC == ALLOC_TYPE_RAW) { index = -1; set_alloc(ALLOC_INIT); FreeSpace = (int)(this.Size - FIRST_FIELD_OFFSET_ABS); FIELDS_NUMBER = (short)0; FIELDS_SIZE = FIRST_FIELD_OFFSET_REL; // Create cache FCache = new List <FieldCache>(32); // Create cache binary tree FCacheTree = new VSBBTree(FCT_NAME, 32, true); } else { index = find_field(nm, type); } // Field is not found in cache, add new field if (index < 0) { fc = new FieldCache(); fc.STATE = STATE_NEW; // New field fc.OFFSET = -1; fc.NAME = nm; fc.VALUE = compress(data, type); fc.LENGTH = fc.VALUE.Length; fc.OLDLENGTH = fc.VALUE.Length; fc.TYPE = type; fc.DATA_OFFSET = FIELD_NAME_POS + fc.NAME.Length; if ((fc.TYPE == FIELD_TYPE_INT) | (fc.TYPE == FIELD_TYPE_LONG)) { fc.DATA_OFFSET += 1; } else if ((fc.TYPE == FIELD_TYPE_BYTES) | (fc.TYPE == FIELD_TYPE_STRING)) { compressed_length = compress(VSLib.ConvertLongToByte(fc.LENGTH), FIELD_TYPE_LONG); fc.DATA_OFFSET += (compressed_length.Length + 1); } fc.FULL_LENGTH = fc.DATA_OFFSET + fc.LENGTH; // Add to the tree FCacheTree.Insert(fc.NAME, (long)FCache.Count); // Add to the cache FCache.Add(fc); } else { // Field found in cache, update fc = FCache[index]; byte[] b = compress(data, type); if (b.Length == fc.LENGTH) { if (b.Length == 0) { return; } bool eq = true; for (int i = 0; i < b.Length; i++) { if (b[i] != fc.VALUE[i]) { eq = false; break; } } if (eq) { return; // Value not changed } for (int i = 0; i < b.Length; i++) { fc.VALUE[i] = b[i]; } base.Write(base.FIXED + fc.OFFSET + fc.DATA_OFFSET, b, fc.LENGTH); fc.STATE = STATE_LOADED; FCache.RemoveAt(index); FCache.Insert(index, fc); set_alloc(ALLOC_RENEW); return; } fc.VALUE = b; fc.LENGTH = fc.VALUE.Length; fc.DATA_OFFSET = FIELD_NAME_POS + fc.NAME.Length; if ((fc.TYPE == FIELD_TYPE_INT) | (fc.TYPE == FIELD_TYPE_LONG)) { fc.DATA_OFFSET += 1; } else if ((fc.TYPE == FIELD_TYPE_BYTES) | (fc.TYPE == FIELD_TYPE_STRING)) { compressed_length = compress(VSLib.ConvertLongToByte(fc.LENGTH), FIELD_TYPE_LONG); fc.DATA_OFFSET += (compressed_length.Length + 1); } fc.FULL_LENGTH = fc.DATA_OFFSET + fc.LENGTH; // Update full length fc.STATE = STATE_UPDATED; FCache.RemoveAt(index); FCache.Insert(index, fc); } if (serialize) { this.serialize(); } }
/// <summary> /// Set DateTime value /// </summary> /// <param name="name"></param> /// <returns></returns> public void Set(string name, DateTime value) { set_field(name, FIELD_TYPE_DATETIME, VSLib.ConvertLongToByte(value.Ticks)); }
/// <summary> /// Set long value /// </summary> /// <param name="name"></param> /// <returns></returns> public void Set(string name, long value) { set_field(name, FIELD_TYPE_LONG, VSLib.ConvertLongToByte(value)); }
// long public new void Write(long address, long data) { this.Write(address, VSLib.ConvertLongToByte(data), 8); }
/// <summary> /// Write long /// </summary> /// <param name="offset"></param> /// <param name="data"></param> public void Write(long offset, long data) { byte[] b = VSLib.ConvertLongToByte(data); this.Write(offset, ref b); }