Allocate() public method

Allocates a chunk of memory. If memory is cached it is returned. If no memory is cached then it is allocated. Check the size of the returned buffer to determine how much memory was allocated.
public Allocate ( ) : byte[]
return byte[]
コード例 #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);
        }