Commit Graph

791 Commits

Author SHA1 Message Date
Nadav Har'El
9b63b02328 doc: fix small mixup in reference (pipe.hh)
Signed-off-by: Nadav Har'El <nyh@cloudius-systems.com>
2015-07-07 12:57:09 +03:00
Avi Kivity
af30fe11df doc: more info in fiber module reference table 2015-07-07 00:38:53 +03:00
Avi Kivity
1501b273f6 doc: add reference section to fiber module 2015-07-07 00:29:23 +03:00
Avi Kivity
89931d53fa semaphore: document 2015-07-07 00:10:51 +03:00
Avi Kivity
5338a6a8db Merge branch 'master' of github.com:cloudius-systems/seastar 2015-07-06 11:12:36 +03:00
Amnon Heiman
2c08647a6e scollectd: change get_collectd_value() to use const ref
After the implementation of the code that uses the scollectd API was
modified, the get_collectd_value gets the collectd ID as a const
reference, to remove unnessary creation of shared_ptr.

Signed-off-by: Amnon Heiman <amnon@cloudius-systems.com>
2015-07-06 11:09:32 +03:00
Raphael S. Carvalho
f6fdde0ff6 core: make gate_closed_exception::what a public member
gate_closed_exception::what() is currently a private member, thus
calling the method when handling the exception isn't possible.

Signed-off-by: Raphael S. Carvalho <raphaelsc@cloudius-systems.com>
2015-07-06 10:25:21 +03:00
Glauber Costa
a4a23f8eb0 gate: introduce with_gate idiom
Execute a function making sure it is wrapped in a gate.

This can afford to be considerably simpler than do_with, since we are not
playing any games with object creation, and the gate itself can be assumed to
be relatively long lived.

Among other things, this will allow us to make changes to enter / leave without
breaking existing code, and experiment with stronger ways of doing leave - as
Avi suggested recently.

Signed-off-by: Glauber Costa <glommer@cloudius-systems.com>
2015-07-05 19:07:08 +03:00
Gleb Natapov
7d33cf62a5 Add is_smart_ptr metafunction to detect know smart pointers objects 2015-07-02 16:46:23 +03:00
Avi Kivity
033e46c7b0 sharded: speed up compilation
- unify three invoke_on() variants by using futurize<>
 - move type calculation out of method signature
2015-07-02 15:33:35 +03:00
Avi Kivity
00da6d85c3 future: optimize for compile time
.then()'s return type is a complex template, which needs to be mangled into
the function's name.  Move the return type into a defaulted template type
parameter, so that the entire type expression is eliminated, being replaced
by the result type.

Saves about 1% compile time and 3% object size on futures_test.o.
2015-07-02 12:47:07 +03:00
Glauber Costa
641034075b sprint: use sstring as a parameter to sprint
We can use sstring as an argument to sprint. In some cases, we already have the
string in a variable and end up being forced to call c_str() from the caller
site. Accepting sstring as a parameter makes for a cleaner interface.

Signed-off-by: Glauber Costa <glommer@cloudius-systems.com>
2015-06-30 19:11:18 +03:00
Nadav Har'El
770e6b7816 future: add handle_exception() method
This patch adds a "class future" method for handling an exception result
of the future. It is impossible to discard a future's exception while passing
through the value of the result (what will we pass in the case of
exception?), so we discard the result as well.

An example of how this can be used, to log an error (but otherwise do
nothing) if removing a file fails:

  remove_file(filename).handle_exception(
    [] (std::exception_ptr eptr) {
      print("Exception when deleting file: %s", eptr);
    });

Signed-off-by: Nadav Har'El <nyh@cloudius-systems.com>
2015-06-30 14:57:53 +03:00
Avi Kivity
7842ac8db6 doc: document file I/O 2015-06-28 22:42:06 +03:00
Avi Kivity
ae38e95bb2 file: uninline posix_file_impl destructor 2015-06-28 20:42:30 +03:00
Avi Kivity
8039544806 file: warn if file::close() was not called in time 2015-06-28 20:39:06 +03:00
Avi Kivity
c05c7c09cf fstream: close file on stream close 2015-06-28 20:36:23 +03:00
Avi Kivity
9c9d943e3a file: add close() method
Closing a file can both expose latent errors that did not have the
opportunity to be reported earlier, and also may block.  While both
are unlikely in the case of O_DIRECT files, better not to risk it.
2015-06-28 20:36:15 +03:00
Nadav Har'El
f687ec40a3 fstream: catch bug early
the file_data_sink_impl::put() code assumes it is always called on buffers
with size multiple of dma alignment (4096), except the *last* one. After
writing one unaligned-size buffer, further writes cannot continue because
the offset into the file no longer has the right alignment! If a caller
does try to do that, there is a bug in the caller (it's not a run-time error,
it's a design bug), and better discover it quickly with an assert, as I do
in this patch.

I had such a caller in an example application, and it took me a whole day
of debugging just to figure out that this is where the caller actually had
a bug.

Signed-off-by: Nadav Har'El <nyh@cloudius-systems.com>
Reviewed-by: Raphael S. Carvalho <raphaelsc@cloudius-systems.com>
2015-06-28 19:31:00 +03:00
Nadav Har'El
b306cee41e fstream: fix behavior of large writes to output stream
Our file-output code contains various layers making sometimes contradictory
assumptions, and it is a real art-form to make it all work together.
They usually do work together well, but there was one undetected bug for
large writes to a file output stream:

The problem is what happens when we try to write a large buffer (larger
than the output stream's buffer) in one output_stream::write() call.
By default, output_stream uses the efficient, zero-copy, implementation
which calls the underlying data sink's put function on the entire written
buffer, without copying it to the stream's buffer first.

Unfortunately, this solution does NOT work on *file* output streams.
Because of our use of AIO and O_DIRECT, we can only write from aligned
buffers, and at aligned (multiple of dma_alignment) sizes. Even a large
size cannot be fully written if not a multiple of dma_alignment, and
the need to align the buffers, and data already on the output_stream,
complicate things further.

Amazingly, we already had an option "_trim_to_size" in output_stream to
do the right thing, and we just need to enable it for file output stream.
In special cases (aligned position, aligned input buffer) it might be
possible to do something even more efficient - zero copy and just one
write request - but in the general case, _trim_to_size is exactly what
we needed.

Signed-off-by: Nadav Har'El <nyh@cloudius-systems.com>
2015-06-28 19:29:19 +03:00
Avi Kivity
6ac01770df core: avoid fstat() call in reactor thread
When creating a file object, we call fstat() to determine whether it's
a block device or a regular file.  While unlikely, the fstat() call can
block.  Use an ioctl() that we expect to fail on regular files instead.
2015-06-28 17:14:43 +03:00
Nadav Har'El
20d2154c4d shared_ptr: add use_count()
Add a use_count() method for shared_ptr, like std::shared_ptr has.

We already had such a method for lw_shared_ptr, but not for shared_ptr.

Signed-off-by: Nadav Har'El <nyh@cloudius-systems.com>
2015-06-28 15:14:56 +03:00
Raphael S. Carvalho
f5ce89b203 core: introduce function to rename file
Signed-off-by: Raphael S. Carvalho <raphaelsc@cloudius-systems.com>
2015-06-28 10:06:06 +03:00
Nadav Har'El
a349f373b4 pipe: avoid needless use of exceptions
When closing the read-end side of the pipe, we need to notify the writer
only if it was blocked in write() on a full pipe - because if it wasn't
blocked, it will get the broken pipe on the next write() attempt.

We used queue::abort() for that, which is fine, because this function
won't do anything if nobody is waiting on a full buffer. But we still
call std::make_exception_ptr() unconditionally, which is slow (involves
throwing an exception and catching it) and an annoying false-alarm when
trying to debug with gdb's "catch throw" (which stops on any throw).

So this patch does

       if (_buf.full()) {
            _buf.abort(std::make_exception_ptr(broken_pipe_exception()));
       }

So that in the typical case when the buffer was not full (hopefully it
is empty), we don't do anything.

Signed-off-by: Nadav Har'El <nyh@cloudius-systems.com>
2015-06-25 17:03:52 +03:00
Tomasz Grabiec
14a8110d1f future: Avoid copying of the result in get0()
Even though we accept std::tuple<T...>&&, 'x' is an l-value reference
inside get0().
2015-06-23 14:28:01 +03:00
Avi Kivity
ab7be2890f core: rename distributed<Service> to seastar::sharded<Service>
distributed<> has the connotation of being distributed across the network.
Sharded is more in line with seastar terms.

Keep the distributed<> name and header file as an alias, for
compatibility.
2015-06-22 12:58:56 +03:00
Avi Kivity
b879fabf36 reactor: block SIGALRM while we're still not ready to handle it
If some code sets up a timer before we've set up the SIGALRM signal handler,
we die.  Block it in the meantime.
2015-06-22 12:48:50 +03:00
Tomasz Grabiec
e5e7348f76 core: Reimplement keep_doing() using repeat() 2015-06-22 09:08:38 +02:00
Tomasz Grabiec
61992f84c5 core: Introduce repeat()
It's like do_until(), but the stop condition is calculated by the
callback instead of being supplied separately.
2015-06-22 09:08:38 +02:00
Avi Kivity
bd3044a38d do_with: doc: mark cherry_pick_tuple as internal 2015-06-21 23:37:12 +03:00
Avi Kivity
9679075b30 shared_mutex: reinstate FIFO ordering
Noticed by Nadav.
2015-06-21 20:54:53 +03:00
Avi Kivity
18fd73b065 gate: fix doc typo 2015-06-21 20:36:15 +03:00
Avi Kivity
a2ec5ebe87 doc: add gate class to fiber module 2015-06-21 20:35:54 +03:00
Avi Kivity
ac94c1d68e doc: add fiber module to main page 2015-06-21 20:33:34 +03:00
Avi Kivity
d9bfbe55c8 core: introduce shared_mutex class
Similar to std::shared_mutex, allows shared and exclusive locking of a
resource (also known as a reader/writer lock).  This implementation is
strictly FIFO.
2015-06-21 20:28:43 +03:00
Avi Kivity
a99956db8e future-util: implement range-based map_reduce() variant 2015-06-21 20:21:24 +03:00
Avi Kivity
33a4f1b32b reactor: move destructor to .cc file
It's totally uninteresting to anyone else.
2015-06-21 18:02:28 +03:00
Avi Kivity
cebe81082b reactor: destroy system timer in destructor
Keeping the timer armed can cause a signal to be sent, which will not
be handled, terminating the program too early.
2015-06-21 17:59:18 +03:00
Avi Kivity
614da559d0 semaphore: provide broken() variant accepting an std::exception_ptr 2015-06-21 11:44:57 +03:00
Nadav Har'El
9b884b3435 reactor: more information on ignored exceptional future
When an exceptional future is ignored, we print a message, and for an
std::exception we print its what(). However, it would be useful to also
see the exception's type. We already had such exception type printing
code for engine_exit(), and this patch extracts that code into a separate
function, and also uses it to print the warning message when an exceptional
future is ignored.

For example, in one test before this patch I see:
 WARNING: exceptional future ignored: _Map_base::at

After this patch,
 WARNING: exceptional future ignored of type 'std::out_of_range': _Map_base::at

Signed-off-by: Nadav Har'El <nyh@cloudius-systems.com>
2015-06-20 11:07:09 +03:00
Nadav Har'El
13a68fa62c pipe: fix syntax error in pipe reader
I'm not sure how my compiler didn't complain earlier...

Signed-off-by: Nadav Har'El <nyh@cloudius-systems.com>
2015-06-20 11:07:06 +03:00
Avi Kivity
39218c32f7 core: extend do_with() to support multiple parameters
do_with(1, 2, 3, [] (int& v1, int& v2, int& v3) {
      return make_ready_future<int>(v1 + v2 + v3);
  });
2015-06-19 20:24:56 +03:00
Avi Kivity
6595ad0bde core: introduce gate class
Gate allows stopping new incoming requests, and detecting when the last
in-progress request has left.
2015-06-19 19:03:15 +03:00
Nadav Har'El
2f4e123eab core: pipe for passing data between fibers
Our queue<T> is a convenient mechanism for passing data between a producer
fiber (a set of consecutive continuations) and a consumer fiber.

However, queue<T> is difficult to use *correctly*. The biggest problem is
how to handle premature stopping: What if one of the two fibers (the reader
or the writer) stops prematurely, and will never read or write any more?
When queue<T> is used naively, the other fiber will just hang indefinitely
while it waits to read from the empty queue, or write to the full queue.

The solution proposed in this patch is a new pipe mechanism, implemented
internally over a queue. pipe<T>() returns two separate objects - a pipe
reader, and a pipe writer. Typically each object is std::move()ed into a
different fiber. When a fiber stops and its captured variables are destroyed,
one end of the pipe is destroyed, and that causes the other end's operations
to return immediately (if the other end was already blocked, it will resume
immediately, and return an exceptions). This behavior is analogous to
Unix's EOF or broken-pipe behavior.

Signed-off-by: Nadav Har'El <nyh@cloudius-systems.com>
2015-06-19 19:03:13 +03:00
Gleb Natapov
f7f445d563 distributed: deallocate _instance array during stop.
Otherwise tester may crash if _instances destructor is called when thread
responsible for the allocation (which tester spawned to run seastar in)
no longer running.
2015-06-18 14:43:38 +03:00
Gleb Natapov
3c4dcd871a add default and move constructor/assignment to server_socket 2015-06-18 14:43:16 +03:00
Glauber Costa
92803a2db3 touch_directory: EEXIST-ignoring make directory
There are many situations in which we would like to make sure a directory
exists.  We can do that by creating the directory we want, and just ignoring
the relevant error.

It is a lot of code though, and I believe it is an idiom common enough to exist
on its own.

Signed-off-by: Glauber Costa <glommer@cloudius-systems.com>
Reviewed-by: Nadav Har'El <nyh@cloudius-systems.com>
2015-06-18 12:51:49 +03:00
Raphael S. Carvalho
534401c91f fstream: use dma_alignment constant instead of a hardcoded value
Signed-off-by: Raphael S. Carvalho <raphaelsc@cloudius-systems.com>
2015-06-18 12:49:33 +03:00
Raphael S. Carvalho
02bdf380c4 fstream: abort instead of silently returning a ready future
Signed-off-by: Raphael S. Carvalho <raphaelsc@cloudius-systems.com>
2015-06-18 12:49:33 +03:00
Gleb Natapov
a2c1ab66b7 semaphore: fix access to freed memory in wait(timeout)
wait() with timeout takes reference to an entry, but when
circular_buffer is resized it may be moved, so freed instance will be
accessed on timeout. Fix it by using std::list instead.
2015-06-18 12:35:25 +03:00