public RC SorterWrite(Context ctx, VdbeCursor cursor, Mem mem) { VdbeSorter sorter = cursor.Sorter; Debug.Assert(sorter != null); sorter.InMemory += ConvertEx.GetVarintLength(mem.N) + mem.N; SorterRecord newRecord = (SorterRecord)C._tagalloc(ctx, mem.N + sizeof(SorterRecord)); // New list element RC rc = RC.OK; if (newRecord == null) { rc = RC.NOMEM; } else { newRecord.P = newRecord[1]; C._memcpy(newRecord.P, mem.Z, mem.N); newRecord.N = mem.N; newRecord.Next = sorter.Record; sorter.Record = newRecord; } // See if the contents of the sorter should now be written out. They are written out when either of the following are true: // * The total memory allocated for the in-memory list is greater than (page-size * cache-size), or // * The total memory allocated for the in-memory list is greater than (page-size * 10) and sqlite3HeapNearlyFull() returns true. if (rc == RC.OK && sorter.MaxPmaSize > 0 && ((sorter.InMemory > sorter.MaxPmaSize) || (sorter.InMemory > sorter.MaxPmaSize && C._heapnearlyfull()))) { #if DEBUG long expect = sorter.WriteOffset + ConvertEx.GetVarintLength(sorter.InMemory) + sorter.InMemory; #endif rc = VdbeSorterListToPMA(ctx, cursor); sorter.InMemory = 0; Debug.Assert(rc != RC.OK || expect == sorter.WriteOffset); } return(rc); }
static RC VdbeSorterSort(VdbeCursor cursor) { SorterRecord slots = new SorterRecord[64]; if (slots == null) { return(RC.NOMEM); } VdbeSorter sorter = cursor.Sorter; SorterRecord p = sorter.Record; int i; while (p != null) { SorterRecord next = p.Next; p.Next = null; for (i = 0; slots[i] != null; i++) { VdbeSorterMerge(cursor, p, slots[i], ref p); slots[i] = null; } slots[i] = p; p = next; } p = null; for (i = 0; i < 64; i++) { VdbeSorterMerge(cursor, p, slots[i], ref p); } sorter.Record = p; C._free(ref slots); return(RC.OK); }
static void VdbeSorterMerge(VdbeCursor cursor, SorterRecord p1, SorterRecord p2, ref SorterRecord out_) { SorterRecord result = null; SorterRecord pp = result; object p2P = (p2 != null ? p2.P : null); while (p1 != null && p2 != null) { int r; VdbeSorterCompare(cursor, false, p1.P, p1.N, p2P, p2.N, ref r); if (r <= 0) { pp = p1; pp = p1.Next; p1 = p1.Next; p2P = null; } else { pp = p2; pp = p2.Next; p2 = p2.Next; if (p2 != null) { break; } p2P = p2.P; } } pp = (p1 != null ? p1 : p2); out_ = result; }
static void VdbeSorterRecordFree(Context ctx, SorterRecord record) { SorterRecord next; for (SorterRecord p = record; p != null; p = next) { next = p.Next; C._tagfree(ctx, ref p); } }
static RC VdbeSorterListToPMA(Context ctx, VdbeCursor cursor) { VdbeSorter sorter = cursor.Sorter; FileWriter writer; writer._memset(); if (sorter.InMemory == 0) { Debug.Assert(sorter.Record == null); return(RC.OK); } RC rc = VdbeSorterSort(cursor); // If the first temporary PMA file has not been opened, open it now. if (rc == RC.OK && sorter.Temp1 == null) { rc = VdbeSorterOpenTempFile(ctx, ref sorter.Temp1); Debug.Assert(rc != RC.OK || sorter.Temp1 != null); Debug.Assert(sorter.WriteOffset == 0); Debug.Assert(sorter.PMAs == 0); } if (rc == RC.OK) { FileWriterInit(ctx, sorter.Temp1, writer, sorter.WriteOffset); sorter.PMAs++; FileWriterWriteVarint(writer, sorter.InMemory); SorterRecord p; SorterRecord next = null; for (p = sorter.Record; p; p = next) { next = p.Next; FileWriterWriteVarint(writer, p.N); FileWriterWrite(writer, (byte[])p.P, p.N); C._tagfree(ctx, ref p); } sorter.Record = p; rc = FileWriterFinish(ctx, writer, sorter.WriteOffset); } return(rc); }
public RC SorterNext(Context ctx, VdbeCursor cursor, ref bool eof) { VdbeSorter sorter = cursor.Sorter; if (sorter.Trees) { int prevI = sorter.Trees[1]; // Index of iterator to advance RC rc = VdbeSorterIterNext(ctx, sorter.Iters[prevI]); for (int i = (sorter.Trees.length + prevI) / 2; rc == RC.OK && i > 0; i /= 2) // Index of aTree[] to recalculate { rc = VdbeSorterDoCompare(cursor, i); } eof = (sorter.Iters[sorter.Trees[1]].File == null); return(rc); } SorterRecord free = sorter.Record; sorter.Record = free.Next; free.Next = nullptr; VdbeSorterRecordFree(ctx, free); eof = (sorter.Record == null); return(RC.OK); }
static RC VdbeSorterSort(VdbeCursor cursor) { SorterRecord slots = new SorterRecord[64]; if (slots == null) return RC.NOMEM; VdbeSorter sorter = cursor.Sorter; SorterRecord p = sorter.Record; int i; while (p != null) { SorterRecord next = p.Next; p.Next = null; for (i = 0; slots[i] != null; i++) { VdbeSorterMerge(cursor, p, slots[i], ref p); slots[i] = null; } slots[i] = p; p = next; } p = null; for (i = 0; i < 64; i++) VdbeSorterMerge(cursor, p, slots[i], ref p); sorter.Record = p; C._free(ref slots); return RC.OK; }
static void VdbeSorterMerge(VdbeCursor cursor, SorterRecord p1, SorterRecord p2, ref SorterRecord out_) { SorterRecord result = null; SorterRecord pp = result; object p2P = (p2 != null ? p2.P : null); while (p1 != null && p2 != null) { int r; VdbeSorterCompare(cursor, false, p1.P, p1.N, p2P, p2.N, ref r); if (r <= 0) { pp = p1; pp = p1.Next; p1 = p1.Next; p2P = null; } else { pp = p2; pp = p2.Next; p2 = p2.Next; if (p2 != null) break; p2P = p2.P; } } pp = (p1 != null ? p1 : p2); out_ = result; }