internal void getByteArray(Page pg, int i) { int len = BtreePage.getKeyStrSize(pg, i); int offs = BtreePage.firstKeyOffs + BtreePage.getKeyStrOffs(pg, i); byte[] bval = new byte[len]; Array.Copy(pg.data, offs, bval, 0, len); key = new Key(bval); }
internal void getStr(Page pg, int i) { int len = BtreePage.getKeyStrSize(pg, i); int offs = BtreePage.firstKeyOffs + BtreePage.getKeyStrOffs(pg, i); char[] sval = new char[len]; for (int j = 0; j < len; j++) { sval[j] = (char) Bytes.unpack2(pg.data, offs); offs += 2; } key = new Key(sval); }
/// <summary> /// Remove all associations with this name /// </summary> /// <param name="item">source item</param> /// <param name="name">attribute name (verb in terms of associative database model)</param> /// <returns>number of removed associations</returns> public int Unlink(Item item, String name) { checkIfActive(); int id; if (!db.name2id.TryGetValue(name, out id)) { return 0; } int nFields = item.fieldIds.Length; int nStrings = item.stringFields.Length; int nNumbers = item.numericFields.Length; int l, r; for (l = 0; l < nFields && item.fieldIds[l] != id; l++) ; for (r = l; r < nFields && item.fieldIds[r] == id; r++) ; if (l < r) { Index index = (Index)db.storage.GetObjectByOID(id); if (l < nStrings) { for (int i = l; i < r; i++) { index.Remove(new Key(item.stringFields[i].ToLower()), item); } item.stringFields = Arrays.Remove(item.stringFields, l, r - l); } else if (l < nStrings + nNumbers) { for (int i = l; i < r; i++) { index.Remove(new Key(item.numericFields[i - nStrings]), item); } item.numericFields = Arrays.Remove(item.numericFields, l - nStrings, r - l); } else { checkIfNotInverseLink(name); int j = l - nStrings - nNumbers; for (int i = l; i < r; i++) { removeLink(item, (Item)item.relations[j], id); item.relations.Remove(j); } } item.fieldIds = Arrays.Remove(item.fieldIds, l, r - l); modify(item); return r - l; } checkIfNotInverseLink(name); Key key = new Key(((long)item.Oid << 32) | (uint)id); int nUnlinked = 0; foreach (Item target in db.root.relations.Range(key, key)) { db.root.relations.Remove(key, target); removeLink(item, target, id); nUnlinked += 1; } item.fieldNames = null; return nUnlinked; }
internal void extract(Page pg, int offs, ClassDescriptor.FieldType type) { byte[] data = pg.data; switch (type) { case ClassDescriptor.FieldType.tpBoolean: key = new Key(data[offs] != 0); break; case ClassDescriptor.FieldType.tpSByte: key = new Key((sbyte)data[offs]); break; case ClassDescriptor.FieldType.tpByte: key = new Key(data[offs]); break; case ClassDescriptor.FieldType.tpShort: key = new Key(Bytes.unpack2(data, offs)); break; case ClassDescriptor.FieldType.tpUShort: key = new Key((ushort)Bytes.unpack2(data, offs)); break; case ClassDescriptor.FieldType.tpChar: key = new Key((char) Bytes.unpack2(data, offs)); break; case ClassDescriptor.FieldType.tpInt: key = new Key(Bytes.unpack4(data, offs)); break; case ClassDescriptor.FieldType.tpEnum: case ClassDescriptor.FieldType.tpUInt: case ClassDescriptor.FieldType.tpObject: case ClassDescriptor.FieldType.tpOid: key = new Key((uint)Bytes.unpack4(data, offs)); break; case ClassDescriptor.FieldType.tpLong: key = new Key(Bytes.unpack8(data, offs)); break; case ClassDescriptor.FieldType.tpDate: case ClassDescriptor.FieldType.tpULong: key = new Key((ulong)Bytes.unpack8(data, offs)); break; case ClassDescriptor.FieldType.tpFloat: key = new Key(Bytes.unpackF4(data, offs)); break; case ClassDescriptor.FieldType.tpDouble: key = new Key(Bytes.unpackF8(data, offs)); break; case ClassDescriptor.FieldType.tpGuid: key = new Key(Bytes.unpackGuid(data, offs)); break; case ClassDescriptor.FieldType.tpDecimal: key = new Key(Bytes.unpackDecimal(data, offs)); break; default: Debug.Assert(false, "Invalid type"); break; } }
internal BtreeKey(Key key, int oid) { this.key = key; this.oid = oid; }
internal static bool find(StorageImpl db, int pageId, Key firstKey, Key lastKey, Btree tree, int height, ArrayList result) { Page pg = db.getPage(pageId); int l = 0, n = getnItems(pg), r = n; int oid; height -= 1; try { if (tree.FieldType == ClassDescriptor.FieldType.tpString) { if (firstKey != null) { while (l < r) { int i = (l + r) >> 1; if (compareStr(firstKey, pg, i) >= firstKey.inclusion) { l = i + 1; } else { r = i; } } Debug.Assert(r == l); } if (lastKey != null) { if (height == 0) { while (l < n) { if (- compareStr(lastKey, pg, l) >= lastKey.inclusion) { return false; } oid = getKeyStrOid(pg, l); result.Add(db.lookupObject(oid, null)); l += 1; } } else { do { if (!find(db, getKeyStrOid(pg, l), firstKey, lastKey, tree, height, result)) { return false; } if (l == n) { return true; } } while (compareStr(lastKey, pg, l++) >= 0); return false; } } else { if (height == 0) { while (l < n) { oid = getKeyStrOid(pg, l); result.Add(db.lookupObject(oid, null)); l += 1; } } else { do { if (!find(db, getKeyStrOid(pg, l), firstKey, lastKey, tree, height, result)) { return false; } } while (++l <= n); } } } else if (tree.FieldType == ClassDescriptor.FieldType.tpArrayOfByte) { if (firstKey != null) { while (l < r) { int i = (l + r) >> 1; if (tree.compareByteArrays(firstKey, pg, i) >= firstKey.inclusion) { l = i + 1; } else { r = i; } } Debug.Assert(r == l); } if (lastKey != null) { if (height == 0) { while (l < n) { if (-tree.compareByteArrays(lastKey, pg, l) >= lastKey.inclusion) { return false; } oid = getKeyStrOid(pg, l); result.Add(db.lookupObject(oid, null)); l += 1; } } else { do { if (!find(db, getKeyStrOid(pg, l), firstKey, lastKey, tree, height, result)) { return false; } if (l == n) { return true; } } while (tree.compareByteArrays(lastKey, pg, l++) >= 0); return false; } } else { if (height == 0) { while (l < n) { oid = getKeyStrOid(pg, l); result.Add(db.lookupObject(oid, null)); l += 1; } } else { do { if (!find(db, getKeyStrOid(pg, l), firstKey, lastKey, tree, height, result)) { return false; } } while (++l <= n); } } } else { if (firstKey != null) { while (l < r) { int i = (l + r) >> 1; if (compare(firstKey, pg, i) >= firstKey.inclusion) { l = i + 1; } else { r = i; } } Debug.Assert(r == l); } if (lastKey != null) { if (height == 0) { while (l < n) { if (- compare(lastKey, pg, l) >= lastKey.inclusion) { return false; } oid = getReference(pg, maxItems - 1 - l); result.Add(db.lookupObject(oid, null)); l += 1; } return true; } else { do { if (!find(db, getReference(pg, maxItems - 1 - l), firstKey, lastKey, tree, height, result)) { return false; } if (l == n) { return true; } } while (compare(lastKey, pg, l++) >= 0); return false; } } if (height == 0) { while (l < n) { oid = getReference(pg, maxItems - 1 - l); result.Add(db.lookupObject(oid, null)); l += 1; } } else { do { if (!find(db, getReference(pg, maxItems - 1 - l), firstKey, lastKey, tree, height, result)) { return false; } } while (++l <= n); } } } finally { db.pool.unfix(pg); } return true; }
internal static int compare(Key key, Page pg, int i) { long i8; ulong u8; int i4; uint u4; float r4; double r8; switch (key.type) { case ClassDescriptor.FieldType.tpSByte: return (sbyte) key.ival - (sbyte)pg.data[BtreePage.firstKeyOffs + i]; case ClassDescriptor.FieldType.tpBoolean: case ClassDescriptor.FieldType.tpByte: return (byte)key.ival - pg.data[BtreePage.firstKeyOffs + i]; case ClassDescriptor.FieldType.tpShort: return (short) key.ival - Bytes.unpack2(pg.data, BtreePage.firstKeyOffs + i * 2); case ClassDescriptor.FieldType.tpUShort: return (ushort) key.ival - (ushort)Bytes.unpack2(pg.data, BtreePage.firstKeyOffs + i * 2); case ClassDescriptor.FieldType.tpChar: return (char) key.ival - (char) Bytes.unpack2(pg.data, BtreePage.firstKeyOffs + i * 2); case ClassDescriptor.FieldType.tpObject: case ClassDescriptor.FieldType.tpUInt: case ClassDescriptor.FieldType.tpOid: case ClassDescriptor.FieldType.tpEnum: u4 = (uint)Bytes.unpack4(pg.data, BtreePage.firstKeyOffs + i * 4); return (uint)key.ival < u4 ? -1 : (uint)key.ival == u4 ? 0 : 1; case ClassDescriptor.FieldType.tpInt: i4 = Bytes.unpack4(pg.data, BtreePage.firstKeyOffs + i * 4); return key.ival < i4 ? -1 : key.ival == i4 ? 0 : 1; case ClassDescriptor.FieldType.tpLong: i8 = Bytes.unpack8(pg.data, BtreePage.firstKeyOffs + i * 8); return key.lval < i8 ? -1 : key.lval == i8 ? 0 : 1; case ClassDescriptor.FieldType.tpDate: case ClassDescriptor.FieldType.tpULong: u8 = (ulong)Bytes.unpack8(pg.data, BtreePage.firstKeyOffs + i * 8); return (ulong)key.lval < u8 ? -1 : (ulong)key.lval == u8 ? 0 : 1; case ClassDescriptor.FieldType.tpFloat: r4 = Bytes.unpackF4(pg.data, BtreePage.firstKeyOffs + i * 4); return key.dval < r4 ? -1 : key.dval == r4 ? 0 : 1; case ClassDescriptor.FieldType.tpDouble: r8 = Bytes.unpackF8(pg.data, BtreePage.firstKeyOffs + i * 8); return key.dval < r8 ? -1 : key.dval == r8 ? 0 : 1; case ClassDescriptor.FieldType.tpDecimal: return key.dec.CompareTo(Bytes.unpackDecimal(pg.data, BtreePage.firstKeyOffs + i*16)); case ClassDescriptor.FieldType.tpGuid: return key.guid.CompareTo(Bytes.unpackGuid(pg.data, BtreePage.firstKeyOffs + i*16)); } Debug.Assert(false, "Invalid type"); return 0; }
internal static int compareStr(Key key, Page pg, int i) { char[] chars = (char[])key.oval; int alen = chars.Length; int blen = BtreePage.getKeyStrSize(pg, i); int minlen = alen < blen?alen:blen; int offs = BtreePage.getKeyStrOffs(pg, i) + BtreePage.firstKeyOffs; byte[] b = pg.data; for (int j = 0; j < minlen; j++) { int diff = chars[j] - (char) Bytes.unpack2(b, offs); if (diff != 0) { return diff; } offs += 2; } return alen - blen; }
private IEnumerable SearchReferenceProperty(VersionHistory type, string uri, NameVal[] patterns, SearchKind kind, DateTime timestamp, NameVal prop, bool compound, PropDef def, ArrayList refs) { refs.Add(def); NameVal[] restOfPatterns = compound ? patterns : SubArray(patterns); object val = prop.val; switch (prop.name) { case Symbols.Timestamp: if (val is Range) { Range range = (Range)val; if (range.from is DateTime) { Key fromKey = new Key((DateTime)range.from, range.fromInclusive); Key tillKey = new Key((DateTime)range.till, range.tillInclusive); return new SearchResult(root, type, uri, restOfPatterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), root.timeIndex.GetEnumerator(fromKey, tillKey), kind, timestamp)); } } else if (val is DateTime) { Key key = new Key((DateTime)val); return new SearchResult(root, type, uri, restOfPatterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), root.timeIndex.GetEnumerator(key, key), kind, timestamp)); } return new object[0]; // empty selection case Symbols.Rectangle: if (val is NameVal[]) { NameVal[] coord = (NameVal[])val; if (coord.Length == 4) { RectangleR2 r = new RectangleR2((double)coord[0].val, (double)coord[1].val, (double)coord[2].val, (double)coord[3].val); return new SearchResult(root, type, uri, restOfPatterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), root.spatialIndex.Overlaps(r).GetEnumerator(), kind, timestamp)); } } break; case Symbols.Point: if (val is NameVal[]) { NameVal[] coord = (NameVal[])val; if (coord.Length == 2) { double x = (double)coord[0].val; double y = (double)coord[1].val; RectangleR2 r = new RectangleR2(x, y, x, y); return new SearchResult(root, type, uri, restOfPatterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), root.spatialIndex.Overlaps(r).GetEnumerator(), kind, timestamp)); } } break; case Symbols.Keyword: if (val is string) { ArrayList keywords = new ArrayList(); foreach (string keyword in ((string)val).ToLower().Split(keywordSeparators)) { if (keyword.Length > 0 && !keywordStopList.ContainsKey(keyword)) { keywords.Add(keyword); } } IEnumerator[] occurences = new IEnumerator[keywords.Count]; for (int i = 0; i < occurences.Length; i++) { Key key = new Key((string)keywords[i]); occurences[i] = root.inverseIndex.GetEnumerator(key, key); } return new SearchResult(root, type, uri, restOfPatterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), db.Merge(occurences), kind, timestamp)); } break; } def = (PropDef)root.propDefIndex[prop.name]; if (def == null) { return new object[0]; // empty selection } if (val is Range) { Range range = (Range)val; if (range.from is double) { Key fromKey = new Key(new object[]{def, range.from}, range.fromInclusive); Key tillKey = new Key(new object[]{def, range.till}, range.tillInclusive); return new SearchResult(root, type, uri, restOfPatterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), root.numPropIndex.GetEnumerator(fromKey, tillKey), kind, timestamp)); } else if (range.from is DateTime) { Key fromKey = new Key(new object[]{def, range.from}, range.fromInclusive); Key tillKey = new Key(new object[]{def, range.till}, range.tillInclusive); return new SearchResult(root, type, uri, restOfPatterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), root.timePropIndex.GetEnumerator(fromKey, tillKey), kind, timestamp)); } else { Key fromKey = new Key(new object[]{def, range.from}, range.fromInclusive); Key tillKey = new Key(new object[]{def, range.till}, range.tillInclusive); return new SearchResult(root, type, uri, restOfPatterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), root.strPropIndex.GetEnumerator(fromKey, tillKey), kind, timestamp)); } } if (val is string) { string str = (string)prop.val; int wc = str.IndexOf('*'); if (wc < 0) { Key key = new Key(new object[]{def, str}); return new SearchResult(root, type, uri, restOfPatterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), root.strPropIndex.GetEnumerator(key, key), kind, timestamp)); } else if (wc > 0) { string prefix = str.Substring(0, wc); Key fromKey = new Key(new object[]{def, prefix}); Key tillKey = new Key(new object[]{def, prefix + Char.MaxValue}, false); return new SearchResult(root, type, uri, wc == str.Length-1 ? restOfPatterns : patterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), root.strPropIndex.GetEnumerator(fromKey, tillKey), kind, timestamp)); } } else if (val is double) { Key key = new Key(new object[]{def, val}); return new SearchResult(root, type, uri, restOfPatterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), root.numPropIndex.GetEnumerator(key, key), kind, timestamp)); } else if (val is DateTime) { Key key = new Key(new object[]{def, (DateTime)val}); return new SearchResult(root, type, uri, restOfPatterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), root.timePropIndex.GetEnumerator(key, key), kind, timestamp)); } else if (val is NameVal) { return SearchReferenceProperty(type, uri, patterns, kind, timestamp, (NameVal)val, compound, def, refs); } else if (val is NameVal[]) { NameVal[] props = (NameVal[])val; if (props.Length > 0) { return SearchReferenceProperty(type, uri, patterns, kind, timestamp, props[0], true, def, refs); } } return null; }
public bool MoveNext() { while (true) { while (pos < iterators.Length && !iterators[pos].MoveNext()) { pos += 1; } if (pos == iterators.Length) { currThing = null; return false; } Thing thing = (Thing)iterators[pos].Current; switch (kind) { case SearchKind.LatestVersion: if (!thing.IsLatest()) { continue; } break; case SearchKind.LatestBefore: if (thing.timestamp > timestamp) { continue; } break; case SearchKind.OldestAfter: if (thing.timestamp < timestamp) { continue; } break; } if (pos == 0) { if (visited.ContainsKey(thing.Oid)) { continue; } else { visited[thing.Oid] = true; } currThing = thing; return true; } pos -= 1; Key key = new Key(new object[]{defs[pos], thing.vh}); iterators[pos] = root.refPropIndex.GetEnumerator(key, key); } }
/// <summary>Get iterator through object matching specified search parameters</summary> /// <param name="type">String representing type of the object (direct or indirect - IsInstanceOf /// method will be used to check if object belongs to the specified type). It may be null, /// in this case type criteria is skipped.</param> /// <param name="uri">Object URI pattern. It may be null, in this case URI is not inspected.</param> /// <param name="patterns">array of name:value pairs specifying search condition for object properties</param> /// <param name="kind">search kind used to select inspected versions</param> /// <param name="timestamp">timestamp used to select versions, if kind is SearchKind.LatestVersion /// or SearchKind.AllVersions this parameter is ignored</param> /// <returns>Enumerator through object meet search criteria.</returns> public IEnumerable Search(string type, string uri, NameVal[] patterns, SearchKind kind, DateTime timestamp) { VersionHistory typeVh = null; root.SharedLock(); try { if (type != null) { typeVh = GetObject(type); if (typeVh == null) { return new object[0]; // empty selection } } if (uri != null) { int wc = uri.IndexOf('*'); if (wc < 0) { return new SearchResult(root, typeVh, null, patterns, kind, timestamp, root.prefixUriIndex.GetEnumerator(uri, uri)); } else if (wc > 0) { String prefix = uri.Substring(0, wc); return new SearchResult(root, typeVh, uri, patterns, kind, timestamp, root.prefixUriIndex.GetEnumerator(prefix)); } else if ((wc = uri.LastIndexOf('*')) < uri.Length-1) { String suffix = ReverseString(uri.Substring(wc+1, uri.Length-wc-1)); return new SearchResult(root, typeVh, uri, patterns, kind, timestamp, root.suffixUriIndex.GetEnumerator(suffix)); } } if (patterns.Length > 0) { NameVal prop = patterns[0]; object val = prop.val; NameVal[] restOfPatterns = SubArray(patterns); switch (prop.name) { case Symbols.Timestamp: if (val is Range) { Range range = (Range)val; if (range.from is DateTime) { Key fromKey = new Key((DateTime)range.from, range.fromInclusive); Key tillKey = new Key((DateTime)range.till, range.tillInclusive); return new SearchResult(root, typeVh, uri, restOfPatterns, kind, timestamp, root.timeIndex.GetEnumerator(fromKey, tillKey)); } } else if (val is DateTime) { Key key = new Key((DateTime)val); return new SearchResult(root, typeVh, uri, restOfPatterns, kind, timestamp, root.timeIndex.GetEnumerator(key, key)); } return new object[0]; // empty selection case Symbols.Rectangle: if (val is NameVal[]) { NameVal[] coord = (NameVal[])val; if (coord.Length == 4) { RectangleR2 r = new RectangleR2((double)coord[0].val, (double)coord[1].val, (double)coord[2].val, (double)coord[3].val); return new SearchResult(root, typeVh, uri, restOfPatterns, kind, timestamp, root.spatialIndex.Overlaps(r).GetEnumerator()); } } break; case Symbols.Point: if (val is NameVal[]) { NameVal[] coord = (NameVal[])val; if (coord.Length == 2) { double x = (double)coord[0].val; double y = (double)coord[1].val; RectangleR2 r = new RectangleR2(x, y, x, y); return new SearchResult(root, typeVh, uri, restOfPatterns, kind, timestamp, root.spatialIndex.Overlaps(r).GetEnumerator()); } } break; case Symbols.Keyword: if (val is string) { ArrayList keywords = new ArrayList(); foreach (string keyword in ((string)val).ToLower().Split(keywordSeparators)) { if (keyword.Length > 0 && !keywordStopList.ContainsKey(keyword)) { keywords.Add(keyword); } } IEnumerator[] occurences = new IEnumerator[keywords.Count]; for (int i = 0; i < occurences.Length; i++) { Key key = new Key((string)keywords[i]); occurences[i] = root.inverseIndex.GetEnumerator(key, key); } return new SearchResult(root, typeVh, uri, restOfPatterns, kind, timestamp, db.Merge(occurences)); } break; } PropDef def = (PropDef)root.propDefIndex[prop.name]; if (def == null) { return new object[0]; // empty selection } if (val is Range) { Range range = (Range)val; if (range.from is double) { Key fromKey = new Key(new object[]{def, range.from}, range.fromInclusive); Key tillKey = new Key(new object[]{def, range.till}, range.tillInclusive); return new SearchResult(root, typeVh, uri, restOfPatterns, kind, timestamp, root.numPropIndex.GetEnumerator(fromKey, tillKey)); } else if (range.from is DateTime) { Key fromKey = new Key(new object[]{def, range.from}, range.fromInclusive); Key tillKey = new Key(new object[]{def, range.till}, range.tillInclusive); return new SearchResult(root, typeVh, uri, restOfPatterns, kind, timestamp, root.timePropIndex.GetEnumerator(fromKey, tillKey)); } else { Key fromKey = new Key(new object[]{def, range.from}, range.fromInclusive); Key tillKey = new Key(new object[]{def, range.till}, range.tillInclusive); return new SearchResult(root, typeVh, uri, restOfPatterns, kind, timestamp, root.strPropIndex.GetEnumerator(fromKey, tillKey)); } } else if (val is string) { string str = (string)val; int wc = str.IndexOf('*'); if (wc < 0) { Key key = new Key(new object[]{def, str}); return new SearchResult(root, typeVh, uri, restOfPatterns, kind, timestamp, root.strPropIndex.GetEnumerator(key, key)); } else if (wc > 0) { string prefix = str.Substring(0, wc); Key fromKey = new Key(new object[]{def, prefix}); Key tillKey = new Key(new object[]{def, prefix + Char.MaxValue}, false); return new SearchResult(root, typeVh, uri, wc == str.Length-1 ? restOfPatterns : patterns, kind, timestamp, root.strPropIndex.GetEnumerator(fromKey, tillKey)); } } else if (val is double) { Key key = new Key(new object[]{def, val}); return new SearchResult(root, typeVh, uri, restOfPatterns, kind, timestamp, root.numPropIndex.GetEnumerator(key, key)); } else if (val is DateTime) { Key key = new Key(new object[]{def, val}); return new SearchResult(root, typeVh, uri, restOfPatterns, kind, timestamp, root.timePropIndex.GetEnumerator(key, key)); } else if (val is NameVal) { IEnumerable iterator = SearchReferenceProperty(typeVh, uri, patterns, kind, timestamp, (NameVal)val, false, def, new ArrayList()); if (iterator != null) { return iterator; } } else if (val is NameVal[]) { NameVal[] props = (NameVal[])val; if (props.Length > 0) { IEnumerable iterator = SearchReferenceProperty(typeVh, uri, patterns, kind, timestamp, props[0], props.Length > 1, def, new ArrayList()); if (iterator != null) { return iterator; } } } } if (kind == SearchKind.LatestVersion) { return new SearchResult(root, typeVh, uri, patterns, kind, timestamp, root.latest.GetEnumerator()); } return new SearchResult(root, typeVh, uri, patterns, kind, timestamp, root.timeIndex.GetEnumerator()); } finally { root.Unlock(); } }
private Thing CreateObject(Thing type, VersionHistory vh, NameVal[] props) { Thing thing = new Thing(); thing.vh = vh; thing.type = type; thing.timestamp = DateTime.Now; thing.props = new PropVal[props.Length]; for (int i = 0; i < props.Length; i++) { NameVal prop = props[i]; PropDef def = (PropDef)root.propDefIndex[prop.name]; if (def == null) { def = new PropDef(); def.name = prop.name; root.propDefIndex.Put(def); } object val = prop.val; PropVal pv = new PropVal(def, val); Key key = new Key(new object[]{def, val}); if (val is string) { root.strPropIndex.Put(key, thing); foreach (string keyword in ((string)val).ToLower().Split(keywordSeparators)) { if (keyword.Length > 0 && !keywordStopList.ContainsKey(keyword)) { root.inverseIndex.Put(keyword, thing); } } } else if (val is double) { root.numPropIndex.Put(key, thing); } else if (val is DateTime) { root.timePropIndex.Put(key, thing); } else if (val is VersionHistory || val == null) { root.refPropIndex.Put(key, thing); if (prop.name == Symbols.Rectangle) { PropVal[] coord = ((VersionHistory)val).Latest.props; RectangleR2 r = new RectangleR2((double)coord[0].val, (double)coord[1].val, (double)coord[2].val, (double)coord[3].val); root.spatialIndex.Put(r, thing); } else if (prop.name == Symbols.Point) { PropVal[] coord = ((VersionHistory)val).Latest.props; double x = (double)coord[0].val; double y = (double)coord[1].val; RectangleR2 r = new RectangleR2(x, y, x, y); root.spatialIndex.Put(r, thing); } } else { throw new InvalidOperationException("Invalid propery value type " + prop.val.GetType()); } thing.props[i] = pv; } thing.Modify(); vh.versions.Add(thing); root.timeIndex.Put(thing); root.latest.Add(thing); return thing; }