Free() public method

Frees an unused buffer. This may be added to the cache.
public Free ( byte data ) : void
data byte The memory to free.
return void
コード例 #1
0
        /// <summary>
        /// Update the tableid and position the tableid on the record that was modified.
        /// This can be useful when inserting a record because by default the tableid
        /// remains in its old location.
        /// </summary>
        /// <remarks>
        /// Save is the final step in performing an insert or an update. The update is begun by
        /// calling creating an Update object and then by calling JetSetColumn or JetSetColumns one or more times
        /// to set the record state. Finally, Update is called to complete the update operation.
        /// Indexes are updated only by Update or and not during JetSetColumn or JetSetColumns
        /// </remarks>
        public void SaveAndGotoBookmark()
        {
            var bookmark = bookmarkCache.Allocate();
            int actualBookmarkSize;

            this.Save(bookmark, bookmark.Length, out actualBookmarkSize);
            Api.JetGotoBookmark(this.sesid, this.tableid, bookmark, actualBookmarkSize);
            bookmarkCache.Free(bookmark);
        }
コード例 #2
0
ファイル: ColumnValue.cs プロジェクト: stgwilli/ravendb
        /// <summary>
        /// Recursive RetrieveColumns method for data pinning. This should pin a buffer and
        /// call the inherited RetrieveColumns method.
        /// </summary>
        /// <param name="sesid">The session to use.</param>
        /// <param name="tableid">
        /// The table to retrieve the columns from.
        /// </param>
        /// <param name="columnValues">
        /// Column values to retrieve.
        /// </param>
        /// <returns>An error code.</returns>
        internal static int RetrieveColumns(JET_SESID sesid, JET_TABLEID tableid, ColumnValue[] columnValues)
        {
            if (columnValues.Length > 1024)
            {
                throw new ArgumentOutOfRangeException("columnValues", columnValues.Length, "Too many column values");
            }

            int err;

            unsafe
            {
                NATIVE_RETRIEVECOLUMN *nativeRetrievecolumns = stackalloc NATIVE_RETRIEVECOLUMN[columnValues.Length];
                byte[] buffer = memoryCache.Allocate();
                fixed(byte *pinnedBuffer = buffer)
                {
                    byte *currentBuffer            = pinnedBuffer;
                    int   numVariableLengthColumns = columnValues.Length;

                    // First the fixed-size columns
                    for (int i = 0; i < columnValues.Length; ++i)
                    {
                        if (0 != columnValues[i].Size)
                        {
                            columnValues[i].MakeNativeRetrieveColumn(ref nativeRetrievecolumns[i]);
                            nativeRetrievecolumns[i].pvData = new IntPtr(currentBuffer);
                            nativeRetrievecolumns[i].cbData = checked ((uint)columnValues[i].Size);

                            currentBuffer += nativeRetrievecolumns[i].cbData;
                            Debug.Assert(currentBuffer <= pinnedBuffer + buffer.Length, "Moved past end of pinned buffer");

                            numVariableLengthColumns--;
                        }
                    }

                    // Now the variable-length columns
                    if (numVariableLengthColumns > 0)
                    {
                        int bufferUsed      = checked ((int)(currentBuffer - pinnedBuffer));
                        int bufferRemaining = checked (buffer.Length - bufferUsed);
                        int bufferPerColumn = bufferRemaining / numVariableLengthColumns;
                        Debug.Assert(bufferPerColumn > 0, "Not enough buffer left to retrieve variable length columns");

                        // Now the variable-size columns
                        for (int i = 0; i < columnValues.Length; ++i)
                        {
                            if (0 == columnValues[i].Size)
                            {
                                columnValues[i].MakeNativeRetrieveColumn(ref nativeRetrievecolumns[i]);
                                nativeRetrievecolumns[i].pvData = new IntPtr(currentBuffer);
                                nativeRetrievecolumns[i].cbData = checked ((uint)bufferPerColumn);
                                currentBuffer += nativeRetrievecolumns[i].cbData;
                                Debug.Assert(currentBuffer <= pinnedBuffer + buffer.Length, "Moved past end of pinned buffer");
                            }
                        }
                    }

                    // Retrieve the columns
                    err = Api.Impl.JetRetrieveColumns(sesid, tableid, nativeRetrievecolumns, columnValues.Length);

                    // Propagate the errors.
                    for (int i = 0; i < columnValues.Length; ++i)
                    {
                        columnValues[i].Error = (JET_err)nativeRetrievecolumns[i].err;
                    }

                    // Now parse out the columns that were retrieved successfully
                    for (int i = 0; i < columnValues.Length; ++i)
                    {
                        if (nativeRetrievecolumns[i].err >= (int)JET_err.Success &&
                            nativeRetrievecolumns[i].err != (int)JET_wrn.BufferTruncated)
                        {
                            byte *columnBuffer = (byte *)nativeRetrievecolumns[i].pvData;
                            int   startIndex   = checked ((int)(columnBuffer - pinnedBuffer));
                            columnValues[i].GetValueFromBytes(
                                buffer,
                                startIndex,
                                checked ((int)nativeRetrievecolumns[i].cbActual),
                                nativeRetrievecolumns[i].err);
                        }
                    }
                }

                memoryCache.Free(buffer);

                // Finally retrieve the buffers where the columns weren't large enough.
                RetrieveTruncatedBuffers(sesid, tableid, columnValues, nativeRetrievecolumns);
            }

            return(err);
        }
コード例 #3
0
        /// <summary>
        /// Retrieves a string column value from the current record. The record is that
        /// record associated with the index entry at the current position of the cursor.
        /// </summary>
        /// <param name="sesid">The session to use.</param>
        /// <param name="tableid">The cursor to retrieve the column from.</param>
        /// <param name="columnid">The columnid to retrieve.</param>
        /// <param name="encoding">The string encoding to use when converting data.</param>
        /// <param name="grbit">Retrieval options.</param>
        /// <returns>The data retrieved from the column as a string. Null if the column is null.</returns>
        public static string RetrieveColumnAsString(
            JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, Encoding encoding, RetrieveColumnGrbit grbit)
        {
            JET_wrn wrn;

            // This is an optimization for retrieving small Unicode strings
            // We use a stack-allocated buffer to retrieve the data and then create
            // a string from the data
            if (Encoding.Unicode == encoding)
            {
                unsafe
                {
                    // 512 bytes give 256 Unicode characters.
                    const int BufferSize = 512;
                    char *    buffer     = stackalloc char[BufferSize];
                    int       actualDataSize;
                    wrn = JetRetrieveColumn(
                        sesid, tableid, columnid, new IntPtr(buffer), BufferSize, out actualDataSize, grbit, null);
                    if (JET_wrn.ColumnNull == wrn)
                    {
                        return(null);
                    }

                    if (JET_wrn.Success == wrn)
                    {
                        return(new string(buffer, 0, actualDataSize / sizeof(char)));
                    }

                    Debug.Assert(JET_wrn.BufferTruncated == wrn, "Unexpected warning code");

                    // Fallthrough to normal case below
                }
            }

            // Retrieving a string happens in two stages: first the data is retrieved into a data
            // buffer and then the buffer is converted to a string. The buffer isn't needed for
            // very long so we try to use a cached buffer.
            byte[] cachedBuffer = memoryCache.Allocate();
            byte[] data         = cachedBuffer;

            int dataSize;

            wrn = JetRetrieveColumn(sesid, tableid, columnid, data, data.Length, out dataSize, grbit, null);
            if (JET_wrn.ColumnNull == wrn)
            {
                return(null);
            }

            if (JET_wrn.BufferTruncated == wrn)
            {
                Debug.Assert(dataSize > data.Length, "Expected column to be bigger than buffer");
                data = new byte[dataSize];
                wrn  = JetRetrieveColumn(sesid, tableid, columnid, data, data.Length, out dataSize, grbit, null);
                if (JET_wrn.BufferTruncated == wrn)
                {
                    string error = String.Format(
                        CultureInfo.CurrentCulture,
                        "Column size changed from {0} to {1}. The record was probably updated by another thread.",
                        data.Length,
                        dataSize);
                    Trace.TraceError(error);
                    throw new InvalidOperationException(error);
                }
            }

            // TODO: for Unicode strings pin the buffer and use the String(char*) constructor.
            string s = encoding.GetString(data, 0, dataSize);

            // Now we have extracted the string from the buffer we can free (cache) the buffer.
            memoryCache.Free(cachedBuffer);

            return(s);
        }