Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mariadb
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
8e59978b
Commit
8e59978b
authored
Sep 28, 2010
by
Sergey Petrunya
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move Lifo_buffer to separate file.
parent
4f56acb6
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
412 additions
and
0 deletions
+412
-0
sql/sql_lifo_buffer.h
sql/sql_lifo_buffer.h
+412
-0
No files found.
sql/sql_lifo_buffer.h
0 → 100644
View file @
8e59978b
/**
@defgroup Bi-directional LIFO buffers used by DS-MRR implementation
@{
*/
class
Forward_lifo_buffer
;
class
Backward_lifo_buffer
;
/*
A base class for in-memory buffer used by DS-MRR implementation. Common
properties:
- The buffer is last-in-first-out, i.e. elements that are written last are
read first.
- The buffer contains fixed-size elements. The elements are either atomic
byte sequences or pairs of them.
- The buffer resides in the memory provided by the user. It is possible to
= dynamically (ie. between write operations) add ajacent memory space to
the buffer
= dynamically remove unused space from the buffer.
The intent of this is to allow to have two buffers on adjacent memory
space, one is being read from (and so its space shrinks), while the other
is being written to (and so it needs more and more space).
There are two concrete classes, Forward_lifo_buffer and Backward_lifo_buffer.
*/
class
Lifo_buffer
{
protected:
/**
Pointers to data to be written. write() call will assume that
(*write_ptr1) points to size1 bytes of data to be written.
If write_ptr2 != NULL then the buffer stores pairs, and (*write_ptr2)
points to size2 bytes of data that form the second component.
*/
uchar
**
write_ptr1
;
size_t
size1
;
uchar
**
write_ptr2
;
size_t
size2
;
/**
read() will do reading by storing pointer to read data into *read_ptr1 (if
the buffer stores atomic elements), or into {*read_ptr1, *read_ptr2} (if
the buffer stores pairs).
*/
uchar
**
read_ptr1
;
uchar
**
read_ptr2
;
uchar
*
start
;
/**< points to start of buffer space */
uchar
*
end
;
/**< points to just beyond the end of buffer space */
public:
enum
enum_direction
{
BACKWARD
=-
1
,
/**< buffer is filled/read from bigger to smaller memory addresses */
FORWARD
=
1
/**< buffer is filled/read from smaller to bigger memory addresses */
};
virtual
enum_direction
type
()
=
0
;
/* Buffer space control functions */
/** Let the buffer store data in the given space. */
void
set_buffer_space
(
uchar
*
start_arg
,
uchar
*
end_arg
)
{
start
=
start_arg
;
end
=
end_arg
;
TRASH
(
start
,
end
-
start
);
reset
();
}
/**
Specify where write() should get the source data from, as well as source
data size.
*/
void
setup_writing
(
uchar
**
data1
,
size_t
len1
,
uchar
**
data2
,
size_t
len2
)
{
write_ptr1
=
data1
;
size1
=
len1
;
write_ptr2
=
data2
;
size2
=
len2
;
}
/**
Specify where read() should store pointers to read data, as well as read
data size. The sizes must match those passed to setup_writing().
*/
void
setup_reading
(
uchar
**
data1
,
size_t
len1
,
uchar
**
data2
,
size_t
len2
)
{
read_ptr1
=
data1
;
DBUG_ASSERT
(
len1
==
size1
);
read_ptr2
=
data2
;
DBUG_ASSERT
(
len2
==
size2
);
}
bool
can_write
()
{
return
have_space_for
(
size1
+
(
write_ptr2
?
size2
:
0
));
}
virtual
void
write
()
=
0
;
bool
is_empty
()
{
return
used_size
()
==
0
;
}
virtual
bool
read
()
=
0
;
void
sort
(
qsort2_cmp
cmp_func
,
void
*
cmp_func_arg
)
{
uint
elem_size
=
size1
+
(
write_ptr2
?
size2
:
0
);
uint
n_elements
=
used_size
()
/
elem_size
;
my_qsort2
(
used_area
(),
n_elements
,
elem_size
,
cmp_func
,
cmp_func_arg
);
}
virtual
void
reset
()
=
0
;
virtual
uchar
*
end_of_space
()
=
0
;
protected:
bool
have_data
(
size_t
bytes
)
{
return
(
used_size
()
>=
bytes
);
}
virtual
bool
have_space_for
(
size_t
bytes
)
=
0
;
virtual
size_t
used_size
()
=
0
;
public:
virtual
void
remove_unused_space
(
uchar
**
unused_start
,
uchar
**
unused_end
)
=
0
;
virtual
uchar
*
used_area
()
=
0
;
/** Iterator to walk over contents of the buffer without reading it. */
class
Iterator
{
public:
virtual
void
init
(
Lifo_buffer
*
buf
)
=
0
;
/*
Read the next value. The calling convention is the same as buf->read()
has.
@retval FALSE - ok
@retval TRUE - EOF, reached the end of the buffer
*/
virtual
bool
read_next
()
=
0
;
virtual
~
Iterator
()
{}
protected:
Lifo_buffer
*
buf
;
virtual
uchar
*
get_next
(
size_t
nbytes
)
=
0
;
};
virtual
~
Lifo_buffer
()
{};
friend
class
Forward_iterator
;
friend
class
Backward_iterator
;
};
/**
Forward LIFO buffer
The buffer that is being written to from start to end and read in the
reverse. 'pos' points to just beyond the end of used space.
It is possible to grow/shink the buffer at the end bound
used space unused space
*==============*-----------------*
^ ^ ^
| | +--- end
| +---- pos
+--- start
*/
class
Forward_lifo_buffer
:
public
Lifo_buffer
{
uchar
*
pos
;
public:
enum_direction
type
()
{
return
FORWARD
;
}
size_t
used_size
()
{
return
pos
-
start
;
}
void
reset
()
{
pos
=
start
;
}
uchar
*
end_of_space
()
{
return
pos
;
}
bool
have_space_for
(
size_t
bytes
)
{
return
(
pos
+
bytes
<
end
);
}
void
write
()
{
write_bytes
(
*
write_ptr1
,
size1
);
if
(
write_ptr2
)
write_bytes
(
*
write_ptr2
,
size2
);
}
void
write_bytes
(
const
uchar
*
data
,
size_t
bytes
)
{
DBUG_ASSERT
(
have_space_for
(
bytes
));
memcpy
(
pos
,
data
,
bytes
);
pos
+=
bytes
;
}
uchar
*
read_bytes
(
size_t
bytes
)
{
DBUG_ASSERT
(
have_data
(
bytes
));
pos
=
pos
-
bytes
;
return
pos
;
}
bool
read
()
{
if
(
!
have_data
(
size1
+
(
read_ptr2
?
size2
:
0
)))
return
TRUE
;
if
(
read_ptr2
)
*
read_ptr2
=
read_bytes
(
size2
);
*
read_ptr1
=
read_bytes
(
size1
);
return
FALSE
;
}
void
remove_unused_space
(
uchar
**
unused_start
,
uchar
**
unused_end
)
{
DBUG_ASSERT
(
0
);
/* Don't need this yet */
}
/**
Add more space to the buffer. The caller is responsible that the space
being added is adjacent to the end of the buffer.
@param unused_start Start of space
@param unused_end End of space
*/
void
grow
(
uchar
*
unused_start
,
uchar
*
unused_end
)
{
DBUG_ASSERT
(
unused_end
>=
unused_start
);
DBUG_ASSERT
(
end
==
unused_start
);
TRASH
(
unused_start
,
unused_end
-
unused_start
);
end
=
unused_end
;
}
/* Return pointer to start of the memory area that is occupied by the data */
uchar
*
used_area
()
{
return
start
;
}
friend
class
Forward_iterator
;
};
/**
Iterator for Forward_lifo_buffer
*/
class
Forward_iterator
:
public
Lifo_buffer
::
Iterator
{
uchar
*
pos
;
/** Return pointer to next chunk of nbytes bytes and avance over it */
uchar
*
get_next
(
size_t
nbytes
)
{
if
(
pos
-
nbytes
<
((
Forward_lifo_buffer
*
)
buf
)
->
start
)
return
NULL
;
pos
-=
nbytes
;
return
pos
;
}
public:
bool
read_next
()
{
uchar
*
res
;
if
(
buf
->
read_ptr2
)
{
if
((
res
=
get_next
(
buf
->
size2
)))
{
*
(
buf
->
read_ptr2
)
=
res
;
*
buf
->
read_ptr1
=
get_next
(
buf
->
size1
);
return
FALSE
;
}
}
else
{
if
((
res
=
get_next
(
buf
->
size1
)))
{
*
(
buf
->
read_ptr1
)
=
res
;
return
FALSE
;
}
}
return
TRUE
;
/* EOF */
}
void
init
(
Lifo_buffer
*
buf_arg
)
{
DBUG_ASSERT
(
buf_arg
->
type
()
==
Lifo_buffer
::
FORWARD
);
buf
=
buf_arg
;
pos
=
((
Forward_lifo_buffer
*
)
buf
)
->
pos
;
}
};
/**
Backward LIFO buffer
The buffer that is being written to from start to end and read in the
reverse. 'pos' points to the start of used space.
It is possible to grow/shink the buffer at the start.
unused space used space
*--------------*=================*
^ ^ ^
| | +--- end
| +---- pos
+--- start
*/
class
Backward_lifo_buffer
:
public
Lifo_buffer
{
uchar
*
pos
;
public:
enum_direction
type
()
{
return
BACKWARD
;
}
size_t
used_size
()
{
return
end
-
pos
;
}
void
reset
()
{
pos
=
end
;
}
uchar
*
end_of_space
()
{
return
end
;
}
bool
have_space_for
(
size_t
bytes
)
{
return
(
pos
-
bytes
>=
start
);
}
void
write
()
{
if
(
write_ptr2
)
write_bytes
(
*
write_ptr2
,
size2
);
write_bytes
(
*
write_ptr1
,
size1
);
}
void
write_bytes
(
const
uchar
*
data
,
size_t
bytes
)
{
DBUG_ASSERT
(
have_space_for
(
bytes
));
pos
-=
bytes
;
memcpy
(
pos
,
data
,
bytes
);
}
bool
read
()
{
if
(
!
have_data
(
size1
+
(
read_ptr2
?
size2
:
0
)))
return
TRUE
;
*
read_ptr1
=
read_bytes
(
size1
);
if
(
read_ptr2
)
*
read_ptr2
=
read_bytes
(
size2
);
return
FALSE
;
}
uchar
*
read_bytes
(
size_t
bytes
)
{
DBUG_ASSERT
(
have_data
(
bytes
));
uchar
*
ret
=
pos
;
pos
=
pos
+
bytes
;
return
ret
;
}
/**
Stop using/return the unused part of the space
@param unused_start OUT Start of the unused space
@param unused_end OUT End of the unused space
*/
void
remove_unused_space
(
uchar
**
unused_start
,
uchar
**
unused_end
)
{
*
unused_start
=
start
;
*
unused_end
=
pos
;
start
=
pos
;
}
void
grow
(
uchar
*
unused_start
,
uchar
*
unused_end
)
{
DBUG_ASSERT
(
0
);
/* Not used for backward buffers */
}
/* Return pointer to start of the memory area that is occupied by the data */
uchar
*
used_area
()
{
return
pos
;
}
friend
class
Backward_iterator
;
};
/**
Iterator for Backward_lifo_buffer
*/
class
Backward_iterator
:
public
Lifo_buffer
::
Iterator
{
uchar
*
pos
;
/* Return pointer to next chunk of nbytes bytes and advance over it */
uchar
*
get_next
(
size_t
nbytes
)
{
if
(
pos
+
nbytes
>
((
Backward_lifo_buffer
*
)
buf
)
->
end
)
return
NULL
;
uchar
*
res
=
pos
;
pos
+=
nbytes
;
return
res
;
}
public:
bool
read_next
()
{
/*
Always read the first component first (if the buffer is backwards, we
have written the second component first).
*/
uchar
*
res
;
if
((
res
=
get_next
(
buf
->
size1
)))
{
*
(
buf
->
read_ptr1
)
=
res
;
if
(
buf
->
read_ptr2
)
*
buf
->
read_ptr2
=
get_next
(
buf
->
size2
);
return
FALSE
;
}
return
TRUE
;
/* EOF */
}
void
init
(
Lifo_buffer
*
buf_arg
)
{
DBUG_ASSERT
(
buf_arg
->
type
()
==
Lifo_buffer
::
BACKWARD
);
buf
=
buf_arg
;
pos
=
((
Backward_lifo_buffer
*
)
buf
)
->
pos
;
}
};
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment