/** * mongoc_buffer_append_from_stream: * @buffer; A mongoc_buffer_t. * @stream: The stream to read from. * @size: The number of bytes to read. * @timeout_msec: The number of milliseconds to wait or -1 for the default * @error: A location for a bson_error_t, or NULL. * * Reads from stream @size bytes and stores them in @buffer. This can be used * in conjunction with reading RPCs from a stream. You read from the stream * into this buffer and then scatter the buffer into the RPC. * * Returns: true if successful; otherwise false and @error is set. */ bool _mongoc_buffer_append_from_stream (mongoc_buffer_t *buffer, mongoc_stream_t *stream, size_t size, int32_t timeout_msec, bson_error_t *error) { uint8_t *buf; ssize_t ret; ENTRY; BSON_ASSERT (buffer); BSON_ASSERT (stream); BSON_ASSERT (size); BSON_ASSERT (buffer->datalen); BSON_ASSERT ((buffer->datalen + size) < INT_MAX); if (!SPACE_FOR (buffer, size)) { if (buffer->len) { memmove (&buffer->data[0], &buffer->data[buffer->off], buffer->len); } buffer->off = 0; if (!SPACE_FOR (buffer, size)) { buffer->datalen = bson_next_power_of_two (size + buffer->len + buffer->off); buffer->data = (uint8_t *) buffer->realloc_func ( buffer->data, buffer->datalen, NULL); } } buf = &buffer->data[buffer->off + buffer->len]; BSON_ASSERT ((buffer->off + buffer->len + size) <= buffer->datalen); ret = mongoc_stream_read (stream, buf, size, size, timeout_msec); if (ret != size) { bson_set_error (error, MONGOC_ERROR_STREAM, MONGOC_ERROR_STREAM_SOCKET, "Failed to read %" PRIu64 " bytes: socket error or timeout", (uint64_t) size); RETURN (false); } buffer->len += ret; RETURN (true); }
char *myrealloc(char *ptr, ssize_t len) { MBLOCK *real_ptr; ssize_t old_len; #ifndef NO_SHARED_EMPTY_STRINGS if (ptr == empty_string) return (mymalloc(len)); #endif /* * Note: for safety reasons the request length is a signed type. This * allows us to catch integer overflow problems that weren't already * caught up-stream. */ if (len < 1) msg_panic("myrealloc: requested length %ld", (long) len); #ifdef MYMALLOC_FUZZ len += MYMALLOC_FUZZ; #endif CHECK_IN_PTR(ptr, real_ptr, old_len, "myrealloc"); if ((real_ptr = (MBLOCK *) realloc((char *) real_ptr, SPACE_FOR(len))) == 0) msg_fatal("myrealloc: insufficient memory for %ld bytes: %m", (long) len); CHECK_OUT_PTR(ptr, real_ptr, len); if (len > old_len) memset(ptr + old_len, FILLER, len - old_len); return (ptr); }
/** * mongoc_buffer_append_from_stream: * @buffer; A mongoc_buffer_t. * @stream: The stream to read from. * @size: The number of bytes to read. * @timeout_msec: The number of milliseconds to wait or -1 for the default * @error: A location for a bson_error_t, or NULL. * * Reads from stream @size bytes and stores them in @buffer. This can be used * in conjunction with reading RPCs from a stream. You read from the stream * into this buffer and then scatter the buffer into the RPC. * * Returns: true if successful; otherwise false and @error is set. */ bool _mongoc_buffer_append_from_stream (mongoc_buffer_t *buffer, mongoc_stream_t *stream, size_t size, int32_t timeout_msec, bson_error_t *error) { uint8_t *buf; ssize_t ret; ENTRY; bson_return_val_if_fail (buffer, false); bson_return_val_if_fail (stream, false); bson_return_val_if_fail (size, false); BSON_ASSERT (buffer->datalen); if (!SPACE_FOR (buffer, size)) { if (buffer->len) { memmove(&buffer->data[0], &buffer->data[buffer->off], buffer->len); } buffer->off = 0; if (!SPACE_FOR (buffer, size)) { buffer->datalen = bson_next_power_of_two ((uint32_t)size); buffer->data = buffer->realloc_func (buffer->data, buffer->datalen, NULL); } } buf = &buffer->data[buffer->off + buffer->len]; ret = mongoc_stream_read (stream, buf, size, size, timeout_msec); if (ret != size) { bson_set_error (error, MONGOC_ERROR_STREAM, MONGOC_ERROR_STREAM_SOCKET, "Failed to read %u bytes from socket.", (unsigned)size); RETURN (false); } buffer->len += ret; RETURN (true); }
/** * mongoc_buffer_try_append_from_stream: * @buffer; A mongoc_buffer_t. * @stream: The stream to read from. * @size: The number of bytes to read. * @timeout_msec: The number of milliseconds to wait or -1 for the default * @error: A location for a bson_error_t, or NULL. * * Reads from stream @size bytes and stores them in @buffer. This can be used * in conjunction with reading RPCs from a stream. You read from the stream * into this buffer and then scatter the buffer into the RPC. * * Returns: bytes read if successful; otherwise -1 and @error is set. */ ssize_t _mongoc_buffer_try_append_from_stream (mongoc_buffer_t *buffer, mongoc_stream_t *stream, size_t size, int32_t timeout_msec, bson_error_t *error) { uint8_t *buf; ssize_t ret; ENTRY; BSON_ASSERT (buffer); BSON_ASSERT (stream); BSON_ASSERT (size); BSON_ASSERT (buffer->datalen); BSON_ASSERT ((buffer->datalen + size) < INT_MAX); if (!SPACE_FOR (buffer, size)) { if (buffer->len) { memmove (&buffer->data[0], &buffer->data[buffer->off], buffer->len); } buffer->off = 0; if (!SPACE_FOR (buffer, size)) { buffer->datalen = bson_next_power_of_two (size + buffer->len + buffer->off); buffer->data = (uint8_t *) buffer->realloc_func ( buffer->data, buffer->datalen, NULL); } } buf = &buffer->data[buffer->off + buffer->len]; BSON_ASSERT ((buffer->off + buffer->len + size) <= buffer->datalen); ret = mongoc_stream_read (stream, buf, size, 0, timeout_msec); if (ret > 0) { buffer->len += ret; } RETURN (ret); }
void *acl_default_realloc(const char *filename, int line, void *ptr, size_t len) { const char *myname = "acl_default_realloc"; MBLOCK *real_ptr; size_t old_len, new_len; const char *pname = NULL; if (filename && *filename) SET_FILE(pname, filename); else pname = __FILENAME_UNKNOWN; #ifndef NO_SHARED_EMPTY_STRINGS if (ptr == empty_string) return acl_default_malloc(pname, line, len); #endif if (len < 1) { acl_msg_warn("%s(%d)->%s: realloc: requested length %ld", pname, line, myname, (long) len); len = 128; } if (ptr == NULL) return acl_default_malloc(pname, line, len); CHECK_IN_PTR(ptr, real_ptr, old_len, pname, line); new_len = SPACE_FOR(len); if (new_len <= 0) acl_msg_fatal("%s(%d): new_len(%d) <= 0", myname, __LINE__, (int) new_len); else if (new_len >= __malloc_limit) { acl_msg_warn("%s(%d): new_len(%d) too large", myname, __LINE__, (int) new_len); } #ifdef _USE_GLIB if ((real_ptr = (MBLOCK *) g_realloc((char *) real_ptr, new_len)) == 0) acl_msg_fatal("%s(%d)->%s: realloc: insufficient memory: %s", pname, line, myname, strerror(errno)); #else if ((real_ptr = (MBLOCK *) realloc((char *) real_ptr, new_len)) == 0) acl_msg_fatal("%s(%d)->%s: realloc: insufficient memory: %s", pname, line, myname, strerror(errno)); #endif CHECK_OUT_PTR(ptr, real_ptr, len); #if 0 if (len > old_len) memset((char *) ptr + old_len, FILLER, len - old_len); #endif return ptr; }
void *acl_default_malloc(const char *filename, int line, size_t len) { const char *myname = "acl_default_malloc"; size_t new_len; char *ptr; MBLOCK *real_ptr; const char *pname = NULL; #if 0 printf("%s:%d, len: %d\r\n", filename, line, (int) len); acl_trace_info(); #endif if (filename && *filename) SET_FILE(pname, filename); else pname = __FILENAME_UNKNOWN; if (len < 1) { acl_msg_warn("%s(%d), %s: malloc: length %ld invalid", pname, line, myname, (long) len); len = 128; } new_len = SPACE_FOR(len); if (new_len <= 0) acl_msg_fatal("%s(%d): new_len(%d) <= 0", myname, __LINE__, (int) new_len); else if (new_len >= __malloc_limit) { acl_msg_warn("%s(%d): new_len(%d) too large", myname, __LINE__, (int) new_len); } #ifdef _USE_GLIB if ((real_ptr = (MBLOCK *) g_malloc(new_len)) == 0) { acl_msg_error("%s(%d)->%s: new_len: %d, g_malloc error(%s)", pname, line, myname, (int) new_len, strerror(errno)); return 0; } #else if ((real_ptr = (MBLOCK *) malloc(new_len)) == 0) { acl_msg_error("%s(%d)->%s: malloc: insufficient memory: %s, " "new_len: %d", pname, line, myname, strerror(errno), (int) new_len); return 0; } #endif CHECK_OUT_PTR(ptr, real_ptr, len); #if 0 memset(ptr, FILLER, len); #endif return ptr; }
void myfree(char *ptr) { MBLOCK *real_ptr; ssize_t len; #ifndef NO_SHARED_EMPTY_STRINGS if (ptr != empty_string) { #endif CHECK_IN_PTR(ptr, real_ptr, len, "myfree"); memset((char *) real_ptr, FILLER, SPACE_FOR(len)); free((char *) real_ptr); #ifndef NO_SHARED_EMPTY_STRINGS } #endif }
void acl_default_memstat(const char *filename, int line, void *ptr, size_t *len, size_t *real_len) { MBLOCK *real_ptr; const char *pname = NULL; size_t old_len; if (filename && *filename) SET_FILE(pname, filename); else pname = __FILENAME_UNKNOWN; CHECK_PTR(ptr, real_ptr, old_len, pname, line); if (len) *len = real_ptr->length; if (real_len) *real_len = SPACE_FOR(*len); }
void *acl_default_malloc(const char *filename, int line, size_t len) { const char *myname = "acl_default_malloc"; size_t new_len; char *ptr; MBLOCK *real_ptr; const char *pname = NULL; if (filename && *filename) SET_FILE(pname, filename); else pname = __FILENAME_UNKNOWN; if (len < 1) acl_msg_fatal("%s(%d)->%s: malloc: requested length %ld invalid", pname, line, myname, (long) len); new_len = SPACE_FOR(len); if (new_len <= 0) acl_msg_fatal("%s(%d): new_len(%d) <= 0", myname, __LINE__, (int) new_len); else if (new_len >= 100000000) acl_msg_warn("%s(%d): new_len(%d) too large", myname, __LINE__, (int) new_len); #ifdef _USE_GLIB if ((real_ptr = (MBLOCK *) g_malloc(new_len)) == 0) { acl_msg_error("%s(%d)->%s: g_malloc error(%s)", pname, line, myname, strerror(errno)); return (0); } #else if ((real_ptr = (MBLOCK *) malloc(new_len)) == 0) { acl_msg_error("%s(%d)->%s: malloc: insufficient memory: %s", pname, line, myname, strerror(errno)); return (0); } #endif CHECK_OUT_PTR(ptr, real_ptr, len); #if 0 memset(ptr, FILLER, len); #endif return (ptr); }
char *mymalloc(ssize_t len) { char *ptr; MBLOCK *real_ptr; /* * Note: for safety reasons the request length is a signed type. This * allows us to catch integer overflow problems that weren't already * caught up-stream. */ if (len < 1) msg_panic("mymalloc: requested length %ld", (long) len); #ifdef MYMALLOC_FUZZ len += MYMALLOC_FUZZ; #endif if ((real_ptr = (MBLOCK *) malloc(SPACE_FOR(len))) == 0) msg_fatal("mymalloc: insufficient memory for %ld bytes: %m", (long) len); CHECK_OUT_PTR(ptr, real_ptr, len); memset(ptr, FILLER, len); return (ptr); }
/** * _mongoc_buffer_fill: * @buffer: A mongoc_buffer_t. * @stream: A stream to read from. * @min_bytes: The minumum number of bytes to read. * @error: A location for a bson_error_t or NULL. * * Attempts to fill the entire buffer, or at least @min_bytes. * * Returns: The number of buffered bytes, or -1 on failure. */ ssize_t _mongoc_buffer_fill (mongoc_buffer_t *buffer, mongoc_stream_t *stream, size_t min_bytes, int32_t timeout_msec, bson_error_t *error) { ssize_t ret; size_t avail_bytes; ENTRY; bson_return_val_if_fail(buffer, false); bson_return_val_if_fail(stream, false); bson_return_val_if_fail(min_bytes >= 0, false); BSON_ASSERT (buffer->data); BSON_ASSERT (buffer->datalen); if (min_bytes <= buffer->len) { RETURN (buffer->len); } min_bytes -= buffer->len; if (buffer->len) { memmove (&buffer->data[0], &buffer->data[buffer->off], buffer->len); } buffer->off = 0; if (!SPACE_FOR (buffer, min_bytes)) { buffer->datalen = bson_next_power_of_two (buffer->len + min_bytes); buffer->data = buffer->realloc_func (buffer->data, buffer->datalen, buffer->realloc_data); } avail_bytes = buffer->datalen - buffer->len; ret = mongoc_stream_read (stream, &buffer->data[buffer->off + buffer->len], avail_bytes, min_bytes, timeout_msec); if (ret == -1) { bson_set_error (error, MONGOC_ERROR_STREAM, MONGOC_ERROR_STREAM_SOCKET, "Failed to buffer %u bytes within %d milliseconds.", (unsigned)min_bytes, (int)timeout_msec); RETURN (-1); } buffer->len += ret; if (buffer->len < min_bytes) { bson_set_error (error, MONGOC_ERROR_STREAM, MONGOC_ERROR_STREAM_SOCKET, "Could only buffer %u of %u bytes in %d milliseconds.", (unsigned)buffer->len, (unsigned)min_bytes, (int)timeout_msec); RETURN (-1); } RETURN (buffer->len); }
static void tls_mem_free(const char *filename, int line, void *ptr) { MBLOCK *real_ptr; size_t len; CHECK_IN_PTR2(ptr, real_ptr, len, filename, line); #if 1 if (real_ptr->mem_slice->tid != (unsigned long) acl_pthread_self()) { #else if (real_ptr->mem_slice->tid != mem_slice->tid) { #endif MUTEX_LOCK(real_ptr->mem_slice); PRIVATE_ARRAY_PUSH(real_ptr->mem_slice->list, real_ptr); MUTEX_UNLOCK(real_ptr->mem_slice); } else acl_slice_pool_free(filename, line, real_ptr); } static void *tls_mem_alloc(const char *filename, int line, size_t len) { const char *myname = "tls_mem_alloc"; ACL_MEM_SLICE *mem_slice = acl_pthread_getspecific(__mem_slice_key); char *ptr; MBLOCK *real_ptr; if (mem_slice == NULL) { /* 每个子线程获得自己的线程局部存储内存池 */ mem_slice = mem_slice_create(); mem_slice->slice_list = __mem_slice_list; /* 将子线程的线程局部存储内存池置入全局内存池句柄集合中 */ if (__mem_slice_list_lock) thread_mutex_lock(__mem_slice_list_lock); private_array_push(__mem_slice_list, mem_slice); if (__mem_slice_list_lock) thread_mutex_unlock(__mem_slice_list_lock); } real_ptr = (MBLOCK *) acl_slice_pool_alloc(filename, line, mem_slice->slice_pool, SPACE_FOR(len)); if (real_ptr == 0) { acl_msg_error("%s(%d): malloc: insufficient memory", myname, __LINE__); return 0; } mem_slice->nalloc++; if (mem_slice->nalloc == mem_slice->nalloc_gc) { mem_slice->nalloc = 0; mem_slice_gc(mem_slice); } CHECK_OUT_PTR(ptr, real_ptr, mem_slice, len); return ptr; } static void *tls_mem_calloc(const char *filename, int line, size_t nmemb, size_t size) { void *ptr = tls_mem_alloc(filename, line, nmemb * size); memset(ptr, 0, nmemb * size); return ptr; }