/// <summary> /// Retrieve metadata for a given object. /// DedupeObjectMap objects returned should be ordered in ascending order based on the chunk's position or address. /// </summary> /// <param name="key">Object key.</param> /// <returns>Object metadata.</returns> public override DedupeObject GetObjectMetadata(string key) { if (String.IsNullOrEmpty(key)) { throw new ArgumentNullException(nameof(key)); } key = DedupeCommon.SanitizeString(key); DbExpression e = new DbExpression( _ORM.GetColumnName <DedupeObject>(nameof(DedupeObject.Key)), DbOperators.Equals, key); DedupeObject ret = _ORM.SelectFirst <DedupeObject>(e); if (ret != null) { ret.Chunks = GetChunks(key); ret.ObjectMap = GetObjectMap(key); if (ret.ObjectMap != null && ret.ObjectMap.Count > 0) { ret.ObjectMap = ret.ObjectMap.OrderBy(o => o.ChunkAddress).ToList(); } } return(ret); }
/// <summary> /// Add a configuration key-value pair. /// </summary> /// <param name="key">The key.</param> /// <param name="val">The value.</param> public override void AddConfigData(string key, string val) { if (String.IsNullOrEmpty(key)) { throw new ArgumentNullException(nameof(key)); } if (String.IsNullOrEmpty(val)) { throw new ArgumentNullException(nameof(val)); } key = DedupeCommon.SanitizeString(key); val = DedupeCommon.SanitizeString(val); string keyCheckQuery = "SELECT * FROM DedupeConfig WHERE Key = '" + key + "'"; DataTable keyCheckResult; string keyDeleteQuery = "DELETE FROM DedupeConfig WHERE Key = '" + key + "'"; DataTable keyDeleteResult; string keyInsertQuery = "INSERT INTO DedupeConfig (Key, Val) VALUES ('" + key + "', '" + val + "')"; DataTable keyInsertResult; lock (_ConfigLock) { if (Query(keyCheckQuery, out keyCheckResult)) { Query(keyDeleteQuery, out keyDeleteResult); } Query(keyInsertQuery, out keyInsertResult); } return; }
/// <summary> /// Increment reference count for a chunk by its key. If the chunk does not exist, it is created. /// </summary> /// <param name="chunkKey">Chunk key.</param> /// <param name="length">The chunk length, used when creating the chunk.</param> public override void IncrementChunkRefcount(string chunkKey, int length) { if (String.IsNullOrEmpty(chunkKey)) { throw new ArgumentNullException(nameof(chunkKey)); } chunkKey = DedupeCommon.SanitizeString(chunkKey); lock (_ChunkLock) { DedupeChunk chunk = GetChunkMetadata(chunkKey); if (chunk != null) { chunk.RefCount = chunk.RefCount + 1; _ORM.Update <DedupeChunk>(chunk); } else { chunk = new DedupeChunk(chunkKey, length, 1); _ORM.Insert <DedupeChunk>(chunk); } } }
/// <summary> /// Retrieve metadata for a given object. /// </summary> /// <param name="name">The name of the object.</param> /// <param name="metadata">Object metadata.</param> /// <returns>True if successful.</returns> public override bool GetObjectMetadata(string name, out ObjectMetadata metadata) { if (String.IsNullOrEmpty(name)) { throw new ArgumentNullException(nameof(name)); } name = DedupeCommon.SanitizeString(name); metadata = null; string query = "SELECT * FROM ObjectMap WHERE Name = '" + name + "'"; DataTable result; bool success = false; lock (_ObjectLock) { success = Query(query, out result); } if (result == null || result.Rows.Count < 1) { return(false); } if (!success) { return(false); } metadata = ObjectMetadata.FromDataTable(result); return(true); }
public override bool GetConfigData(string key, out string val) { val = null; key = DedupeCommon.SanitizeString(key); string keyQuery = "SELECT configval FROM DedupeConfig WHERE configkey = '" + key + "' LIMIT 1"; DataTable result; lock (_ConfigLock) { result = _Database.Query(keyQuery); if (result != null && result.Rows.Count > 0) { foreach (DataRow curr in result.Rows) { val = curr["configval"].ToString(); if (_Debug) { Console.WriteLine("Returning " + key + ": " + val); } return(true); } } } return(false); }
/// <summary> /// Determine if a chunk exists in the index. /// </summary> /// <param name="key">Chunk key.</param> /// <returns>True if the chunk exists.</returns> public override bool ChunkExists(string key) { if (String.IsNullOrEmpty(key)) { return(false); } key = DedupeCommon.SanitizeString(key); string query = "SELECT * FROM ObjectMap WHERE ChunkKey = '" + key + "' LIMIT 1"; DataTable result; lock (_ObjectLock) { if (Query(query, out result)) { if (result != null && result.Rows.Count > 0) { return(true); } } } return(false); }
/// <summary> /// Determine if an object exists in the index. /// </summary> /// <param name="name">The name of the object.</param> /// <returns>True if the object exists.</returns> public override bool ObjectExists(string name) { if (String.IsNullOrEmpty(name)) { return(false); } name = DedupeCommon.SanitizeString(name); string query = "SELECT * FROM ObjectMap WHERE Name = '" + name + "' LIMIT 1"; DataTable result; lock (_ObjectLock) { if (Query(query, out result)) { if (result != null && result.Rows.Count > 0) { return(true); } } } return(false); }
/// <summary> /// Retrieve chunk metadata for a given object. /// </summary> /// <param name="key">Object key.</param> /// <returns>Chunks associated with the object.</returns> public override List <DedupeChunk> GetChunks(string key) { if (String.IsNullOrEmpty(key)) { throw new ArgumentNullException(nameof(key)); } List <DedupeChunk> ret = new List <DedupeChunk>(); key = DedupeCommon.SanitizeString(key); List <DedupeObjectMap> maps = GetObjectMap(key); if (maps == null || maps.Count < 1) { return(ret); } List <string> chunkKeys = maps.Select(m => m.ChunkKey).ToList(); if (chunkKeys == null || chunkKeys.Count < 1) { return(ret); } chunkKeys = chunkKeys.Distinct().ToList(); DbExpression e = new DbExpression( _ORM.GetColumnName <DedupeChunk>(nameof(DedupeChunk.Key)), DbOperators.In, chunkKeys); ret = _ORM.SelectMany <DedupeChunk>(e); return(ret); }
/// <summary> /// Retrieve a configuration value. /// </summary> /// <param name="key">The key.</param> /// <param name="val">The value.</param> /// <returns>True if successful.</returns> public override bool GetConfigData(string key, out string val) { val = null; if (String.IsNullOrEmpty(key)) { throw new ArgumentNullException(nameof(key)); } key = DedupeCommon.SanitizeString(key); string keyQuery = "SELECT Val FROM DedupeConfig WHERE Key = '" + key + "' LIMIT 1"; DataTable result; lock (_ConfigLock) { if (Query(keyQuery, out result)) { if (result != null && result.Rows.Count > 0) { foreach (DataRow curr in result.Rows) { val = curr["Val"].ToString(); if (_Debug) { Console.WriteLine("Returning " + key + ": " + val); } return(true); } } } } return(false); }
public override void DeleteObjectChunks(string name, out List <string> garbageCollectChunks) { garbageCollectChunks = new List <string>(); name = DedupeCommon.SanitizeString(name); string selectQuery = "SELECT * FROM ObjectMap WHERE Name = '" + name + "'"; string deleteObjectMapQuery = "DELETE FROM ObjectMap WHERE Name = '" + name + "'"; DataTable result; bool garbageCollect = false; lock (_ObjectLock) { result = _Database.Query(selectQuery); if (result == null || result.Rows.Count < 1) { return; } foreach (DataRow curr in result.Rows) { Chunk c = Chunk.FromDataRow(curr); DecrementChunkRefcount(c.Key, out garbageCollect); if (garbageCollect) { garbageCollectChunks.Add(c.Key); } } result = _Database.Query(deleteObjectMapQuery); } }
/// <summary> /// Retrieve chunk metadata for a given object. /// </summary> /// <param name="name">The name of the object.</param> /// <param name="chunks">Chunks associated with the object.</param> /// <returns>True if successful.</returns> public override bool GetObjectChunks(string name, out List <Chunk> chunks) { if (String.IsNullOrEmpty(name)) { throw new ArgumentNullException(nameof(name)); } name = DedupeCommon.SanitizeString(name); chunks = new List <Chunk>(); string query = "SELECT * FROM ObjectMap WHERE Name = '" + name + "'"; DataTable result; bool success = false; lock (_ObjectLock) { success = Query(query, out result); } if (result == null || result.Rows.Count < 1) { return(false); } if (!success) { return(false); } foreach (DataRow row in result.Rows) { chunks.Add(Chunk.FromDataRow(row)); } return(true); }
public override bool AddObjectChunk(string name, long totalLen, Chunk chunk) { if (String.IsNullOrEmpty(name)) { throw new ArgumentNullException(nameof(name)); } if (totalLen < 1) { throw new ArgumentException("Total length must be greater than zero."); } if (chunk == null) { throw new ArgumentNullException(nameof(chunk)); } name = DedupeCommon.SanitizeString(name); DataTable result = null; string query = AddObjectChunkQuery(name, totalLen, chunk); lock (_ObjectLock) { result = _Database.Query(query); return(IncrementChunkRefcount(chunk.Key, chunk.Length)); } }
public override bool GetObjectChunks(string name, out List <Chunk> chunks) { name = DedupeCommon.SanitizeString(name); chunks = new List <Chunk>(); string query = "SELECT * FROM ObjectMap WHERE Name = '" + name + "'"; DataTable result; lock (_ObjectLock) { result = _Database.Query(query); } if (result == null || result.Rows.Count < 1) { return(false); } foreach (DataRow row in result.Rows) { chunks.Add(Chunk.FromDataRow(row)); } return(true); }
public override bool AddObjectChunks(string name, long totalLen, List <Chunk> chunks) { name = DedupeCommon.SanitizeString(name); if (ObjectExists(name)) { return(false); } DataTable result; List <string> addObjectChunksQueries = BatchAddObjectChunksQuery(name, totalLen, chunks); lock (_ObjectLock) { foreach (string query in addObjectChunksQueries) { result = _Database.Query(query); } foreach (Chunk currChunk in chunks) { IncrementChunkRefcount(currChunk.Key, currChunk.Length); } } return(true); }
/// <summary> /// Add a configuration key-value pair. /// </summary> /// <param name="key">The key.</param> /// <param name="val">The value.</param> public override void AddConfigValue(string key, string val) { if (String.IsNullOrEmpty(key)) { throw new ArgumentNullException(nameof(key)); } if (String.IsNullOrEmpty(val)) { throw new ArgumentNullException(nameof(val)); } key = DedupeCommon.SanitizeString(key); val = DedupeCommon.SanitizeString(val); DbExpression e = new DbExpression( _ORM.GetColumnName <DedupeConfig>(nameof(DedupeConfig.Key)), DbOperators.Equals, key); DedupeConfig config = _ORM.SelectFirst <DedupeConfig>(e); if (config != null) { _ORM.Delete <DedupeConfig>(config); } config = new DedupeConfig(key, val); config = _ORM.Insert <DedupeConfig>(config); }
/// <summary> /// Decrement the reference count of a chunk by its key. If the reference count reaches zero, the chunk is deleted. /// </summary> /// <param name="chunkKey">Chunk key.</param> /// <returns>Boolean indicating if the chunk should be garbage collected.</returns> public override bool DecrementChunkRefcount(string chunkKey) { if (String.IsNullOrEmpty(chunkKey)) { throw new ArgumentNullException(nameof(chunkKey)); } chunkKey = DedupeCommon.SanitizeString(chunkKey); DedupeChunk chunk = GetChunkMetadata(chunkKey); if (chunk == null) { return(false); } chunk.RefCount = chunk.RefCount - 1; if (chunk.RefCount < 1) { _ORM.Delete <DedupeChunk>(chunk); return(true); } else { _ORM.Update <DedupeChunk>(chunk); return(false); } }
/// <summary> /// Retrieve chunks containing data within a range of bytes from the original object. /// </summary> /// <param name="name">Object name.</param> /// <param name="start">Starting range.</param> /// <param name="end">Ending range.</param> /// <param name="chunks">Chunks.</param> /// <returns>True if successful.</returns> public override bool GetChunksForRange(string name, long start, long end, out List <Chunk> chunks) { if (String.IsNullOrEmpty(name)) { throw new ArgumentNullException(nameof(name)); } if (start < 0) { throw new ArgumentOutOfRangeException("Start of range must be zero or greater."); } if (end < 0) { throw new ArgumentOutOfRangeException("End of range must be zero or greater."); } if (end < start) { throw new ArgumentOutOfRangeException("End of range must be greater than or equal to start of range."); } name = DedupeCommon.SanitizeString(name); chunks = new List <Chunk>(); string query = "SELECT * FROM ObjectMap " + "WHERE Name = '" + name + "' AND " + "(" + " (chunkAddress <= " + start + " AND chunkAddress + chunkLength > " + start + ") " + " OR (chunkAddress <= " + end + " AND chunkAddress + chunkLength > " + end + ") " + " OR (chunkAddress >= " + start + " AND chunkAddress <= " + end + ") " + ")"; DataTable result; bool success = false; lock (_ObjectLock) { success = Query(query, out result); } if (result == null || result.Rows.Count < 1) { return(false); } if (!success) { return(false); } foreach (DataRow row in result.Rows) { chunks.Add(Chunk.FromDataRow(row)); } chunks = chunks.OrderBy(c => c.Address).ToList(); return(true); }
/// <summary> /// Increment the reference count of a chunk key, or insert the key. /// </summary> /// <param name="key">The chunk key.</param> /// <param name="len">The length of the chunk.</param> /// <returns>True if successful.</returns> public override bool IncrementChunkRefcount(string key, long len) { if (String.IsNullOrEmpty(key)) { throw new ArgumentNullException(nameof(key)); } key = DedupeCommon.SanitizeString(key); string selectQuery = ""; string updateQuery = ""; string insertQuery = ""; DataTable selectResult; DataTable updateResult; DataTable insertResult; selectQuery = "SELECT * FROM ChunkRefcount WHERE ChunkKey = '" + key + "'"; insertQuery = "INSERT INTO ChunkRefcount (ChunkKey, ChunkLength, RefCount) VALUES ('" + key + "', '" + len + "', 1)"; lock (_ChunkRefcountLock) { if (Query(selectQuery, out selectResult)) { if (selectResult == null || selectResult.Rows.Count < 1) { #region New-Entry return(Query(insertQuery, out insertResult)); #endregion } else { #region Update int currCount = 0; foreach (DataRow curr in selectResult.Rows) { currCount = Convert.ToInt32(curr["RefCount"]); } currCount++; updateQuery = "UPDATE ChunkRefcount SET RefCount = '" + currCount + "' WHERE ChunkKey = '" + key + "'"; return(Query(updateQuery, out updateResult)); #endregion } } else { return(false); } } }
/// <summary> /// Decrement the reference count of a chunk key, or delete the key. /// </summary> /// <param name="key">The chunk key.</param> /// <param name="garbageCollect">Boolean indicating if the chunk should be garbage collected.</param> /// <returns>True if successful.</returns> public override bool DecrementChunkRefcount(string key, out bool garbageCollect) { garbageCollect = false; if (String.IsNullOrEmpty(key)) { throw new ArgumentNullException(nameof(key)); } key = DedupeCommon.SanitizeString(key); string selectQuery = ""; string updateQuery = ""; string deleteQuery = ""; DataTable selectResult; DataTable updateResult; DataTable deleteResult; selectQuery = "SELECT * FROM ChunkRefcount WHERE ChunkKey = '" + key + "'"; deleteQuery = "DELETE FROM ChunkRefcount WHERE ChunkKey = '" + key + "'"; lock (_ChunkRefcountLock) { if (Query(selectQuery, out selectResult)) { if (selectResult == null || selectResult.Rows.Count < 1) { return(false); } else { int currCount = 0; foreach (DataRow curr in selectResult.Rows) { currCount = Convert.ToInt32(curr["RefCount"]); } currCount--; if (currCount == 0) { garbageCollect = true; return(Query(deleteQuery, out deleteResult)); } else { updateQuery = "UPDATE ChunkRefcount SET RefCount = '" + currCount + "' WHERE ChunkKey = '" + key + "'"; return(Query(updateQuery, out updateResult)); } } } else { return(false); } } }
/// <summary> /// Add chunks from an object to the index. /// </summary> /// <param name="name">The name of the object.</param> /// <param name="totalLen">The total length of the object.</param> /// <param name="chunks">The chunks from the object.</param> /// <returns>True if successful.</returns> public override bool AddObjectChunks(string name, long totalLen, List <Chunk> chunks) { if (String.IsNullOrEmpty(name)) { throw new ArgumentNullException(nameof(name)); } if (totalLen < 1) { throw new ArgumentException("Total length must be greater than zero."); } if (chunks == null || chunks.Count < 1) { throw new ArgumentException("No chunk data supplied."); } name = DedupeCommon.SanitizeString(name); if (ObjectExists(name)) { return(false); } DataTable result; List <string> addObjectChunksQueries = BatchAddObjectChunksQuery(name, totalLen, chunks); lock (_ObjectLock) { foreach (string query in addObjectChunksQueries) { if (!Query(query, out result)) { if (_Debug) { Console.WriteLine("Insert query failed: " + query); } return(false); } } foreach (Chunk currChunk in chunks) { if (!IncrementChunkRefcount(currChunk.Key, currChunk.Length)) { if (_Debug) { Console.WriteLine("Unable to increment refcount for chunk: " + currChunk.Key); } return(false); } } } return(true); }
/// <summary> /// Delete an object and dereference the associated chunks. /// </summary> /// <param name="name">The name of the object.</param> /// <param name="garbageCollectChunks">List of chunk keys that should be garbage collected.</param> public override void DeleteObjectChunks(string name, out List <string> garbageCollectChunks) { garbageCollectChunks = new List <string>(); if (String.IsNullOrEmpty(name)) { throw new ArgumentNullException(nameof(name)); } name = DedupeCommon.SanitizeString(name); string selectQuery = "SELECT * FROM ObjectMap WHERE Name = '" + name + "'"; string deleteObjectMapQuery = "DELETE FROM ObjectMap WHERE Name = '" + name + "'"; DataTable result; bool garbageCollect = false; lock (_ObjectLock) { if (!Query(selectQuery, out result)) { if (_Debug) { Console.WriteLine("Unable to retrieve object map for object: " + name); } } if (result == null || result.Rows.Count < 1) { return; } foreach (DataRow curr in result.Rows) { Chunk c = Chunk.FromDataRow(curr); DecrementChunkRefcount(c.Key, out garbageCollect); if (garbageCollect) { garbageCollectChunks.Add(c.Key); } } if (!Query(deleteObjectMapQuery, out result)) { if (_Debug) { Console.WriteLine("Unable to delete object map entries for object: " + name); } } } }
public override bool DecrementChunkRefcount(string key, out bool garbageCollect) { garbageCollect = false; key = DedupeCommon.SanitizeString(key); string selectQuery = ""; string updateQuery = ""; string deleteQuery = ""; DataTable selectResult; DataTable updateResult; DataTable deleteResult; selectQuery = "SELECT * FROM ChunkRefcount WHERE ChunkKey = '" + key + "'"; deleteQuery = "DELETE FROM ChunkRefcount WHERE ChunkKey = '" + key + "'"; lock (_ChunkRefcountLock) { selectResult = _Database.Query(selectQuery); if (selectResult == null || selectResult.Rows.Count < 1) { return(false); } else { int currCount = 0; foreach (DataRow curr in selectResult.Rows) { currCount = Convert.ToInt32(curr["RefCount"]); } currCount--; if (currCount == 0) { garbageCollect = true; deleteResult = _Database.Query(deleteQuery); return(true); } else { updateQuery = "UPDATE ChunkRefcount SET RefCount = '" + currCount + "' WHERE ChunkKey = '" + key + "'"; updateResult = _Database.Query(updateQuery); return(true); } } } }
/// <summary> /// Determine if an object exists in the index. /// </summary> /// <param name="key">Object key.</param> /// <returns>True if the object exists.</returns> public override bool Exists(string key) { if (String.IsNullOrEmpty(key)) { return(false); } key = DedupeCommon.SanitizeString(key); DbExpression e = new DbExpression( _ORM.GetColumnName <DedupeObject>(nameof(DedupeObject.Key)), DbOperators.Equals, key); return(_ORM.Exists <DedupeObject>(e)); }
/// <summary> /// Retrieve metadata for a given chunk by its key. /// </summary> /// <param name="chunkKey">Chunk key.</param> /// <returns>Chunk metadata.</returns> public override DedupeChunk GetChunkMetadata(string chunkKey) { if (String.IsNullOrEmpty(chunkKey)) { throw new ArgumentNullException(nameof(chunkKey)); } chunkKey = DedupeCommon.SanitizeString(chunkKey); DbExpression e = new DbExpression( _ORM.GetColumnName <DedupeChunk>(nameof(DedupeChunk.Key)), DbOperators.Equals, chunkKey); DedupeChunk ret = _ORM.SelectFirst <DedupeChunk>(e); return(ret); }
public override bool ObjectExists(string name) { name = DedupeCommon.SanitizeString(name); string query = "SELECT * FROM ObjectMap WHERE Name = '" + name + "' LIMIT 1"; DataTable result; lock (_ObjectLock) { result = _Database.Query(query); if (result != null && result.Rows.Count > 0) { return(true); } } return(false); }
/// <summary> /// Add a new object to the index. /// </summary> /// <param name="key">Object key.</param> /// <param name="length">The total length of the object.</param> public override void AddObject(string key, long length) { if (String.IsNullOrEmpty(key)) { throw new ArgumentNullException(nameof(key)); } if (length < 1) { throw new ArgumentException("Length must be greater than zero."); } key = DedupeCommon.SanitizeString(key); if (Exists(key)) { throw new ArgumentException("An object with key '" + key + "' already exists."); } DedupeObject obj = _ORM.Insert <DedupeObject>(new DedupeObject(key, length)); }
/// <summary> /// Add chunk from an object to the index. /// </summary> /// <param name="name">The name of the object.</param> /// <param name="totalLen">The total length of the object.</param> /// <param name="chunk">Chunk from the object..</param> /// <returns>True if successful.</returns> public override bool AddObjectChunk(string name, long totalLen, Chunk chunk) { if (String.IsNullOrEmpty(name)) { throw new ArgumentNullException(nameof(name)); } if (totalLen < 1) { throw new ArgumentException("Total length must be greater than zero."); } if (chunk == null) { throw new ArgumentNullException(nameof(chunk)); } name = DedupeCommon.SanitizeString(name); DataTable result = null; string query = AddObjectChunkQuery(name, totalLen, chunk); lock (_ObjectLock) { if (!Query(query, out result)) { if (_Debug) { Console.WriteLine("Insert query failed: " + query); } return(false); } if (!IncrementChunkRefcount(chunk.Key, chunk.Length)) { if (_Debug) { Console.WriteLine("Unable to increment refcount for chunk: " + chunk.Key); } return(false); } } return(true); }
/// <summary> /// Retrieve the object map containing the metadata for a given address within the original object. /// </summary> /// <param name="key">Object key.</param> /// <param name="position">Starting byte position.</param> /// <returns>Dedupe object map.</returns> public override DedupeObjectMap GetObjectMapForPosition(string key, long position) { if (String.IsNullOrEmpty(key)) { throw new ArgumentNullException(nameof(key)); } if (position < 0) { throw new ArgumentOutOfRangeException("Start of range must be zero or greater."); } key = DedupeCommon.SanitizeString(key); DedupeObject obj = GetObjectMetadata(key); if (obj == null) { return(null); } string objMapTable = _ORM.GetTableName(typeof(DedupeObjectMap)); string objKeyCol = _ORM.GetColumnName <DedupeObjectMap>(nameof(DedupeObjectMap.ObjectKey)); string chunkAddrCol = _ORM.GetColumnName <DedupeObjectMap>(nameof(DedupeObjectMap.ChunkAddress)); string chunkLenCol = _ORM.GetColumnName <DedupeObjectMap>(nameof(DedupeObjectMap.ChunkLength)); string query = "SELECT * FROM " + objMapTable + " " + "WHERE " + " " + objKeyCol + " = '" + obj.Key + "' " + " AND " + chunkAddrCol + " <= " + position + " AND " + chunkAddrCol + " + " + chunkLenCol + " > " + position + " "; DedupeObjectMap map = null; DataTable result = _ORM.Query(query); if (result != null && result.Rows.Count > 0) { map = _ORM.DataRowToObject <DedupeObjectMap>(result.Rows[0]); } return(map); }
public override bool GetObjectMetadata(string name, out ObjectMetadata metadata) { name = DedupeCommon.SanitizeString(name); metadata = null; string query = "SELECT * FROM ObjectMap WHERE Name = '" + name + "'"; DataTable result; lock (_ObjectLock) { result = _Database.Query(query); } if (result == null || result.Rows.Count < 1) { return(false); } metadata = ObjectMetadata.FromDataTable(result); return(true); }
/// <summary> /// Retrieve the chunk containing data for a given address within the original object. /// </summary> /// <param name="name">Object name.</param> /// <param name="start">Starting range.</param> /// <param name="chunk">Chunk.</param> /// <returns>True if successful.</returns> public override bool GetChunkForPosition(string name, long start, out Chunk chunk) { if (String.IsNullOrEmpty(name)) { throw new ArgumentNullException(nameof(name)); } if (start < 0) { throw new ArgumentOutOfRangeException("Start of range must be zero or greater."); } chunk = null; name = DedupeCommon.SanitizeString(name); string query = "SELECT * FROM ObjectMap " + "WHERE " + " Name = '" + name + "' " + " AND chunkAddress <= " + start + " AND chunkAddress + chunkLength > " + start + " "; DataTable result; bool success = false; lock (_ObjectLock) { success = Query(query, out result); } if (result == null || result.Rows.Count < 1) { return(false); } if (!success) { return(false); } chunk = Chunk.FromDataRow(result.Rows[0]); return(true); }