text:
For those of you who are new to the series, you may want to check out Part 1 and Part 2 before reading this post. It will help give you some context as well as introduce you to some of the jargon and technology that I'm using. If you've already read then, or don't want to, then please read on!
This post builds on the previous two, but not without a few little modifications. If you're interested in following along step by step with your own version of the code running, then get yourself a copy of this changeset before doing so.
In this post we're going to cover:
- A slight refactor of code structure to support the "standard" approach to building applications in Erlang using OTP.
- Building a small set of modules to talk to Riak.
- Creation of some JSON helper functions for reading and writing data.
- Calling all the way from the Webmachine front-end to Riak to extract data and display it in a browser using ErlyDTL templates.
There are quite a few code snippets in this post as well as output from script executions and
bash sessions. To avoid confusion, all file listings reference the path to the file that is being modified relative to the root of the project folder.
Be warned, this is a long post :) Get yourself a shmoke und a pancake, a glass of your favourite beverage and put some relaxing music on (instrumental is best).
Are you ready? OK, here we go ...
A Slight Refactor
I was ready to embark on this third post a while back but then I sat back and thought about how I might structure things if I were using another set of technologies. Usually I would put another layer between the web tier and the back-end database cluster as opposed to having the web tier talk to the database directly. It didn't make sense to me that this approach would be any different in Erlang.
I had a chat to two blokes that I really respect to get their views, and then I fired off a question to the Basho guys (via the #riak IRC channel). The Basho lads even made the effort to respond to me via the Riak Recap as they weren't available at the time to answer me via IRC (thanks again Mark). All three of them confirmed my thoughts. Here's what appeared in the recap which captures the question and response nicely:
Q --- I have a Webmachine application which will be talking to Riak. I was going to put application and controller logic in that application and I am wondering if [I] should instead be creating a "core" OTP application with the business style logic in it and have the Webmachine app talk to that app which, in turn, talks to Riak? Is that the general approach that is taken [in Erlang applications]? (from TheColonial via #riak)
A --- We recommend going with the latter approach. You're better off to create a core app that talks to Webmachine and Riak separately.
Perfect, that makes total sense. Therefore the following describes what I did to modify the code base that I had in order to support this set up. Any failure in implementation, structure or understanding is totally my own and in no way reflects on the abilities and advice of those mentioned above who took the time to offer assistance.
Moving on. What we want to end up with is three applications:
|Talks to
|Bomb-proof data storage and replication.
|An OTP application that provides an API to a set of logic that deals with the transformation of data from a client through to the database. It should keep the clients ignorant of the data storage medium. It should provide business logic that would be required for any client application to be able to talk to a `csd`/Riak back-end.
|Provide a nice, web-based interface for the user to experience the goal of the Code Smackdown application.
Given that we're going to be using this structure, the "root" folder should actually be fairly clean without any source. Instead, each
csd-related application should live in its own sub-folder under an
apps folder and the root should just contain the means to build it and start it. In essence what we'd like to see in the root folder is something like this:
oj@spawn-link ~/blog/csd $ ls -F
apps/ dev.haproxy.conf Makefile proxy.sh* rebar* rebar.config start.sh*
With that in mind, let's start the surgery.
Moving csd to csd_web
There are two ways to approach this problem. The first is to do a find and replace, making sure you cover off file names as well as module names, etc. The second is to simply recreate the web site from scratch, copy over any missing files and make any other adjustments manually that may be required.
I preferred the second approach, so that's what I did. First I recreated the web application, which is now called
csd_web in the
apps folder:
oj@spawn-link ~/blog/csd $ mkdir apps && cd apps
oj@spawn-link ~/blog/csd/apps $ ~/blog/webmachine/scripts/new_webmachine.sh csd_web .
==> priv (create)
Writing /home/oj/blog/csd/apps/csd_web/README
Writing /home/oj/blog/csd/apps/csd_web/Makefile
Writing /home/oj/blog/csd/apps/csd_web/rebar.config
Writing /home/oj/blog/csd/apps/csd_web/rebar
Writing /home/oj/blog/csd/apps/csd_web/start.sh
Writing /home/oj/blog/csd/apps/csd_web/ebin/csd_web.app
Writing /home/oj/blog/csd/apps/csd_web/src/csd_web.erl
Writing /home/oj/blog/csd/apps/csd_web/src/csd_web_app.erl
Writing /home/oj/blog/csd/apps/csd_web/src/csd_web_sup.erl
Writing /home/oj/blog/csd/apps/csd_web/src/csd_web_resource.erl
Writing /home/oj/blog/csd/apps/csd_web/priv/dispatch.conf
oj@spawn-link ~/blog/csd/apps $ ls -F
Next I removed a few files which weren't going to be needed any more. I then copied over
rebar.config, the ErlyDTL templates and the
csd.app.src file (which we need to modify):
oj@spawn-link ~/blog/csd/apps $ cd csd_web
oj@spawn-link ~/blog/csd/apps/csd_web $ rm README rebar start.sh
oj@spawn-link ~/blog/csd/apps/csd_web $ cp ../../rebar.config .
oj@spawn-link ~/blog/csd/apps/csd_web $ cp -R ../../templates .
oj@spawn-link ~/blog/csd/apps/csd_web $ cp ../../src/csd.app.src ./src/csd_web.app.src
I then edited the
csd_web.app.src file so that the names were updated (I tidied it up a little and added a version number too):
%%-*- mode: erlang -*-
{application, csd_web,
{description, "The Webmachine component of the Code Smackdown application."},
{vsn, "0.0.1"},
{modules, []},
{registered, []},
{mod, {csd_web_app, []}},
{env, []}
I then opened up
csd_web_resource.erl and made it look like the original
csd_resource.erl so that it called the ErlyDTL template:
-export([init/1, to_html/2]).
init([]) ->
{ok, undefined}.
to_html(ReqData, State) ->
{ok, Content} = sample_dtl:render([{param, "Slartibartfast"}]),
{Content, ReqData, State}.
-- rebar.config --
csd_web is now ready to go. To build it, we need to go back up to the root
csd folder and adjust the
rebar.config so that it knows to look in the
apps sub-folder (thanks to Andrew for pointing this out). We can also remove all the dependencies because that will be taken care of by
%%-*- mode: erlang -*-
{sub_dirs, ["apps/csd_web"]}.
Next, I removed all the other left-over stuff in the root folder that wasn't required any more (including the startup script):
oj@spawn-link ~/blog/csd $ rm -rf README priv src templates start.sh
I then modify the
Makefile so that it does a couple of other things:
- Includes a target which builds just the current applications without building the dependencies (this will make builds much quicker most of the time).
- Includes a target which can start the web application, essentially replacing the original startup script. This target will be dependent on the previous target so that it is always up to date when running the application.
- Includes targets which can start/stop
ERL ?= erl
APP = csd
.PHONY: deps
all: deps
@./rebar compile
@./rebar compile skip_deps=true
@./rebar get-deps
@./rebar clean
distclean: clean
@./rebar delete-deps
webstart: app
exec erl -pa $(PWD)/apps/\*/ebin -pa $(PWD)/deps/\*/ebin -boot start_sasl -s reloader -s csd_web
@haproxy -f dev.haproxy.conf
All that is left to do is start
haproxy and launch the application (make sure
Riak is running first). These commands need to be done in two different terminal windows. First, start the proxy (note the use of
sudo so that we can listen on port 80):
oj@spawn-link ~/blog/csd $ sudo make proxystart
[2] 1935
Available polling systems :
sepoll : pref=400, test result OK
epoll : pref=300, test result OK
poll : pref=200, test result OK
select : pref=150, test result OK
Total: 4 (4 usable), will use sepoll.
Using sepoll() as the polling mechanism.
Then make and start the web application. We have to do a full
make first time around so that all the dependencies are resolved:
oj@spawn-link ~/blog/csd $ make && make webstart
... snip ...
=PROGRESS REPORT==== 4-Apr-2011::21:04:18 ===
application: csd_web
started_at: nonode@nohost
Now we should be able to hit localhost and see the ErlyDTL template rendered in all its awesome, black-and-white glory:
Refactor complete. Now let's start work on our new OTP application which will be responsible for talking to Riak.
If you need a break, now is the time to take it! Go freshen up, take a leak and refill your glass.
Ready to go again? Here we go ...
Creating the csd_core OTP Application
Creation of an OTP-compliant application is another job for Rebar as it comes with a set of templates built-in. Unfortunately those template aren't 100% and hence don't do everything we need to do out of the box. But we shall use them as a starting point:
oj@spawn-link ~/blog/csd $ mkdir apps/csd_core && cd apps/csd_core
oj@spawn-link ~/blog/csd/apps/csd_core $ ../../rebar create-app appid=csd_core
==> csd_core (create-app)
Writing src/csd_core.app.src
Writing src/csd_core_app.erl
Writing src/csd_core_sup.erl
We have a very simple application shell set up, but we need to do a bit more work to get it ready. First, let's create our base
csd_core.erl module which is used to fire up our application. For this we will use
csd_web.erl (the one which is part of our Webmachine application) as a template. Note that I've shuffled things around and removed some things that are not relevant:
%% @author OJ Reeves <firstname.lastname@example.com>
%% @copyright 2011 OJ Reeves
%% @doc csd_core startup code
-author('OJ Reeves <firstname.lastname@example.com>').
-export([start/0, start_link/0, stop/0]).
ensure_started(App) ->
case application:start(App) of
ok ->
{error, {already_started, App}} ->
%% @spec start_link() -> {ok,Pid::pid()}
%% @doc Starts the app for inclusion in a supervisor tree
start_link() ->
%% @spec start() -> ok
%% @doc Start the csd_core server.
start() ->
%% @spec stop() -> ok
%% @doc Stop the csd_core server.
stop() ->
Res = application:stop(csd_core),
Next up, edit
csd_core.app.src and add some application-specific information:
{application, csd_core,
{description, "Core functionality for the Code Smackdown application."},
{vsn, "0.0.1"},
{registered, []},
{mod, {csd_core_app, []}},
{env, []}
We know that we'll be talking to Riak, so we need to make sure we've included the
riakc (Riak client) dependency. Though I haven't yet talked about it, we'll also be using Mochiweb's mochijson2 module to help with handling JSON data, so we shall add this as a dependency to the application. Bear in mind this is already a dependency for the web component of the application, so we're not actually adding a new dependency to the overall application.
We can do this by creating a
rebar.config in
apps/csd_core and editing it to contain the following:
%%-*- mode: erlang -*-
{mochiweb, "1.5.1", {git, "git://github.com/mochi/mochiweb", {tag, "1.5.1"}}},
{riakc, ".*", {git, "git://github.com/basho/riak-erlang-client", "HEAD"}}
Then we need to tell
rebar to build this new application by adjusting the
rebar.config in the
csd root folder:
%%-*- mode: erlang -*-
{sub_dirs, ["apps/csd_core", "apps/csd_web"]}.
Now we have enough to get the
csd_core application started, even though it doesn't do anything. We just need to adjust our
Makefile target so that it launches the
csd_core application as well:
ERL ?= erl
APP = csd
.PHONY: deps
all: deps
@./rebar compile
@./rebar compile skip_deps=true
@./rebar get-deps
@./rebar clean
distclean: clean
@./rebar delete-deps
webstart: app
exec erl -pa $(PWD)/apps/\*/ebin -pa $(PWD)/deps/\*/ebin -boot start_sasl -s reloader -s csd_core -s csd_web
@haproxy -f dev.haproxy.conf
Then off we go:
oj@spawn-link ~/blog/csd $ make webstart
==> csd_core (compile)
Compiled src/csd_core_app.erl
Compiled src/csd_core_sup.erl
Compiled src/csd_core.erl
... snip ...
=PROGRESS REPORT==== 4-Apr-2011::21:49:27 ===
application: csd_core
started_at: nonode@nohost
... snip ...
=PROGRESS REPORT==== 4-Apr-2011::21:49:27 ===
application: csd_web
started_at: nonode@nohost
As you can see we now have a system which contains both
csd_core and
csd_web. This is great, but
csd_core needs a lot more work. The intent for this application is to be an OTP application which provides an API to the
csd logic and back-end database. This means we're going to need to get ourselves a gen_server set up which can handle requests from various clients. Let's do that next.
rebar comes with a simple template that we can use for creating the
gen_server behaviour, so we can invoke that from the command line and have it generate the shell for us:
oj@spawn-link ~/blog/csd/apps/csd_core $ ../../rebar create template=simplesrv srvid=csd_core_server
==> csd_core (create)
Writing src/csd_core_server.erl
We now have a very dumb server ready to go, to make it start with the rest of the application we have to modify
csd_core_sup, the supervisor and tell it to fire up the server for us:
%% Supervisor callbacks
%% Helper macro for declaring children of supervisor
-define(CHILD(I, Type), {I, {I, start_link, []}, permanent, 5000, Type, [I]}).
%% ===================================================================
%% API functions
%% ===================================================================
start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
%% ===================================================================
%% Supervisor callbacks
%% ===================================================================
init([]) ->
Server = ?CHILD(csd_core_server, worker),
Processes = [Server],
{ok, { {one_for_one, 5, 10}, Processes} }.
With this in place we can now start our application again and we should see the new `csd_core_server` appear in the start-up sequence:
oj@spawn-link ~/blog/csd $ make webstart
... snip ...
=PROGRESS REPORT==== 4-Apr-2011::22:04:04 ===
supervisor: {local,csd_core_sup}
started: [{pid,<0.54.0>},
=PROGRESS REPORT==== 4-Apr-2011::22:04:04 ===
application: csd_core
started_at: nonode@nohost
... snip ...
The shell and structure of our application is now in place. We are finally ready to start talking to Riak!
Again, now is the time to have a mini-break if you need one. Grab a Shigar und a waffle and a cup of English Breakfast tea.
Preparing csd_core for Riak connectivity
Given that this is the first look at connecting to Riak, we're going to have to set up a little infrastructure to support our needs. As a result, the data itself won't be discussed much for fear of turning this post into something way more epic than originally intended.
So in short, we're interested in storing the idea of a code snippet. That is an entity which contains two opposing blobs of code which are being compared. That snippet will have a title. Down the track, more information will be associated with this snippet, such as the author, along with links to a set of comments and votes. For now we'll just focus on storing the bare essentials of the snippet.
The Snippet
As far as our Erlang code is concerned, our snippet is going to be a simple list of properties that we can interact with via the proplists module. This keeps things really simple. To demonstrate what our snippet will look like in code, here is the function that takes a Title, and the two code blobs (called Left and Right) and returns a
snippet instance. This code goes in a module called
csd_snippet defined in
to_snippet(Title, Left, Right) ->
{title, Title},
{left, Left},
{right, Right}
Note that the first part of the tuple is the atom
snippet which I am using to identify the layout of the contents in the second part of the tuple. Down the track we'll have more collections of data in the system than just snippets, and we may want to make sure that the caller doesn't accidentally pass in a
user, for example, to a function expecting a
It is important at this point to note that, down the track, I will include a
key property in all of the data objects that are pushed to Riak. This property serves as the identifier for the object in Riak and is stored alongside the rest of the data so that it is easy to relate the in-memory instance back to the stored instance. This value, if not specified, will be inserted automatically when an item is saved via the API functions in
csd_core. More on this later.
Formatting Data for Storage in Riak
Riak is very flexible in that it will store whatever kind of information you give it. This is good because it means we can cater our data format to whatever needs we have.
In our case, the easiest option would be to store our Erlang terms as binary using [termtobinary][] as we wouldn't have to think about anything else. We could easily read the data using [binarytoterm][]. Done.
This comes with a set of problems though. For example, if we wanted to map/reduce using JavaScript we wouldn't find it easy to get the data into a format that we could use. Another example would be that the RESTful interface to Riak would be close to useless because any non-Erlang client would have to somehow get the data into a meaningful format to work with.
Instead of using binary and throwing Erlang terms straight into Riak, we're going to use JSON. It's very easy to convert to and from JSON in many different languages, and it's very easy to read. We can also easily verify that the data is being stored correctly by querying Riak's RESTful interface directly using cURL or a browser.
In order to store data in JSON format, we're going to enlist the help of mochijson2, a library that comes with Mochiweb that makes it a lot easier to deal with JSON than doing everything manually. Given that we're using Webmachine for the front-end (which itself relies on Mochiweb) we already have the dependency available.
Unfortunately we can't just throw our data straight at this module and have it do everything for us.
mochijson2 requires data to be in a certain format before it can encode it to JSON. When decoding from JSON, it converts the data into the same format. Hence, we need the ability to convert our own data format to and from this intermediate data format so that
mochijson2 can deal with it.
We need two functions:
to_json() and
from_json(), and we shall define these in a helper module called
csd_json. This module will live in
-export([from_json/1, from_json/2, to_json/1, to_json/2]).
to_json(PropList) ->
to_json(PropList, fun(_) -> true end).
to_json(PropList, IsStrFun) ->
list_to_binary(mochijson2:encode(from_proplist(PropList, IsStrFun))).
from_json(Json) ->
from_json(Json, fun(_) -> true end).
from_json(Json, IsStrFun) ->
to_proplist(mochijson2:decode(Json), IsStrFun).
You're probably wondering why each of these functions requires the
IsStrFun parameter (if you're not, you're obviously an experienced Erlanger!). For those who don't know, strings in Erlang are actually lists of integers. This is fantastic as it makes it easy to manipulate strings as if they were lists, but it comes at a small price: it's not possible to determine the difference between a list of integers and a string.
Why is this important?
mochijson2 needs strings to be encoded as binaries, so we need a way to differentiate between integer lists and real strings. My original implementations of both the
to_json() and
from_json() functions attempted to figure out if certain fields were strings or not by looking at the content of the list. Not only was the code messy, but it wasn't foolproof. Instead, I made the decision to force the user to provide a callback function which will tell the JSON serialiser if the given property is a string or not. This callback takes a single parameter which is the name (in atom form) of the property and returns a boolean --
true indicates that the value is a string,
false otherwise.
In some cases we might just be happy to encode/decode every single value as a string. Hence, there is an overload to both
to_json() and
from_json() which caters for this case. The rest of the code which implments the conversion is listed below. Don't feel that you need to understand the code below, as it's really not the goal of this post. The full source to this module is included in the source link specified at the end of this post.
from_proplist(List=[H|_], IsStrFun) when is_tuple(H) ->
{ struct, lists:map(fun(P) -> from_proplist(P, IsStrFun) end, List) };
from_proplist({PropName, ComplexProp=[H|_]}, IsStrFun) when is_tuple(H) ->
{ list_to_binary(atom_to_list(PropName)), from_proplist(ComplexProp, IsStrFun) };
from_proplist({PropName, PropVal}, IsStrFun) ->
{ list_to_binary(atom_to_list(PropName)), to_value(PropName, PropVal, IsStrFun) }.
to_proplist({struct, PropList}, IsStrFun) when is_list(PropList) ->
lists:map(fun(P) -> to_proplist(P, IsStrFun) end, PropList);
to_proplist({PropName, ComplexProp={struct, _}}, IsStrFun) ->
{ list_to_atom(binary_to_list(PropName)), to_proplist(ComplexProp, IsStrFun) };
to_proplist({PropName, PropVal}, IsStrFun) ->
PropAtom = list_to_atom(binary_to_list(PropName)),
{ PropAtom, from_value(PropAtom, PropVal, IsStrFun) }.
to_value(PropName, L=[H|_], IsStrFun) when is_list(L) and is_list(H) ->
lists:map(fun(P) -> to_value(PropName, P, IsStrFun) end, L);
to_value(PropName, L, IsStrFun) when is_list(L) ->
case IsStrFun(PropName) of
true -> list_to_binary(L);
_ -> lists:map(fun(V) -> to_value(PropName, V, IsStrFun) end, L)
to_value(_, V, _) ->
from_value(PropName, L, IsStrFun) when is_list(L) ->
lists:map(fun(P) -> from_value(PropName, P, IsStrFun) end, L);
from_value(PropName, B, IsStrFun) when is_binary(B) ->
case IsStrFun(PropName) of
true -> binary_to_list(B);
from_value(_, V, _) ->
We are now able to read and write data to and from JSON format. Now we need to use the Riak client to push that into our Riak cluster.
Setting up the Riak client
Basho have done a great job of creating a protocol buffer-based client for use with Riak. The interface is really simple to use. Despite that, we shall create a module which will deal with this for us. This gives us a single point of abstraction of Riak and a place where we can add extra support for our own needs without spreading Riak-specific code all over the source base.
The first problem we need to resolve is: what do we do with configuration?
This was a question I initially didn't know how to answer. After a bit of deliberation and a chat with a respected Erlang sifu (who has a fantastic Erlang tutorial site) I decided to go with a module-based option.
We have our Riak cluster hidden behind the
haproxy load balancer, and hence we have a single entry-point to connect to. If this entry-point changes, it changes for all of the clients, not just a single client. Therefore, I want the ability to manage a single set of connection information, but I want the ability to update it on the fly without having to restart the
csd_core application. This is Erlang, after all, and modifying code and configuration on-the-fly is extremely easy. We shall abuse that.
We create a single module,
csd_riak_config.erl, to contain our configuration which is referenced at start-up. It looks like this:
connection_info() ->
{ "127.0.0.1", 8080 }.
Pretty simple stuff. Let's use this functionality in our
gen_server, and carry the configuration through from initialisation to all of the calls that will be made to the Riak server. This requires two simple modifications to the
csd_core_server module:
start_link() ->
ConnInfo = csd_riak_config:connection_info(),
gen_server:start_link({local, ?SERVER}, ?MODULE, [ConnInfo], []).
% ...
init([ConnInfo]) ->
{ok, ConnInfo}.
Confiuration is now loaded and is being passed to all of our
gen_server callbacks. Let's make use of it.
csd_snippet is the entry point for all snippet-related information, and one of the things that we are going to want to be able to do is write a snippet to Riak. So let's create a code-path that can do that.
The first point of call for a client is the OTP interface. Let's create an API call and a call handler to support saving snippets in
%% This is a simple function which invokes a call via the gen_sever
%% behaviour.
save_snippet(Snippet) ->
gen_server:call(?SERVER, {save_snippet, Snippet}, infinity).
%% Handle the case where a caller wants to save a snippet to Riak. We
%% create a connection to Riak and pass that into the snippet handler
%% along with the snippet that needs to be saved. We return the newly
%% saved snippet.
handle_call({save_snippet, Snippet}, _From, ConnInfo) ->
RiakPid = csd_riak:connect(ConnInfo),
SavedSnippet = csd_snippet:save(RiakPid, Snippet),
{reply, SavedSnippet, ConnInfo};
Of course, we will need to export the
save_snippet() function if we want to be able to call it.
You'll notice that we're getting the connection information passed in as the state for the OTP call, and that we're using that to create a connection to Riak via the
csd_riak module. We shall cover this module in just a minute, but hopefully the interface to this function should make it relatively self-explanatory.
You might be wondering "Why are you creating the Riak client connection here instead of letting the
csd_snippet:save() function do it by itself. It's a good question. The reason I decided to create the connection as part of OTP call rather than in the data/helper modules is because down the track there will probably be a need to do multiple interactions with Riak in a single call. If we force each of the called modules, such as
csd_snippet, to establish their own connections then we'd probably have multiple connections to Riak being created during a single client request. This isn't what I would like to see happen, so it made sense (in my view) to create the client connection once and reuse it across all modules that are invoked during the request.
With that out of the way, we need to implement the
save() function in the
csd_snippet module. Brace yourself:
save(RiakPid, Snippet={snippet, SnippetData}) ->
case proplists:get_value(key, SnippetData, undefined) of
undefined ->
Key = csd_riak:new_key(),
NewSnippetData = [{key, Key} | SnippetData],
RiakObj = csd_riak:create(?BUCKET, Key, to_json_internal(NewSnippetData)),
ok = csd_riak:save(RiakPid, RiakObj),
{snippet, NewSnippetData};
ExistingKey ->
RiakObj = csd_riak:fetch(RiakPid, ?BUCKET, ExistingKey),
NewRiakObj = csd_riak:update(RiakObj, to_json_internal(SnippetData)),
ok = csd_riak:save(RiakPid, NewRiakObj),
On the surface this looks a little complicated, but it's actually very simple. As mentioned earlier in the post, we use a
key property to store the identifier of the object in Riak. This code supports this notion. It works as follows:
- Try to get the value of the
keyfrom the given list of properties.
- If not found ...
- create a new key using the
new_key()function in the
csd_riakmodule (this will be covered shortly).
- Add the
keyto the list of properties for the snippet.
- Create a new instance of a Riak object (more on this later) which contains the details of the snippet data to be written, along with the target bucket name and the key of the snippet.
- Save the Riak object to the Riak cluster using the specified Riak client connection (Pid), and for now assume that it succeeds.
- Return the new set of snippet data with the snippet's key included.
- create a new key using the
- If found ...
- Load the existing data from the Riak cluster into a Riak object.
- Update the Riak object with the new data values passed into the function.
- Save the Riak object back to the Riak cluster using the specified Riak client connection (Pid), and for now assume that it succeeds.
- Return the snippet back to the caller as is.
It's fairly basic functionality which does enough to cater for our needs at this point. Through this one function, we can write new snippet instances to Riak, and we can update them too.
You'll also notice that another function is being called that hasn't been discussed:
to_snippet_internal(). Rather than try to explain this, let's see the code as it's quite easy to follow:
%% exported functions
to_json({snippet, SnippetData}) ->
from_json(SnippetJson) ->
%% helper functions used internally.
to_json_internal(SnippetData) ->
csd_json:to_json(SnippetData, fun is_string/1).
from_json_internal(SnippetJson) ->
{snippet, csd_json:from_json(SnippetJson, fun is_string/1)}.
is_string(title) -> true;
is_string(left) -> true;
is_string(right) -> true;
is_string(_) -> false.
As you can see, these are helper functions which call the
csd_json functions to serialise/deserialise to/from JSON format. The
is_string() function is the one that is used to tell the JSON functionality which properties are strings and which are not. At the moment, all properties defined on the snippet are string properties. Bear in mind that the
key property, which is added automatically, is not a string.
All that is left is to see how
csd_riak deals with the underlying Riak connectivity. Prepare to be underwhelmed!
%% @spec connect(connection_info()) -> pid()
%% @doc Create a connection to the specified Riak cluster and
%% return the Pid associated with the new connection.
connect({IP, Port}) ->
{ok, RiakPid} = riakc_pb_socket:start_link(IP, Port),
%% @spec create(binary, binary, json) -> riakc_obj()
%% @doc Create a new instance of a riak object using the
%% parameters given. The riak object can then be
%% persisted to a Riak node/cluster. This overload
%% assumes that the data passed in is JSON and sets
%% the MIME type to "application/json" for you.
create(Bucket, Key, JsonData) ->
create(Bucket, Key, JsonData, "application/json").
%% @spec create(binary, binary, term(), string) -> riakc_obj()
%% @doc Create a new instance of a riak object using the
%% parameters given. The riak object can then be
%% persisted to a Riak node/cluster. This overload
%% takes arbitrary data and requires the user to
%% specify the mime type of the data that is being
%% stored.
create(Bucket, Key, Item, MimeType) ->
RiakObj = riakc_obj:new(Bucket, Key, Item, MimeType),
%% @spec fetch(pid(), binary, binary) -> riakc_obj()
%% @doc Fetches a riakc object from a Riak node/cluster
%% using the connection given.
fetch(RiakPid, Bucket, Key) ->
RiakObj = riakc_pb_socket:get(RiakPid, Bucket, Key),
%% @spec update(riakc_obj(), term()) -> riakc_obj()
%% @doc Updates the stored value for a riakc object with
%% the new one specified.
update(RiakObj, NewValue) ->
NewRiakObj = riakc_obj:update_value(RiakObj, NewValue),
%% @spec get_value(riakc_obj()) -> term()
%% @doc Retrieves the stored value from within the riakc
%% object.
get_value(RiakObj) ->
Value = riakc_obj:get_value(RiakObj),
%% @spec save(pid(), riakc_obj()) -> {ok, riakc_obj()} | {error | Reason}
%% @doc Saves the given riak object to the specified Riak node/cluster.
save(RiakPid, RiakObj) ->
Result = riakc_pb_socket:put(RiakPid, RiakObj),
%% @spec new_key() -> key()
%% @doc Generate an close-to-unique key that can be used to identify
%% an object in riak. This implementation is blatantly borrowed
%% (purloined) from the wriaki source (thanks basho!)
new_key() ->
{{Yr, Mo, Dy}, {Hr, Mn, Sc}} = erlang:universaltime(),
{_, _, Now} = now(),
new_key([Yr, Mo, Dy, Hr, Mn, Sc, node(), Now]).
%% @spec new_key(list()) -> key()
%% @doc Generate an close-to-unique key that can be used to identify
%% an object in riak using the given list parameter as the stuff
%% to hash.
new_key(List) ->
Hash = erlang:phash2(List),
Hopefully the code in this module is fairly self-explanatory. It's a very simple API to follow which made it very easy to build. So with this in place, let's fire up the application, create a new snippet and see if it lands in the Riak store:
oj@spawn-link ~/blog/csd $ make webstart
... snip ...
=PROGRESS REPORT==== 4-Apr-2011::22:54:55 ===
application: csd_web
started_at: nonode@nohost
1> Snippet = csd_snippet:to_snippet(
1> "Super composition!",
1> "(.^) = (.) . (.)",
1> "(.^) = fmap `fmap` fmap").
{snippet,[{title,"Super composition!"},
{left,"(.^) = (.) . (.)"},
{right,"(.^) = fmap `fmap` fmap"}]}
2> SavedSnippet = csd_core_server:save_snippet(Snippet).
PROGRESS REPORT==== 4-Apr-2011::22:57:13 ===
supervisor: {local,inet_gethost_native_sup}
started: [{pid,<0.103.0>},{mfa,{inet_gethost_native,init,[[]]}}]
=PROGRESS REPORT==== 4-Apr-2011::22:57:13 ===
supervisor: {local,kernel_safe_sup}
started: [{pid,<0.102.0>},
{title,"Super composition!"},
{left,"(.^) = (.) . (.)"},
{right,"(.^) = fmap `fmap` fmap"}]}
As you can see from the above script dump, a new
key was generated for us and stored alongside the snippet (it's highlighted in bold). Verifying that the data has persisted is simple. We can hit any of the Riak nodes via its web interface. Let's take a look at http://localhost:8091/riak/snippet/B41kUQ== (your URL will have a different key):
Great stuff! For more detail, let's see what cURL has to say:
oj@spawn-link ~/blog/csd/ $ curl http://localhost:8091/riak/snippet/B41kUQ== -v
* About to connect() to localhost port 8091 (#0)
* Trying ::1... Connection refused
* Trying 127.0.0.1... connected
* Connected to localhost (127.0.0.1) port 8091 (#0)
> GET /riak/snippet/B41kUQ== HTTP/1.1
> User-Agent: curl/7.21.0 (x86_64-pc-linux-gnu) libcurl/7.21.0 OpenSSL/0.9.8o zlib/184.108.40.206 libidn/1.18
> Host: localhost:8091
> Accept: */*
< X-Riak-Vclock: a85hYGBgzGDKBVIsjOy7jmcwJTLmsTJ8tuc7zpcFAA==
< Vary: Accept-Encoding
< Server: MochiWeb/1.1 WebMachine/1.7.3 (participate in the frantic)
< Link: </riak/snippet>; rel="up"
< Last-Modified: Mon, 04 Apr 2011 13:13:23 GMT
< ETag: "6fw7c5v4IPAsf4B5hMHybc"
< Date: Mon, 04 Apr 2011 13:13:36 GMT
< Content-Type: application/json
< Content-Length: 107
* Connection #0 to host localhost left intact
* Closing connection #0
{"key":"B41kUQ==","title":"Super composition!","left":"(.^) = (.) . (.)","right":"(.^) = fmap `fmap` fmap"}
As you can see, it has not only serialised to JSON properly, but the MIME type has been set correctly as well.
This is all well and good, but we need our code to be able to read from Riak as well. That's up next.Reading Data from Riak
We've already covered off what happens at the bottom level when reading data from Riak (see the above code snippet for more info). To enable this functionality at the top level, we simply need to create a
gen_server call, handle it appropriately and expose a function in the
csd_snippet module. Let's start at the top level:
%% OTP API function to get a snippet based on the key
get_snippet(SnippetKey) ->
gen_server:call(?SERVER, {get_snippet, SnippetKey}, infinity).
%% handle the call and call the functionality from csd_snippet
handle_call({get_snippet, SnippetKey}, _From, ConnInfo) ->
RiakPid = csd_riak:connect(ConnInfo),
Snippet = csd_snippet:fetch(RiakPid, SnippetKey),
{reply, Snippet, ConnInfo};
This code is a bit of a no-brainer. It's very similar to the writing code, but just a bit simpler. Let's see what the
csd_snippet:fetch() function looks like:
fetch(RiakPid, Key) ->
{ok, RiakObj} = csd_riak:fetch(RiakPid, ?BUCKET, Key),
SnippetJson = csd_riak:get_value(RiakObj),
This code just pulls a Riak object out of the back-end, extracts is value and deserialises it from JSON to our Erlang
proplist. Very simple stuff.
We should be able to build this and, via the Erlang console, verify that it functions:
3> Reloading csd_core_server ... ok.
3> csd_core_server:get_snippet(<<"B41kUQ==">>).
{title,"Super composition!"},
{left,"(.^) = (.) . (.)"},
{right,"(.^) = fmap `fmap` fmap"}]}
Works like a charm. Now, for the icing on the cake, let's get this rendering in a very simple template in our browser.
End to End
In order to gain access to our data in Riak from the web we need to create a new resource. This resource will respond to any URI of the form
/snippet/<key>. We shall call this resource
csd_web_snippet_resource and we'll be putting this in our web application. It looks like this:
%% @author OJ Reeves <firstname.lastname@example.com>
%% @copyright 2010 OJ Reeves
%% @doc Webmachine resource that handles snippet-related actions
-author('OJ Reeves <firstname.lastname@example.com>').
-export([init/1, to_html/2]).
init([]) -> {ok, undefined}.
to_html(ReqData, State) ->
PathInfo = wrq:path_info(ReqData),
{ok, SnippetKey} = dict:find(key, PathInfo),
{snippet, SnippetData} = csd_core_server:get_snippet(list_to_binary(SnippetKey)),
{ok, Content} = snippet_dtl:render(SnippetData),
{Content, ReqData, State}.
As you can see, this code calls through to the
csd_core_server to extract the data from the back-end. The value that is used as a key for the snippet is one that is pulled from the URI via Webmachine's
wrq:path_info() function. This function extracts values from the URI based on the rules in
dispatch.conf and provides a dict which can be used to lookup the values.
The code also uses a new ErlyDTL template called
snippet. We'd best add that to the
templates folder:
<h1>Snippet View</h1>
<h2>{{ title }}</h2>
<p>Left: {{ left }}</p>
<p>Right: {{ right }}</p>
Finally, we just need to adjust
dispatch.conf to include the new route handler so that our code gets called:
%%-*- mode: erlang -*-
{[], csd_web_resource, []}.
{["snippet", key], csd_web_snippet_resource, []}.
Note how
key is specified alongside
"snippet". This means that the path following
snippet/ in the URI will be associated with the
key atom in the
dict generated by
We're ready to rock. Rebuild, then hit the right URL, http://localhost/snippet/B41kUQ== (again, your key will be different), and you should get the following:
Wrapping up
Thanks for sticking with me! As you can see there is a little bit of ground-work required if you're interested in producing some form of structure that you can reuse all over your application, but the effort is definitely worth it. Now we have something in place which we can use to store arbitrarily complex
proplists into Riak in JSON format, we have the ability to talk to Riak (read and write), and we have a proper application structure in place which we can build on.
Please note that the mechanism implemented in this post is quite simple and doesn't cover all cases that will be required before the application is complete. In future posts, this implementation will change to support more of those cases, such as dealing with concurrent updates, handling versions, etc.
Many thanks to those people who took the time out of their busy schedules to review my post before I shared it with the world. Those people shall remain nameless to protect them from any mistakes made in this post (which are solely my own).
As always, comments and feedback is welcomed and greatly appreciated. As are suggestions on improvements, pitfalls and blatant mistakes :)
Note: The code for Part 3 (this post) can be found on my Bitbucket account.


text:
[http://youtu.be/j6zseFi070E] (YouTube link)Jeff Highsmith's oldest son started school and needed a desk for homework. But this kid didn't get just any desk- his dad built him something extraordinary. When th...http://www.neatorama.com/2014/02/22/Mission-Control-Desk/
It's more than a clever business card—it's a survival kit! The beef jerky business card may feed you, but it won't solve basic electronic problems. Saar Drimer's hand-soldered card has essen...http://www.neatorama.com/2013/12/02/An-Engineers-Emergency-Business-Card/
If you do a lot of electronic work, it may be handy to keep a color-coded resistor chart nearby. Becky Stern of Adafruit has you covered with this cross stitch sampler. You can find her pattern at the link. Link -...http://www.neatorama.com/2012/06/02/resistor-cross-stitch/
(YouTube link) Bill Hammock, the Engineer Guy, explains how our hi-tech gizmos work as well as they do because of a thin layer of corrosion. -Thanks, Bill!...http://www.neatorama.com/2012/05/29/anodizing-or-the-beauty-of-corrosion/
At first glance, the speaker above may look li... ...to the Behringer's booth at next month's Consumer Electronicshttp://www.neatorama.com/2011/12/12/the-worlds-largest-ipod-dock/
(YouTube link)From YouTube member bd594, the same geek who brought us "Bohemian Rhapsody" by The Gadget Orchestra a couple of years ago, we now have the classic "House of the Rising Sun" played by various vintage electro...http://www.neatorama.com/2011/12/02/house-of-the-rising-sun/
This amazing new device does a lot more than project little duckies onto objects, it projects a truly 3d image onto whichever surface you choose. You can walk around your projection, view it from all sides, and would...http://www.neatorama.com/2011/10/24/hitachis-new-3d-projector/
We've all experienced the pain and heartbreak as... ...pain and heartbreak associated with water-related electronics tragedies. From cell phones dropped in the toilet... ...It might be just the thing to bring your beloved electronics back to life. Linkhttp://www.neatorama.com/2011/07/21/wet-phone-theres-a-bag-for-that/
A new gadget pen created by researchers at the University of Illinois at Urbana-Champaign creates functional electronic circuits on surfaces such as paper and wood . Using liquid metal ink made of silver nanoparticles th...http://www.neatorama.com/2011/06/30/ballpoint-pen-that-draws-electronic-circuits/

subset: commoncrawl


text:
Inflammation of the Testicle (Orchitis)
Orchitis Facts
Patient Comment Read 1 Comment
Orchitis is an inflammatory condition of one or both testicles in males, generally caused by a viral or bacterial infection.
Orchitis Causes
Patient Comments
Orchitis in children most commonly occurs as a result of a viral infection.
Less commonly, orchitis can be caused by a bacterial infection. Generally speaking, most cases of bacterial orchitis occur from the progression and spread of epididymitis (inflammation of the coiled tube on the back of the testicle), either from a sexually transmitted disease (STD) or from a prostate gland/urinary tract infection. This condition is termed epididymo-orchitis.
Individuals may be at risk for non-sexually transmitted orchitis if they have not been immunized against mumps, if they get frequent urinary tract infections, if older than 45 years of age, or if they frequently have a catheter placed into their bladder.
Medically Reviewed by a Doctor on 4/1/2016
Medical Author:
Medical Editor:
Next Page:
Must Read Articles Related to Inflammation of the Testicle (Orchitis)
Chlamydia Chlamydia is a sexual transmitted disease (STD) ...learn more >>
E. coli: Escherichia coli 0157:H7, E. coli 0157:H7 Escherichia coli 0157:H7 (E. coli 0157:H7) infections are caused by bacterial. E. coli 0157:H7 is one of the most virulent strains and is passed from person to ...learn more >>
Gonorrhea Gonorrhea is one of the most common learn more >>
Patient Comments & Reviews
The eMedicineHealth doctors ask about Inflammation of the Testicle (Orchitis):
Inflammation of the Testicle (Orchitis) - Symptoms
What were your symptoms of testicle inflammation (orchitis)?
Inflammation of the Testicle (Orchitis) - Medical Treatment
What was the medical treatment for your orchitis?
Men's Health Resources
Featured Centers
Health Solutions From Our Sponsors
Read What Your Physician is Reading on Medscape
Orchitis »
Orchitis is an acute inflammatory reaction of the testis secondary to infection.


text:
Garshasp: The Monster Slayer Credits (Windows)
Published by
Developed by
Critic Score
100 point score based on reviews from various critics.
User Score
5 point score based on user ratings.
Garshasp: The Monster Slayer Credits
Other Games
In addition to this game, the following people are listed as working on other games. No more than 25 people are listed here, even if there are more than 25 people who have also worked on other games.
Roger Walkden, 57 other games
Jay Wilbur, 56 other games
Erik Simon, 56 other games
Adam Boyes, 31 other games
Christer Ericson, 23 other games
Eric Williams, 23 other games
David Jaffe, 21 other games
Lenny Brown, 18 other games
Martin Szymanski, 18 other games
Karl Jones, 14 other games
Christian Sauerteig, 11 other games
Agostino Simonetta, 10 other games
Benjamin Bezold, 10 other games
Pieter Wycoff, 10 other games
Kay Bennemann, 9 other games
Phil Wilkins, 9 other games
Holger Kuhn, 9 other games
Mario Baumann, 8 other games
Peer Fischer, 8 other games
Michael Schlaak, 8 other games
Behrooz Roozbeh, 8 other games
Torsten Meier, 8 other games
David Cage, 8 other games
Bill Jackson, 7 other games
Katharina Hoerold, 7 other games
People who have worked on this game have also collaborated on the creation of the following games:
Alpha Polaris, a group of 14 people
What Makes You Tick: A Stitch In Time, a group of 11 people
Spy Hunter: Nowhere to Run, a group of 7 people
I'm Not Alone, a group of 7 people
Max & the Magic Marker, a group of 7 people
DWK 5: Hinter dem Horizont, a group of 6 people
Dark Sector, a group of 6 people
Fenimore Fillmore's Revenge, a group of 5 people
God of War III, a group of 4 people
God of War, a group of 4 people
God of War: Ascension, a group of 4 people
God of War II, a group of 4 people
God of War: Ghost of Sparta, a group of 3 people
Goin' Downtown, a group of 3 people
Credits for this game were contributed by Patrick Bregger (164961)


text:
Flowing curves, smooth edges and tapered feet give this gorgeous nightstand a subtle, sophisticated look which makes it the ideal piece to keep hold of everything your little one needs to keep close for a restful night's sleep. Featuring one, six inch deep drawer which has a slow-motion, self-closing mechanism, there is an open shelf underneath for items which can be kept on show or grabbed easily. For added elegance, this piece comes with pearlescent silver effect pulls.
Guaranteed to have extremely low levels of volatile organic compounds and other potential harmful chemicals, all finishes are lead-free, non-toxic and has a full bottom dust cover which prevents any possible dust entry.
- 100% solid wood - Canadian birch
- High resistance finish
- Finished Drawer Boxes - clear coat varnish
- 6-inch deep Drawers, with an English dovetail for increased strength
- Slow-Motion, Self-Closing, Anti-Pinch Drawer Glides with Safety Locks meaning the drawers cannot be slammed shut
- Recessed & Encased Back Panel which reinforces unit's structure
- Dust Cover on furniture bottom helps reinforces unit's structure & eliminates dust entry
- Pearlescent Silver (metal) Knobs made in Italy
Depth: 21" | Height: 24" | Width: 25"
This is a Bespoke item; please read our Terms and Conditions for Bespoke orders. Contact Gigi Brooks' Customer Services if you have any questions or would like to discuss your design options with one of our team of specialists.


text:
06. 02. 2008 - Czech Airlines' Sofia Service Celebrating its 60th Anniversary
Prague, 6 February 2008
On Saturday, Czech Airlines will celebrate the sixtieth anniversary of the commencement of regular flights between Prague and Bulgaria's capital, Sofia. The then Czechoslovak Airlines first flew to that destination on 9 February 1948. The route was operated by the legendary DC-3 Dakota aircraft. Presently, the Airline deploys its most modern Airbus A320 aircraft or Boeing 737s for 162 passengers on this twice-daily service.
Czechoslovak Airlines launched the service to Sofia in the post-war era, full of plans for the airline's further development. In 1948, Czechoslovak Airlines opened up a number of national routes, and many routes abroad, and planned to start flying to the US and Canada, and to purchase long-range American aircraft. Those plans were put to an end by the political coup of 25 February 1948, causing a significant reduction in the route network and in air transport in general.
Last year, the service to Sofia was used by 113,700 passengers, representing a 10.9 percent year-on-year increase. Overall, Czech Airlines operated nearly 620 flights between Prague and Sofia in 2007, which is a 5.5 percent year-on-year increase. The more rapid increase in the number of passengers than the number of flights documents that the utilisation of flights keeps increasing from year to year. This year, Czech Airlines expects a further increase in demand for flights between Prague and Sofia. A morning flight, three times a week, will be added to the afternoon and evening flight, departing on Tuesdays, Wednesdays, and Fridays at 6:50 a.m. from Sofia, and at 9:15 a.m. from Prague. The overall capacity offered between Prague and Sofia will thus increase by ten percent year-on-year.
Plan for 2008
The Czech Airlines air service between Prague and Sofia is used primarily by businessmen and managers. Many of them carry on from Prague on Czech Airlines connecting flights, primarily to Western Europe and Scandinavia, but also to the USA.
During the winter flight schedule, i.e., until 29 March, Czech Airlines essentially offers two flights per day to Sofia, leaving Prague at 11:30 a.m. and 7:10 p.m. From Sofia, passengers can fly at 9:00 a.m., landing in Prague at 9:55, i.e., before the day's peak departure time. The afternoon flight takes off at 3:10 p.m., landing in Prague at 4:05 p.m.
Daniela Hupáková
Communications Director
Czech Airlines Spokesperson


text:
Netgear SRX5308. Switch type: Unmanaged network switch. Supported data transfer rates: 180/21 Mb/s, Maximum data transfer rate: 924 Gbit/s. Certification: RoHS, China RoHS Safety: CE/LVD, cUL EMI: FCC Part 15 Class A, CE mark commercial, C-Tick Class A, V. Internal memory: 512 MB, Flash memory: 64 MB. Weight: 2.1 kg
- Four Gigabit WAN ports for load balancing or failover protection- Hardware accelerated data flow architecture allows for 1Gbps of LAN-to-WAN throughput- Supports up to 125 IPsec VPN tunnels and 50 SSL VPN tunnels for secure remote accessUltra High Performance Business-class Firewall SecurityThe flagship model of the ProSafe firewall family - the SRX5308 is perfect for even the most demanding business networks. The SRX5308 features a hardware-accelerated data flow architecture that allows for 1 Gbps of stateful firewall throughput. This powerful VPN router is a high-performance, SNMP-manageable, network solution that furnishes multidimensional security including denial-of-service (DoS) protection, stateful packet inspection (SPI), URL keyword filtering, configurable hardware DMZ port, logging, reporting, and real-time alerts. QoS, WAN traffic metering, and bandwidth profiling gives you granular bandwidth management capabilities. VLAN support allows you to separate guest traffic from critical production servers. Four Gigabit LAN ports allows for maximum internal data transfer speeds, while the four Gigabit WAN ports provide two modes of session-based load-balancing as well as failover protection to ensure maximum throughput and reliable connectivity to the Internet.Features & Benefits- LAN-to-WAN Throughput1Hardware-accelerated 1Gbps LAN-to-WAN firewall throughput200,000 concurrent connections- Secure FirewallDoS attack protectionBlock TCP/UDP packet floodsPort/service blockingHardware DMZ portWeb content filter- Quad Gigabit WAN Ports2 modes of session-based WAN load balancingWAN failover for maximum uptime- VLAN SupportCreate up to 254 individual 802.1Q VLANsAllows for secure network segmentationSeparate guest traffic from critical production servers- SSL and IPsec VPN Remote AccessSSL VPN – clientless remote access, anywhere, anytimeIPsec VPN – secure site-to-site tunnels and client-based remote accessIndustry-strength encryption algorithmsIKE authentication protects against unauthorized remote access125 simultaneous IPsec VPN tunnels50 simultaneous SSL VPN tunnels- Bandwidth ManagementControl end user bandwidth consumption with Bandwidth ProfilesPrioritize traffic with Quality of Service (QoS)WAN Traffic Metering- Easy to UseAuto Detect connects to your ISP quicklyDHCP (client and server) for fast deploymentIntuitive Web management GUIIPsec VPN Wizard allows for easy VPN setupSNMP, telnet management supportSYSLOG and emailed logs enable thorough network monitoring- Reliable NETGEAR HardwareIndustry-grade metal casingHigh-quality electronicsNETGEAR Lifetime Warranty


text:
magine this: by 2020 we will be able to carry every word every written, every picture or video ever taken and every music track every recorded - in fact the entire world's content - on a small device in our pocket. That's when scientists recently estimated that storage will be so advanced that the world's digitised content might fit onto what will no doubt be the must-have present for Christmas 2020 - the and new and oh-so-achingly hip googlepod.
OK, so we'll theoretically have unlimited access to the world in our pockets, fantastically useful and fun for bite-sized information and entertainment but perhaps unlikely to be a huge draw for extended viewing, or say, viewing a digitised version of The Independent on its tiny screen.
So what's next in the dizzying scramble for new-media real estate? Well, last week one answer came from the iPod-inventor, Apple, which unveiled its vision of our future viewing. Its chief executive, Steve Jobs, announced the launch of a download service that means that a range of films can either be watched on the move or through Apple's new device, iTV, that will transmit video from your computer to your TV.
There's no doubting the public appetite for video over the internet, and that downloading Mission Impossible or episodes of Desperate Housewives will be highly popular. But where does it leave important and vulnerable television programme-areas such as news and current affairs and arts? These have depended either on government subsidy or, increasingly, being sandwiched between more popular shows in the schedule.
So pressing is this problem that, in what amounted to his exit interview, Stephen Carter, Ofcom's former chief executive, told Broadcast magazine that one of his principal regrets was that he should have pushed his plans further and faster. This could have been done, he argued, by being bolder about reducing ITV's public-service broadcasting (PSB) obligations, so "sharpening" the debate.
Then, over the long, hot summer, Ofcom slipped out an issues-paper looking at the future of this type of programming after the digital switch-over in 2012. The 40-page document received little attention, which was perhaps just as well since, when the regulator had first floated its new concept two years ago it was greeted with a range of reactions from bafflement to worse.
You'll be forgiven for not having followed every jot and comma of this acronym-laden debate but (take a deep breath), in a nutshell, Ofcom is suggesting that because of the huge changes in the way we will consume content in the future "we need to re-imagine" the delivery of PSB. This would be achieved through the creation of a new publicly funded public service publisher (or PSP) which would commission content to provide competition to the BBC across a range of platforms, rather than just on regular TV.
A huge amount of bunk is spoken about the current state of health of these types of programmes but, perhaps strangely as a former controller of ITV's current affairs, arts and religion, I tend to agree with Carter. The current system that holds commercial broadcasters to wildly out-of-date licence-requirements in return for access to the airwaves has all but broken down. It's plain to many of us who work in the field that the sort of box-ticking quotas system became self-defeating and contributed to almost killing off the genres it sought to nurture. Within broadcasters these programmes were perceived to some degree as being produced under forbearance, leading to a mentality that "worthy" programmes could rarely deliver viable ratings or be commercially successful.
So what changed? At least part of the answer is that increased competition came to the rescue, inspiring a new creativity. Multiple channels, the web, broadband, blogs and chat-forums have allowed us far greater access than ever and helped refresh and refocus traditional programming. The Web 2.0 revolution promises to take this further, with media-rich interactivity and user-generated content.
Back on old-fashioned TV and radio, the reality is that at least some of these programme-types are thriving. The Boys Who Killed Stephen Lawrence, an inspiring recent BBC investigation, delivered 3.9 million viewers and a 20-per-cent share at 9pm. Tonight with Trevor McDonald consistently achieves 3.5 to 4 million viewers at 8pm, up against EastEnders, and Melvyn Bragg's In Our Time, from Radio 4, is hugely successful as a podcast. And whether or not you agree with the outgoing ITV boss Charles Allen, the excellent Channel 4 News, Dispatches and much else besides are hardly emblematic of Channel 4's failure to deliver on its public service remit. Yet, while all this reflects the creativity of producers and a healthy public appetite for such programming, most of these are underpinned by public money.
So, as the analogue clock counts down, there are increasingly pressing questions about the viability of the full range of subject matter that we've come to enjoy, and how it will translate to a diverse range of platforms. This is why the regulator's plan should be welcomed, but with a number of caveats: it needs far more detail and a firm timetable; lessons must be learnt from the now all-but-defunct commercial PSB system; if the new plan is to be successful it mustn't be a straitjacket of prescriptive quotas and stop-watched minutes; above all it must be a flexible evolving and reactive concept.
Ed Richards, currently Ofcom's dynamic chief operating officer, is widely tipped to be about to step up to the chief-executive role, with Ofcom saying that the announcement on who gets the job will be made next month. It would be good news if it is Richards, as the former Downing Street adviser, BBC strategist, and researcher for Diverse Productions (where he worked on programmes for Channel 4) is a strong advocate of the new PSP. Let's just hope that this means the issue will be at the top of his in-tray - or whatever new media gadget he has.
The BBC sends Little, not Large, to the party conferences
First Andrew Neil and his This Week team massacred "Is this the way to Amarillo", and now his other BBC show, The Daily Politics, is resorting to sending "a Little Andrew Neil and a Little Jenny Scott" to the party conferences, after a team brainstorm, in an attempt to find ways of "refreshing" their coverage.
"You may say it's a straight rip-off of Little Ant and Little Dec on ITV," says Jamie Donald, the editor of the BBC's live political programmes, "but Little Ant and Little Dec got to interview the Prime Minister, and put to him some very challenging questions. For four years, Mr Blair and Mr Brown have consistently refused to be interviewed for the BBC's conference coverage, believing it doesn't reach the people they want to speak to. Maybe now they'll change their minds".
Today Little Andrew and Little Jenny are making a start by grilling Sir Menzies Campbell at the Liberal Democrat conference in Brighton. However, not all the programme's fans seem content - one has replied to Donald's explanation of the stunt on a blog with: "I felt like shooting myself when I read your observations".
When I rang Big Andrew's office he didn't want to comment.
Dominic Crossley-Holland was ITV's last controller of current affairs, arts, and religionReuse content


text:
New Play Control! Pikmin Wii
- Publisher: Nintendo
- Release Date: Mar 9, 2009
- Critic score
- Publication
- By date
The most important thing is: Pikmin is worth playing. It's simply indispensable in any fan collection and a sample of the different way Nintendo makes its games. On the other hand, if you've already played it fully on GameCube, maybe the new version is dispensable
It's not as good as its sequel but Pikmin is still a great game and is essential to those who haven't played it.
If you devoured it back then, be forewarned that there's no extra meat on the bone – no extras, no real refinements beyond the Wii control scheme. If you never got into it, though, don't let the cut-price Wii version slip through your fingers this time.
Pikmin virgins and curious Wii owners should definitely take a look at this quirky, satisfying little game, especially if they have a craving for something a bit different. Vets will probably be fine with their dusty GC copies, but this is certainly a game worth experiencing, in its old or waggle-enhanced form.
Pikmin is a little gem that puts you in touch with the power, the beauty and the cruelty of the Nature in a wonderful way. Just don't mind if you already played the game on Gamecube.
A cynical reissue to exploit the game-starved hardcore on Wii? This is far too complicated for your mum to play. Still, it's a genuine (prequel to a) classic.
Pikmin proved to be quite a revelation when first released, and its charm is not only still there today, but magnified by the inclusion of some very intuitive Wii Remote motion controls and a few other extras to keep fans happy.
The control fiddling has worked, so hats off to the new Pikmin team, and I can recommend this one to any Wii owners, of any age.
Games Master UKThe Pikmin gameplay is still a winner but you might want to hang on for Pikmin 2.[Mar 2009, p.76]
Pelit (Finland)A fun re-release of the Gamecube classic. [Mar 2009]
As one of the first budget-priced GameCube-to-Wii upgrades, New Play Control! Pikmin is a perfect example of what the series is capable of.
Thanks to excellent controls and a cute premise, Pikmin is a must play for newcomers and fans alike.
If you've never dabbled with the series before, the New Play Control! title is a superb buy, especially since it retails for a reduced price.
Fun for all ages. While there's nothing new to speak of, fans of the GameCube version may enjoy a revisit; however those who missed Pikmin the first time around will get the most bang for their buck.
For anyone who hasn't yet had a chance to give Pikmin a go, this is a great opportunity to jump into the series. The new Wii controls work great, and though the production values have aged a bit, it's still a fine game worth going back to.
There's just something about watching your army haul back a bounty from a hard day's work that's very satisfying.
The game may be as old as the Wii's predecessor, but New Play Control! Pikmin still remains a very challenging and engaging title. While the graphics haven't held up as well as one would have hoped, the sound and gameplay definitely remain timeless.
Nintendo's goals with this game appear more modest, and they are largely accomplished. If better controls for an eight-year old game meet your equally modest goals, you should find little that disappoints.
Pikmin is a quirky, innovative, colourful, charming, and addictive game- epitomising exactly what Nintendo are all about. Sure, it's just a GameCube port with Wii controls slapped on, but it works well.
Pikmin newbies and curious Wii owners alike should definitely take a look at New Control Play! Pikmin, especially if they have a craving for something a bit different.
Pikmin, the Miyamoto's RTS experiment, comes to Wii with slightly improved controls and a lower price in order to attract wiimote's fans who couldn't play eight years ago one of the most original and fresh ideas for our dear but dead Gamecube.
If you loved Pikmin and are dying to play again you could probably find a copy way cheaper on the Gamecube (which you can still play on your Wii through backwards compatibility). However, if you'd like to give the new controls a shot, they make the game a little easier to control and for $30, it's not going to prevent you from checking out some other new games as well.
New features in this revision might seem too few. There are no new game modes, nor a graphics overhaul or interesting new things apart from the new control.
Although it has an improved graphical system (16:9 and 480p scan are available), and a control scheme perfectly functional, Pikmin is the same game of six years ago. Those who own a copy of the original version can leave New Play Control on the shop shelves. But those who have never experienced the adventures of Olimar, should take the opportunity to discover one of the most creative game in the past generation. Deep, immediate, poetical: Pikmin is a great classic of videogame industry.
The Wii interface is a brilliant fit for the game, giving it the speed and fluidity of a true RTS.
Pikmin is a creative, original take on console strategy gaming. Not everyone may take to the strategic undercurrent, but as it stands, this Pikmin has already fixed its roots deep in my jaded gamer's heart.
Pikmin 2 is also due a New Play Control! reissue this year, and it's a better game in every respect. It's longer and more sophisticated, with more varied Pikmin and enemy types; it has co-operative and competitive multiplayer; it has randomised caves with finite Pikmin numbers, ideal for the game's challenge mode; it has no time limit.
Viewing this simply as a re-release it's still a hugely enjoyable game, overshadowed only by its own sequel - with its longer, more complex missions, no time limit and multiplayer modes. Since it's getting the New Play Control treatment too it makes this a little harder to recommend... but not much.
Nintendo's New Play Control! first text in Europe's Pikmin, a comeback to the story of Captain Olimar and his little coloured friends that's been adapted for the wiimote and the nunchuk. It's basically the same game that we saw in 2001 with an improved gameplay system, with same graphics and music.
If you've already experienced the charm of Pikmin you're better off waiting for the tweaked second game, but if you missed out on the GameCube and fancy some easy to play real-time strategy there's no reason not to pick this up in preparation for the sequel.
Despite its age, Pimkin delivers an immersive experience. Technically is surely getting old, but style and playability make it great on Wii. This is your chance to add 10 years of Nintendo's history to your collection: think about it.
New Play Control! Pikmin is not only smart, but also a very fun addition for the Wii. The controls are almost perfect and that's what Pikmin is all about. We strongly recommend this title for every gamer that has never played a Pikmin game before, but also for every gamer with a little Pikmin heart. Even though the game is a little outdated it still feels like the game that the GameCube version should have been.
There's a lovely, bucolic charm to Pikmin which makes its brevity easy to forgive. Less acceptable is the fact that a seven-year-old game has been repackaged as a Wii title for an excessive £30 – Nintendo has certainly missed a trick by not adding any kind of extras to increase its longevity.
Are you looking for a tactical game on the Wii, Pikmin is a fun title you should consider buying. Unfortunately it only has a short story. If you never played the GameCube version, but it always looked interesting to you, it is worth the money. Trust me!
Pikmin was a good game back in 2002. Maybe Nintendo thought they should release it again. We rather wished they didn't. The game is a complete waste of time. The game hasn't changed a bit since the original and brings no new content. That's just ridiculous. If you never played Pikmin before...here's your chance...wooptiedoo!
Awards & Rankings
User Score
Generally favorable reviews- based on 33 Ratings
User score distribution:
Positive: 5 out of 5
Mixed: 0 out of 5
Negative: 0 out of 5
RubbermadeMar 27, 2009This is a fantastic game. It is a remake so how can anyone criticize it on having bad graphics or no new content or for not being Pikmin 3?This is a fantastic game. It is a remake so how can anyone criticize it on having bad graphics or no new content or for not being Pikmin 3? New Play Control Pikimin is better than the GCN Pikmin. I can see now why people claim that the Wii has no games rated highly on this site and its because the critics are bias against the Wii and closed minded.… Full Review »
Jul 10, 2014Fantastic game, not just a port, this version allows you to restart your day or go back in times a few days back. So the obnoxious time limitFantastic game, not just a port, this version allows you to restart your day or go back in times a few days back. So the obnoxious time limit is not as grueling at all here. On top of that the wiimote seems to have been made for Pikmin, and this is coming from someone who does not like the wiimote one little bit. A wonderful first installment for one of the best series Myamoto and Nintendo ever created. Here's to many more Pikmin games.… Full Review »
Feb 25, 2011Ah, Pikmin. one of the best RTS series of all time.
it's so great. it's mixes fighting and scavenger hunting so well that My brain should beAh, Pikmin. one of the best RTS series of all time.
it's so great. it's mixes fighting and scavenger hunting so well that My brain should be splattered on the wall from an awesomeness explosion. Why that hasn't happened yet, I'll never know.… Full Review »


text:
LONDON -- Britain's rhythmic gymnastics group is making an appeal after missing out on a place at the London Olympics.
The group failed to reach the score it needed during the first two days of the test event at O2 Arena last month. That competition also served as a second Olympic qualifier.
The team says it was under the impression all three days of the competition counted toward Olympic qualifying. Britain exceeded the required score on the third day.
The appeal will be heard by an independent body Feb. 29.


text:
12 Stories You Need To Know Today
Five Guys and Shake Shack open in London, Volvo tests in-road charging systems and Huffington post launches its African edition.
London's super-rich feel the squeeze as luxury goods become more expensive. Guardian
On why the App Store is unsustainable for startups. Business Insider
MTV UK used Snapchat to promote the promo of their new TV show, Geordie Shore. Mashable
Vine use on Twitter up by almost 100% over the past two months. Paid Content
OUYA, crowded funded gaming console, sold out on Amazon. Engadget
After huge investment, in-flight Wi-Fi is being offered on 8,700 domestic flights. NYT
Five Guys and Shake Shack to open in London this July. Bloomberg
22 British clothing companies agreed to record and report the environmental impact of their clothing. Triple Pundit
Volvo tests its in-road charging system that will allow electric cars to travel without making stops. Uber Gizmo
Huffington launches its first African edition in the form of Huffington Post Maghreb, a French language version catering to Tunisia, Morocco and Algeria. The Drum
Wedding website, The Knot, launches Gay Weddings, new digital magazine. The Knot
Zynga has spent more than $ 300 million in acquisitions in the past three years. Polygon


text:
FAQs: What are the first signs of Alzheimer's disease?
The most common warning signs of Alzheimer's disease (AD) are:
- Asking the same question or repeating the same story over and over again
- Forgetting how to do activities that were previously routine, such as cooking, making repairs, or playing cards
- Losing the ability to handle money or balance a checkbook
- Getting lost in familiar surroundings or misplacing household objects
- Neglecting to bathe or wearing the same clothes over and over again and often insisting that he or she has bathed or that his or her clothes are still clean
- Relying on someone else, such as a spouse, to make decisions or answer questions he or she previously would have handled themselves.
Learn more about the symptoms of AD at www.nia.nih.gov/alzheimers/topics/symptoms.


text:
GEETANJALI RAWAT IT Analyst
Email: firstname.lastname@example.com 614-***-**** / 614-***-****
Professional Summary
• 5+ Years of experience in Quality Assurance of ERP Based Application, Web Based Application, and Client Server based Application.
• Strong Experience in both Manual and Automation Testing of software applications.
• Experienced in assessing testing processes, creating, implementing testing strategies and SQA strategies using Agile-testing methodology.
• Experienced in writing, reviewing and executing test scripts, test plans and test strategies.
• Expertise in User Administration, System Administration and Content Administration of SAP
Enterprise Portal.
• Certified and extensive experience in QTP for writing scripts, merging with QC, using checkpoints etc.
• Certified and Expertise in Database testing for applications developed with MSSQL using SQL Query Analyzer, SQL Enterprise Manager and SQL Server management Studio.
• Expertise in developing and maintain reports using Microsoft reporting Services as a Reporting Tool.
• Strong working knowledge of OOPs concepts.
• Expertise in testing Java, J2EE, JavaScript, JSP, HTML, XML, ASP and VB.Net based Application.
• Expertise in deploying the applications in IIS, Weblogic Application Server and Wepsphere Application Server
• Created unit test cases for WhiteBox Testing using JUNIT Tool.
• Traced the defects using CRM Clarify, Silk Radar, Test Director, Pivotal, Clear Quest and Quality Center (9.0 and 10.0), Bugzilla, WebTeam.
• Expertise in Configuration Management Tool – SharePoint, VSS, SVN and Clear Case for maintaining different versions of the module by check-in and check-out.
• Built and deployed applications on Websphere application server using Build Forge as a Build and Release Management Tool
• Strong knowledge of SDLC, STLC and DTLC.
• Excellent interpersonal, communication and documentation skills.
• Worked on VMware for accessing different operating systems, located remotely, from my machine.
• Hands-on experience with Load Runner.
Technical Skills
• Platforms: Windows 9x/NT/2k/XP, LINUX, UNIX.
• Database: SQL Server 2000, MS SQL, Oracle 9i
• Languages Dev Env.: VB .NET, ASP .NET, C#, Java, J2EE
• ERP Skill set : SAP SCM, SAP CRM, SAP Enterprise Portal, PeopleSoft
• Automated Test Tools: Mercury QTP, Load Runner
• Defect Management Tool: Test Director, Pivotal, WebTeam, Clear Quest, CRM Clarify,
Silk Radar, Quality Center, Bugzilla
• Testing Tool: JUnit
• Scripting Language: Unix/Linux script, Shell Script, VB Script, Ruby,
• Requirement Solution Tool Blueprint
Perl, PL/SQL, Java Script, ASP, JSP
• Terminals: WinScp, Putty
• Application Servers: Weblogic 8.1, IIS, Websphere.
• Web Technologies: HTML, DHTML, XML
• Environment: CMM Levels, Agile, VMware
• Web Browsers: IE , Mozilla Firefox , Google Chrome
• Configuration Management Tool: Clear Case, VSS, SVN
• Release Management Tool: Build Forge
• Development Tool: Toad, Eclipse.
• Requirement Management Tool: Blueprint
• CTFL – Certified Tester Foundation level (ISTQB)
• MCP in SQL Server 2000
• AIS HP Quality Center includes HP QC 9.2 and HP QTP.
• MCSD in C#.NET
Work Experience
Abercrombie & Fitch, Columbus, OH Jul 2011 – Till Date
Role: QA Lead, BA
Project: Time & Attendance: This project involves scheduling of shift and attendance of the associate working in the store or home office at various locations throughout the world.
SOA Oracle 11g Migration: This project involves migration of SOA Oracle messages from 10g to 11g
Ecommerce: This project involves different types of Ecomm applications including website, promotional campaigns, online order etc…
• Working on the QA methodology which best suites the project mentioned above by communicating with the project team and business partners
• Defining and preparing Test Strategies by creating detailed Test Plans with technical team, line of business team to determine the testing environment, phases, timeline of testing, entrance criteria and exit criteria for different phases of testing.
• Extensively involved in creating software-testing life cycle and implementing the same throughout the organization.
• Designing the manual test cases for new functionalities.
• Creating automated scripts using VB Script for new functionalities.
• Performing Performance Testing Feasibility analysis.
• Serving Enterprise Business Analyst to create the testability document.
• Reporting everyday status reports to stakeholders.
• Involved in assigning and delegating tasks to the QA Team
Environment: Java, PeopleSoft, Oracle, SQL Server, Mercury Quality Center, QTP, Neo Load
Lexis Nexis, Dayton, OH Jan 2011 – Jul 2011
Role: Test Lead/ BA
Project: Topics and Taxonomy
This project defines and implements the system to enrich content via enhanced topical classification as currently prioritized by the USLM business. It expands the US legal taxonomy from 17,000 nodes to upwards of 100,000 nodes (plus a few other tasks). It also defines and integrates internal and third party applications for topic masters, taxonomy management node discovery, rule development, automated classification, manual classification and feedback.
• Communicated and collaborated with upper managements and senior business partners to define the Project In-Scope and Out-Of-Scope, Strategies and Deliverable
• Experienced defining and preparing Test Strategies by creating detailed Test Plans with off-shores developers, technical team/lead, line of business team to determine the testing environment, phases, timeline of testing, entrance criteria and exit criteria for different phases of testing such as Unit Testing, System Integration Testing (SIT), User Acceptance Testing (UAT) and Production Check-Out
• Extensive collaboration with business partners and project teammates to analyze high and low level requirements to ensure accuracy in gathering business requirements, analyzed data or workflows and defined the project gaps across multiple projects
• Conducted interviews with the clients (mainly Editors) for gathering detailed requirements, performing evaluation /analysis for functional requirements, planned/analyzed the AS-IS business process in order to create TO-BE business process and documenting the information in Blueprint Requirement Center
• Worked with development team (mainly Technical Leads) to formulate technical design documents and developing use cases, process flow, activity and sequence diagrams
• Review of the test cases written for unit and integration level.
• Managing the day-to-day activities with the offshore test team.
• Managing QC for test cases, requirements, test lab.
• Analyzing and writing detailed specification and test requirements using Blue Print.
• Exporting the requirements from Blueprint to QC.
• Writing Test scripts and functions wherever necessary for various units of the business modules.
• Status reporting to stakeholders
• Reviewing weekly status report
• Reviewing VB script code written for different modules in QTP.
• Writing the VB Script for the Framework of the automation testing of the application.
• Analyzing and providing feedback for performance testing through Load Runner.
• Analyze test results, identify performance bottlenecks and give tuning recommendations
• Assist in issue resolution of Defect Management Process using WebTeam.
• Interface with Environment team(RETS) for infrastructure availability to support testing
• Developing and maintaining traceability matrix for various iterations and for different modules.
Environment: Java, SQL Server, Mercury Quality Center, WebTeam, Blueprint, QTP, Load Runner
Merck & Co., Inc., Lebanon, NJ Oct 2010 – Dec 2010
Role: Senior Automation QA
Project: Comet SAP
Provides front end to US and Mexico users through SAP Customized application with different modules of SAP.
• Prepared the testing documents and test cases, test scripts as per the different phases of the testing.
• Extensive experience in testing the documented Test Cases.
• Written scripts in VBScript to handle SCM module of SAP.
• Designed Regression Test Scenarios in co-ordination with QA and Development Teams.
• Tested the application through SAP GUI.
• Used QC to execute test cases and saving the outcome, import test cases to/from excel, to store requirements.
• Used VB Scripts to automate test cases in QTP.
• Developed, Automated and Executed Test Scenarios using HP Quick Test Pro 9.2(QTP) features like Recovery Scenario Manager , Text Output value , object spy and Parameterization .
• Used checkpoints and synchronization statements extensively to customize the Quick Test Pro (QTP) scripts. Parameterized the scripts and data driven them to improve the flexibility of the tests.
• Integrated the QTP with the Quality Center to run the scripts.
• Worked on the Process order management extensively during the test script design and execution.
• Written the script for creation, modification, confirmation of the process order using COR1/COR2/COR3/CO60 through SAP GUI.
• Interaction with the Client on daily basis for the status reporting and the evaluation and analysis of the scripts written or executed.
Environment: SAP GUI, VB Scripts, Mercury Quality Center, Quick Test Professional
Acresso [Macrovision], Santa Clara, CA Feb 2007 – Feb 2009
Role: Senior QA/BA
Project: Flexnet Manager
Provides businesses centrally monitor, manage and report on software usage in order to optimize usage of the licensed softwares, simplifies license administration, reduces denials of services, and let Acresso demonstrate compliance with vendor agreements.
• Communicated and collaborated frequently with business partners and project teams to gather and analyze high and low level requirements to ensure accuracy in gathering business requirements, analyzed data or workflows, defined the project scope and performed the cost or benefit analyst
• Conducted interviews with the clients for gathering requirements and evaluation or analysis
• Facilitated compilation of high/low level design documents to be used by developers, and worked closely with development team to formulate test plans in the pre-testing phases
• Extensive experience in using Pivotal to document post-implementation incidents/defects and generated reporting and/or statistic for upper-management
• Prepared the testing documents and test cases, test scripts as per the different phases of the testing.
• Performed functional, Sanity, System, Integration, Regression, Retesting, End-to-End testing.
• Developed and integrated monitoring and notification scripts.
• Test Bed Set Up. Deployed various modules and various versions of modules on application server, Web logic and Web sphere.
• Designed Regression Test Scenarios in co-ordination with QA and Development Teams.
• Tested the application for browser compatibility using various browsers.
• Extensive writing knowledge of SQL queries to verify that data is being correctly stored in the database. Also used SQL query analyzer to insert/update data in tables to create different test scenarios.
• Used TOAD for making delta changes in the database.
• Conducted Backend Testing by creating SQL queries using TOAD.
• Solid understanding of Mercury Quality Center with extensive experience managing multiple Domains and Projects, and prepared or managed all modules – Release, Requirements, Test Plan, Test Lab and Defects
• Used QC to execute test cases and saving the outcome, import test cases to/from excel, to store requirements.
• Used VB Scripts to automate test cases in QTP.
• Developed, Automated and Executed Test Scenarios using HP Quick Test Pro 9.2(QTP) features like Recovery Scenario Manager , Text Output value , object spy and Parameterization .
• Used checkpoints and synchronization statements extensively to customize the Quick Test Pro (QTP) scripts. Parameterized the scripts and data driven them to improve the flexibility of the tests.
• Integrated the QTP with the Quality Center to run the scripts.
• Tested the application through SAP GUI.
• Written the script to access the SAP GUI for R/3 and CRM through SAP Enterprise Portal.
• Written the script to launch SAP transaction VA01/VA02/Za01/ZCPH/VA03/VA05.
• Interaction with the Client on daily basis for the status.
• Implemented Microsoft Reporting Services to provide reports for clients to fulfill the requirements.
Environment: SAP, QTP, ASP .NET, C#, VB.NET, VB Script, Java, J2ee, Web logic, Oracle9i, Mercury Quality Center, Web Services, SQL, VMware
Long & Foster Real Estate Inc, Fairfax, VA Feb 2006 – Feb 2007
Role: Software Engineer
Project: Agent Case Express System (ACE)
Provides recording adjustments, accesses reports, authorizes, bulk adjustments, exports reporting etc.
• Prepared test scripts, test plan for different testing methods and phases.
• Maintained and updated test plans, test cases, test environment, and test ware through life cycle.
• Performed blackbox testing -Sanity, System, Integration, Regression, Retesting, End-to-End, (UAT) testing.
• Conducted interviews with the clients for gathering requirements and evaluation or analysis
• Conducted Backend Testing by creating SQL queries to check data integrity, data constraints.
• Managed and developed reports using SSRS 2005 from MSSQL, XML and XSLT.
• Implemented Microsoft Reporting Services to provide critical reports.
• Extensive experience in using Mercury Quality Center to document post-implementation incidents/defects and generated reporting and/or statistic for upper-management
• Implemented and automated regression test scripts based on business requirements using Quick Test Pro (QTP).
• Enhanced the scripts by adding Check points and conditional statements.
• Deployed the .Net application using IIS 6.0.
• Developed Recording adjustments and Reporting modules using C# in .Net Framework
Environment: Win 2k/NT, ASP .NET, C#, VB.NET, VB Script, Java, J2ee, Web logic, Oracle9i, Mercury Quality Center, Web Services, SQL, VMware
Kay Bytes, New Delhi, India May 2005- Jan 2006
Role: Associate Analyst
Project: Ultimate Tool Optimizing Product Information (UTOPIA)
Provides a single portal for quick access to Kay Bytes' product and service information.
• Created and executed unit test cases using JUnit.
• Performed WhiteBox testing.
• Performed user interface, locality, functionality, security testing, retesting, regression, and database testing.
• Used Test Director for defect tracking and defect reporting
• Involved in the Installation build and deployment testing.
• Involved in gathering the requirements.
• Monitored application behavior during testing.
• Performed database testing using stored procedure.
• Written SQL queries against the data for verifying the output from different applications.
Environment: Test director, Java, J2EE, SQL Server 2000.
Bachelor of Engineering in Information Technology with Honors (2001- 2005) from Maharishi Dayanand University, India
Senior QA Lead
Durham, NC - selenium, jira, scrum, qa, framework, sprint,...
QA Analyst
Raleigh, NC - selenium, alm, framework, cases, hp, qa, jira,...
Test Cases Testing
Cary, NC - jira, selenium, alm, qtp, cases, edi, test cases,...
Software QA Reliability and Test Engineer
Fuquay Varina, NC - jira, test engineer, nortel, technical support,...
Test Cases Sales
Cary, NC - cases, requirement, pfizer, test, test cases,...
QA Tester/Software Tester
Morrisville, NC - tester, requirements, testing, execution,...
Sr. SAP Analytics Consultant / Team Lead
Morrisville, NC - bw, hana, sap, bi, bo, lead, functional, team,...


text:
Lee's Tackle Medium RH527VS/XS Flush Mount Bar Pin Rod Holders
by Lee's Tackle
Price: $74.99
TD Code
|Outside Diameter
|Medium with Bar Pin
|0 Degree
|2 in
The choice of boat manufacturers and consumers alike, Lee�s has been the Rod Holder Specialist for over 50 years. Lee manufacturers of over 46 different models of flush mounted rod holders. Available in three different angles (0, 15 & 30 degree) in Stainless Steel. Lee�s has the rod holder to suit any task.
4 Stars based on 4 reviews
By vance curran
arlington, Washington
quality product
August 26, 2015
awesome quality and great appearance
Prosgreat product
Conslittle more finesse to install with trim work required for the hole
By vance curran
arlington, Washington
quality product
August 26, 2015
awesome quality and great finish excellent price
Prosexcellent quality
Consdirections, hole size, takes a little extra trimming for the 15 degree and the 30 degree to fit in the hole
By john m
United States
Great for heavy gear
December 13, 2013
This is the standard for all other rod holders
By scott
ocean city md
flush mount rod holder
October 22, 2013
quality product
Proseasy to install quality
There are no questions or answers for this item.
Similar Products


text:
Cooper U's Visual Interface Design in San Francisco - January
Monday, January 27, 2014 at 8:30 AM - Tuesday, January 28, 2014 at 5:00 PM (PST)
Who's Going
San Francisco, California
London, United Kingdom
Florence, Italy
Event Details
About Cooper's Visual Interface Design Training in San Francisco, California
January 27 - 28
The application of type, color, icons, and other aspects of visual design are critical to the usability of your product or website. Visual design choices are also key to connecting emotionally with your customers (and to selling more products). Our Visual Interface Design course addresses how detailed interaction design, screen layout, and branding should play together to ensure that a well-conceived, well-behaved product is also a usable and desirable one.
More details about the course here!
Cancellation policy
We know things happen. If you need to cancel your registration, notify us by emailing at firstname.lastname@example.com at least 10 business days prior to the start of class, and we will refund your payment, less all applicable discounts (e.g. early bird and multi-class).
Should your plans change with less than 10 business days before class begins, there will be no refunds. However, we will be happy to transfer your registration to the next class that fits your schedule.
When & Where
85 2nd Street
San Francisco,
Monday, January 27, 2014 at 8:30 AM - Tuesday, January 28, 2014 at 5:00 PM (PST)
Add to my calendar
Since 1992, Cooper has partnered with clients to define and deliver upon service and product strategy. We've designed everything from medical devices to consumer products to sophisticated business tools for a wide variety of companies. Our specialty has always been bringing clarity to complex business challenges.
In 2002, we decided to expand our impact by teaching and mentoring clients and working professionals. Drawing from our 20+ years of experience, we offer corporate and public training in service strategy, brand strategy, product definition and design, research, visual design, leadership development and more. See our full list of courses and workshops at www.Cooper.com/training.