public override IEnumerable <BsonDocument> Input(BsonValue options) { var pageID = GetOption(options, "pageID"); var transaction = _monitor.GetTransaction(true, out var isNew); var snapshot = transaction.CreateSnapshot(LockMode.Read, "$", false); _collections = _header.GetCollections().ToDictionary(x => x.Value, x => x.Key); try { var result = pageID != null? this.GetList((uint)pageID.AsInt32, null, transaction, snapshot) : this.GetAllList(transaction, snapshot); foreach (var page in result) { yield return(page); } } finally { transaction.Commit(); } }
private IEnumerable <BsonDocument> DumpPages(uint?pageID) { var collections = _header.GetCollections().ToDictionary(x => x.Value, x => x.Key); var transaction = _monitor.GetTransaction(true, out var isNew); try { var snapshot = transaction.CreateSnapshot(LockMode.Read, "$", false); var start = pageID.HasValue ? pageID.Value : 0; var end = pageID.HasValue ? pageID.Value : _header.LastPageID; for (uint i = start; i <= Math.Min(end, _header.LastPageID); i++) { var page = snapshot.GetPage <BasePage>(i, out var origin, out var position, out var walVersion); var doc = new BsonDocument { ["pageID"] = (int)page.PageID, ["pageType"] = page.PageType.ToString(), ["_position"] = position, ["_origin"] = origin.ToString(), ["_version"] = walVersion, ["nextPageID"] = (int)page.NextPageID, ["prevPageID"] = (int)page.PrevPageID, ["collection"] = collections.GetOrDefault(page.ColID, "-"), ["itemsCount"] = (int)page.ItemsCount, ["freeBytes"] = page.FreeBytes, ["usedBytes"] = (int)page.UsedBytes, ["fragmentedBytes"] = (int)page.FragmentedBytes, ["nextFreePosition"] = (int)page.NextFreePosition, ["highestIndex"] = (int)page.HighestIndex }; if (pageID.HasValue) { doc["buffer"] = page.Buffer.ToArray(); } yield return(doc); transaction.Safepoint(); } } finally { transaction.Commit(); } }
/// <summary> /// Run query definition into engine. Execute optimization to get query planner /// </summary> internal BsonDataReader ExecuteQuery(bool executionPlan) { var transaction = _monitor.GetTransaction(true, out var isNew); transaction.OpenCursors.Add(_cursor); try { // encapsulate all execution to catch any error return(new BsonDataReader(RunQuery(), _collection)); } catch { // if any error, rollback transaction transaction.Rollback(); // remove cursor transaction.OpenCursors.Remove(_cursor); throw; } IEnumerable <BsonDocument> RunQuery() { var snapshot = transaction.CreateSnapshot(_query.ForUpdate ? LockMode.Write : LockMode.Read, _collection, false); // no collection, no documents if (snapshot.CollectionPage == null && _source == null) { // if query use Source (*) need runs with empty data source if (_query.Select.UseSource) { yield return(_query.Select.ExecuteScalar(_pragmas.Collation).AsDocument); } transaction.OpenCursors.Remove(_cursor); if (transaction.OpenCursors.Count == 0 && transaction.ExplicitTransaction == false) { transaction.Commit(); } yield break; } // execute optimization before run query (will fill missing _query properties instance) var optimizer = new QueryOptimization(snapshot, _query, _source, _pragmas.Collation); var queryPlan = optimizer.ProcessQuery(); // if execution is just to get explan plan, return as single document result if (executionPlan) { yield return(queryPlan.GetExecutionPlan()); transaction.OpenCursors.Remove(_cursor); if (transaction.OpenCursors.Count == 0 && transaction.ExplicitTransaction == false) { transaction.Commit(); } yield break; } // get node list from query - distinct by dataBlock (avoid duplicate) var nodes = queryPlan.Index.Run(snapshot.CollectionPage, new IndexService(snapshot, _pragmas.Collation)); // get current query pipe: normal or groupby pipe var pipe = queryPlan.GetPipe(transaction, snapshot, _sortDisk, _pragmas); try { // start cursor elapsed timer _cursor.Elapsed.Start(); // call safepoint just before return each document foreach (var doc in pipe.Pipe(nodes, queryPlan)) { _cursor.Fetched++; _cursor.Elapsed.Stop(); yield return(doc); _cursor.Elapsed.Start(); } } finally { // stop cursor elapsed _cursor.Elapsed.Stop(); transaction.OpenCursors.Remove(_cursor); if (transaction.OpenCursors.Count == 0 && transaction.ExplicitTransaction == false) { transaction.Commit(); } } }; }
/// <summary> /// Run query definition into engine. Execute optimization to get query planner /// </summary> internal BsonDataReader ExecuteQuery(bool executionPlan) { var transaction = _monitor.GetTransaction(true, out var isNew); transaction.OpenCursors++; try { // encapsulate all execution to catch any error return(new BsonDataReader(RunQuery(), _collection)); } catch { // if any error, rollback transaction transaction.Rollback(); throw; } IEnumerable <BsonDocument> RunQuery() { var snapshot = transaction.CreateSnapshot(_query.ForUpdate ? LockMode.Write : LockMode.Read, _collection, false); // no collection, no documents if (snapshot.CollectionPage == null && _source == null) { if (--transaction.OpenCursors == 0 && transaction.ExplicitTransaction == false) { transaction.Commit(); } yield break; } // execute optimization before run query (will fill missing _query properties instance) var optimizer = new QueryOptimization(snapshot, _query, _source); var queryPlan = optimizer.ProcessQuery(); // if execution is just to get explan plan, return as single document result if (executionPlan) { LOG($"explain `{_collection}`", "COMMAND"); yield return(queryPlan.GetExecutionPlan()); if (--transaction.OpenCursors == 0 && transaction.ExplicitTransaction == false) { transaction.Commit(); } yield break; } LOG($"query `{_collection}`", "COMMAND"); // get node list from query - distinct by dataBlock (avoid duplicate) var nodes = queryPlan.Index.Run(snapshot.CollectionPage, new IndexService(snapshot)); // get current query pipe: normal or groupby pipe using (var pipe = queryPlan.GetPipe(transaction, snapshot, _sortDisk, _utcDate)) { // commit transaction before close pipe pipe.Disposing += (s, e) => { if (--transaction.OpenCursors == 0 && transaction.ExplicitTransaction == false) { transaction.Commit(); } }; // call safepoint just before return each document foreach (var doc in pipe.Pipe(nodes, queryPlan)) { yield return(doc); } } }; }
/// <summary> /// Run query definition into engine. Execute optimization to get query planner /// </summary> internal BsonDataReader ExecuteQuery(bool executionPlan) { // get current transaction (if contains a explicit transaction) or a query-only transaction var transaction = _monitor.GetTransaction(true, true, out var isNew); transaction.OpenCursors.Add(_cursor); // return new BsonDataReader with IEnumerable source return(new BsonDataReader(RunQuery(), _collection)); IEnumerable <BsonDocument> RunQuery() { try { var snapshot = transaction.CreateSnapshot(_query.ForUpdate ? LockMode.Write : LockMode.Read, _collection, false); // no collection, no documents if (snapshot.CollectionPage == null && _source == null) { // if query use Source (*) need runs with empty data source if (_query.Select.UseSource) { yield return(_query.Select.ExecuteScalar(_pragmas.Collation).AsDocument); } yield break; } // execute optimization before run query (will fill missing _query properties instance) var optimizer = new QueryOptimization(snapshot, _query, _source, _pragmas.Collation); var queryPlan = optimizer.ProcessQuery(); // if execution is just to get explan plan, return as single document result if (executionPlan) { yield return(queryPlan.GetExecutionPlan()); yield break; } // get node list from query - distinct by dataBlock (avoid duplicate) var nodes = queryPlan.Index.Run(snapshot.CollectionPage, new IndexService(snapshot, _pragmas.Collation)); // get current query pipe: normal or groupby pipe var pipe = queryPlan.GetPipe(transaction, snapshot, _sortDisk, _pragmas); try { // start cursor elapsed timer _cursor.Elapsed.Start(); // call safepoint just before return each document foreach (var doc in pipe.Pipe(nodes, queryPlan)) { _cursor.Fetched++; _cursor.Elapsed.Stop(); yield return(doc); if (transaction.State != TransactionState.Active) { throw new LiteException(0, $"There is no more active transaction for this cursor: {_cursor.Query.ToSQL(_cursor.Collection)}"); } _cursor.Elapsed.Start(); } } finally { // stop cursor elapsed _cursor.Elapsed.Stop(); } } finally { transaction.OpenCursors.Remove(_cursor); if (isNew) { _monitor.ReleaseTransaction(transaction); } } }; }