PageRenderTime 88ms CodeModel.GetById 41ms app.highlight 29ms RepoModel.GetById 1ms app.codeStats 2ms

/docs/yolk.tex

http://github.com/ThomasLocke/yolk
TeX | 2095 lines | 1622 code | 410 blank | 63 comment | 148 complexity | bf7c3ec6465512a6b9a77b63782c3d0e MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1%% LyX 2.0.0 created this file.  For more info, see http://www.lyx.org/.
   2%% Do not edit unless you really know what you are doing.
   3\documentclass[12pt,english]{article}
   4\usepackage{helvet}
   5\renewcommand{\familydefault}{\sfdefault}
   6\usepackage[T1]{fontenc}
   7\usepackage[latin9]{inputenc}
   8\usepackage{listings}
   9\usepackage[a4paper]{geometry}
  10\geometry{verbose,tmargin=2cm,bmargin=2cm,lmargin=2cm,rmargin=2cm}
  11\setlength{\parskip}{\medskipamount}
  12\setlength{\parindent}{0pt}
  13\usepackage{babel}
  14\usepackage[unicode=true]
  15 {hyperref}
  16
  17\makeatletter
  18%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Textclass specific LaTeX commands.
  19\newenvironment{lyxcode}
  20{\par\begin{list}{}{
  21\setlength{\rightmargin}{\leftmargin}
  22\setlength{\listparindent}{0pt}% needed for AMS classes
  23\raggedright
  24\setlength{\itemsep}{0pt}
  25\setlength{\parsep}{0pt}
  26\normalfont\ttfamily}%
  27 \item[]}
  28{\end{list}}
  29
  30\makeatother
  31
  32\begin{document}
  33
  34\title{Yolk Manual}
  35
  36
  37\date{Revised December 11th. 2012}
  38
  39\maketitle
  40\newpage{}
  41
  42\tableofcontents{}
  43
  44\newpage{}
  45
  46
  47\part{General Information}
  48
  49
  50\section{Copyright and License}
  51
  52This document is copyright (C) 2010-, Thomas Lřcke. You may copy this
  53document, in whole or in part, in any form or by any means, as is
  54or with alterations, provided that (1) alterations are clearly marked
  55as alterations and (2) this copyright notice is included unmodified
  56in any copy.
  57
  58Yolk is GPLv3 software. You should have received a copy of the GNU
  59General Public License and a copy of the GCC Runtime Library Exception
  60along with this program; see the files COPYING3 and COPYING.RUNTIME
  61respectively. If not, see \href{http://www.gnu.org/licenses/}{http://www.gnu.org/licenses/}. 
  62
  63
  64\section{What is Yolk?}
  65
  66Yolk is a collection of packages that aim to help build solid web-applications
  67using Ada. Yolk itself doesn't do a whole lot that can't be accomplished
  68simply by using \href{http://libre.adacore.com/libre/tools/aws/}{AWS}
  69and the \href{http://libre.adacore.com/libre/tools/gnat-component-collection/}{GNAT Component Collection (GNATcoll)},
  70but it does make the job of building complete web-applications a bit
  71simpler. Things like changing user for the running application, catching
  72POSIX signals such as SIGKILL, sending log data to syslogd, adding
  73basic static content handlers, creating and starting/stopping an AWS
  74powered HTTP server and building Atom syndication XML are all made
  75a bit easier with Yolk.
  76
  77A Yolk application is in reality an AWS application, with some sugar
  78added, so you're not really building a Yolk web-application, as much
  79as you're building an AWS web-application. What I'm getting at, is
  80that you need to understand how to use AWS, in order for Yolk to make
  81any kind of sense. What you get when using Yolk is the little things
  82that AWS does not readily provide.
  83
  84
  85\subsection{The Yolk demo application}
  86
  87Reading this manual will of course (I hope!) help you understand how
  88to use Yolk, but please consider taking a closer look at the Yolk
  89demo application to get a feel for how Yolk is actually used. The
  90demo is heavily commented, so it should be fairly easy to understand
  91what's going on. The demo application is also very suitable as a foundation
  92for other AWS/Yolk applications.
  93
  94It is much easier to show how to use Yolk, than it is to write down
  95all possible usage scenarios. With the combination of this manual,
  96the Yolk source files and the demo application, you should be able
  97to make full use of the Yolk packages in your own applications.
  98
  99
 100\subsection{The source code}
 101
 102The Yolk source code is the best documentation there is. This document
 103is never going to be as comprehensive as the actual source, so I'll
 104strongly suggest having the source code available as you read this
 105document. What you will find in this document are short descriptions
 106of what a package is meant to do and perhaps small usage examples,
 107not a complete rundown of every type and procedure in a package.
 108
 109
 110\subsection{Building and installing Yolk}
 111
 112See the README and INSTALL files. These are found in the Yolk root
 113directory.
 114
 115
 116\subsection{The files Yolk depend upon}
 117
 118When you read this document and the Yolk source code, you'll notice
 119that quite a few packages depend on various files being available
 120at specified locations. This is for example the case with the \emph{Yolk.Whoops}
 121package that expects its template file to be found at the path \emph{templates/system/500.tmpl}
 122
 123All such {}``dependencies'' will of course be noted accordingly
 124as we go along, but instead of forgetting one or more in your own
 125application, I'd much rather encourage using the demo application
 126as a foundation for your own applications, since all these fixed paths
 127and files has been properly added to the demo.
 128
 129I also recommend compiling and running the demo, to make sure your
 130Yolk install is working as intended. Just read the \emph{demo/README}
 131and \emph{demo/INSTALL} files for instructions on how to get it up
 132and running.
 133
 134
 135\subsection{The Yolk packages naming}
 136
 137The Yolk packages are pretty diverse, ranging from process control
 138to sending email. I've tried naming them as sensibly as possible,
 139in the hope that the package names alone give away their function.
 140If I've failed, well, you're just going to have to refer to this document
 141or take a look at the source for yourself.
 142
 143\newpage{}
 144
 145
 146\part{The Yolk Packages}
 147
 148
 149\section{Yolk}
 150
 151The Yolk main package currently only contain only a few things: The
 152Yolk \emph{Version} string, a \emph{Config\_File} function to get
 153the location of the configuration file and a \emph{PID\_File} function
 154to get the location of the PID file. These are used in a few places,
 155for example in the \emph{directory.tmpl} template file (the version
 156string), in the \emph{Yolk.Configuration} package (the \emph{Config\_File}
 157function) and in the \emph{Yolk.Process\_Control} package (the \emph{PID\_File}
 158function).
 159
 160All Yolk applications accepts two commandline arguments:
 161\begin{itemize}
 162\item \emph{--yolk-config-file} : Defines the location of the configuration
 163file. If empty or not set, then use the default location \emph{configuration/config.ini}.
 164\item \emph{--pid-file} : Defines the location of the PID file. If empty
 165or not set, then don't write a PID file. Note that if you use the
 166\emph{extras/rc.yolk} script to control your application, then this
 167is handled for you transparently.
 168\end{itemize}
 169
 170\section{Yolk.Cache.Discrete\_Keys}
 171
 172If a piece of data doesn't change very often and it is expensive to
 173build, then caching it might be worthwhile. Instead of going to a
 174file or database on every hit, you simply go to the cache and grab
 175the latest version from there. This is \textbf{\emph{very}} fast,
 176at the cost of some memory.
 177
 178If you know exactly what you want to cache, the \emph{Yolk.Cache.Discrete\_Keys}
 179package might be just what you need.
 180
 181
 182\subsection{The generic formal parameters}
 183
 184These are:
 185
 186\begin{minipage}[t]{1\columnwidth}%
 187\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
 188generic
 189   type Key_Type is (<>);
 190   type Element_Type is private;
 191   Max_Element_Age : Duration := 3600.0;
 192package Yolk.Cache.Discrete_Keys is
 193...
 194\end{lstlisting}
 195%
 196\end{minipage}
 197
 198The \emph{Max\_Element\_Age} defaults to one hour. You should obviously
 199set this to whatever suits your needs. This timer is used for all
 200content in the cache. You cannot set this individually for each element.
 201
 202
 203\subsection{Instantiation}
 204
 205If for example we have two different sets of data (Foo and Bar) that
 206are expensive to build, we can instantiate a \emph{Discrete\_Keys}
 207package to handle this:
 208
 209\begin{minipage}[t]{1\columnwidth}%
 210\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
 211type Cache_Keys is (Foo, Bar);
 212package My_Cache is new Yolk.Cache.Discrete_Keys
 213  (Key_Type     => Cache_Keys,
 214   Element_Type => Unbounded_String);
 215\end{lstlisting}
 216%
 217\end{minipage}
 218
 219And that is all. We now have a \emph{My\_Cache} object that can hold
 220two objects: \emph{Foo} and \emph{Bar}. These are of the type \emph{Unbounded\_String}
 221and they have a \emph{Max\_Element\_Age} of 3600.0 seconds.
 222
 223
 224\subsection{Writing to the cache}
 225
 226Before we can read something from the cache, we must first write something
 227to it:
 228
 229\begin{minipage}[t]{1\columnwidth}%
 230\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
 231declare
 232   Foo_Value : Unbounded_String := To_Unbounded_String ("Foo");
 233begin
 234   My_Cache.Write (Key   => Foo,
 235                   Value => Foo_Value);
 236end;
 237\end{lstlisting}
 238%
 239\end{minipage}
 240
 241That is all it takes: {}``Foo'' is now safely tucked away in the
 242\emph{My\_Cache} object, and will be so for 3600.0 seconds. Calling
 243\emph{Write} with the \emph{Foo }key will always overwrite earlier
 244written \emph{Foo} elements, no matter their age.
 245
 246
 247\subsection{Reading from the cache}
 248
 249A cache obviously only makes sense if you intend to read from it.
 250In our case we want to get our hands on the previously written {}``Foo''
 251value:
 252
 253\begin{minipage}[t]{1\columnwidth}%
 254\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
 255declare
 256   Valid : Boolean := False;
 257   Value : Unbounded_String;
 258begin
 259   My_Cache.Read (Key      => Foo,
 260                  Is_Valid => Valid,
 261                  Value    => Value);
 262   if Valid then
 263      --  do something interesting with the data
 264   else
 265      --  the Foo data is invalid.
 266   end if;
 267end;
 268\end{lstlisting}
 269%
 270\end{minipage}
 271
 272In order for an element to be valid (the\emph{ Is\_Valid} parameter
 273is true), it must:
 274\begin{enumerate}
 275\item have been added to the cache in the first place
 276\item be younger than \emph{Max\_Element\_Age}
 277\end{enumerate}
 278If \emph{Is\_Valid} is \emph{False}, then \emph{Value} is undefined.
 279Note that if \emph{Is\_Valid} is \emph{False} then \emph{Key} is removed
 280from the cache, if it exists.
 281
 282
 283\subsection{Checking if a key is valid}
 284
 285If you need to check whether a specific key exists in the cache and
 286is valid, then you must use the \emph{Is\_Valid} function.
 287
 288\begin{minipage}[t]{1\columnwidth}%
 289\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
 290if My_Cache.Is_Valid (Foo) then
 291   --  Foo is good!
 292else
 293   --  Foo is bad!
 294end if;
 295\end{lstlisting}
 296%
 297\end{minipage}
 298
 299This follows the same rules as the \emph{Is\_Valid} parameter for
 300the \emph{Read} procedure.
 301
 302
 303\subsection{Clearing keys and the entire cache}
 304
 305For clearing of keys and the entire cache we have, naturally, two
 306\emph{Clear} procedures:
 307
 308\begin{minipage}[t]{1\columnwidth}%
 309\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
 310-- First we clear the Foo key
 311My_Cache.Clear (Key => Foo);
 312
 313--  And then we clear the entire cache
 314My_Cache.Clear;
 315\end{lstlisting}
 316%
 317\end{minipage}
 318
 319And that's all it takes.
 320
 321
 322\subsection{Cleanup - Getting rid of stale elements}
 323
 324Calling Cleanup will delete all stale elements from the cache:
 325
 326\begin{minipage}[t]{1\columnwidth}%
 327\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
 328My_Cache.Cleanup;
 329\end{lstlisting}
 330%
 331\end{minipage}
 332
 333Note that this is potentially a very expensive operation if the cache
 334is large, as the entire cache is iterated and every element tested
 335for its age. Use with care.
 336
 337
 338\section{Yolk.Cache.String\_Keys}
 339
 340This package is almost similar to the \emph{Yolk.Cache.Discrete\_Keys}
 341package. The biggest difference is that where the \emph{Discrete\_Keys}
 342cache package requires that you define a type for the keys, this package
 343use regular \emph{String} as keys.
 344
 345The implications of this difference between the two cache packages
 346are subtle. Both have the same \emph{Read}, \emph{Write}, \emph{Is\_Valid}
 347and \emph{Clear} procedures and functions, so in that sense the two
 348packages are the same. The biggest difference lies in the available
 349generic formal parameters and the functionality of the \emph{Cleanup}
 350procedure.
 351
 352
 353\subsection{The generic formal parameters}
 354
 355These are:
 356
 357\begin{minipage}[t]{1\columnwidth}%
 358\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
 359generic
 360   type Element_Type is private;
 361   Cleanup_Size      : Positive := 200;
 362   Cleanup_On_Write  : Boolean  := True;
 363   Max_Element_Age   : Duration := 3600.0;
 364   Reserved_Capacity : Positive := 100;
 365package Yolk.Cache.Discrete_Keys is
 366...
 367\end{lstlisting}
 368%
 369\end{minipage}
 370
 371When the amount of elements in the cache >= \emph{Cleanup\_Size},
 372then the \emph{Cleanup} procedure is called by \emph{Write}, if \emph{Cleanup\_On\_Write}
 373is set to Boolean \emph{True}. \emph{Cleanup\_Size} is a sort of failsafe
 374for this cache package. Since we can't know for sure what is being
 375added (we don't know the keys beforehand), we need to make sure it
 376doesn't gobble up all available resources. Set this number high enough
 377that it'll never tricker under normal circumstances, but low enough
 378that it'll prevent resource exhaustion in case of errors.
 379
 380The \emph{Max\_Element\_Age} defaults to one hour. You should obviously
 381set this to whatever suits your needs. This timer is used for all
 382content in the cache. You cannot set this individually for each element.
 383
 384\emph{Reserved\_Capacity} should be set as close as possible to the
 385expected final size of the cache. If your best guestimate is 200 elements
 386in the cache, then set this to 200. Note that this setting has no
 387bearing on the actual size of the cache. The cache will happily grow
 388beyond the \emph{Reserved\_Capacity} value.
 389
 390
 391\subsection{Instantiation}
 392
 393Instantiating \emph{String\_Keys} is done like this:
 394
 395\begin{minipage}[t]{1\columnwidth}%
 396\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
 397package My_Cache is new Yolk.Cache.String_Keys
 398  (Element_Type      => Unbounded_String,
 399   Reserved_Capacity => 200);
 400\end{lstlisting}
 401%
 402\end{minipage}
 403
 404And that is all. We now have a \emph{My\_Cache} object that can hold
 405objects of the type \emph{Unbounded\_String}, all of which have a
 406\emph{Max\_Element\_Age} of 3600.0 seconds. Also we've told the cache
 407to set aside at least 200 positions for content.
 408
 409
 410\subsection{Writing to the cache}
 411
 412Before we can read something from the cache, we must first write something
 413to it:
 414
 415\begin{minipage}[t]{1\columnwidth}%
 416\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
 417declare
 418   Value : Unbounded_String := To_Unbounded_String ("42");
 419begin
 420   My_Cache.Write (Key   => "Foo",
 421                   Value => Value);
 422end;
 423\end{lstlisting}
 424%
 425\end{minipage}
 426
 427{}``42'' is now safely tucked away in the \emph{My\_Cache} object
 428under the key {}``Foo'', and will be so for 3600.0 seconds. Calling
 429\emph{Write} with the {}``Foo''\emph{ }String will always overwrite
 430earlier written {}``Foo'' elements, no matter their age.
 431
 432
 433\subsection{Reading from the cache}
 434
 435A cache obviously only makes sense if you intend to read from it.
 436In our case we want to get our hands on the previously written {}``Foo''
 437value:
 438
 439\begin{minipage}[t]{1\columnwidth}%
 440\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
 441declare
 442   Valid : Boolean := False;
 443   Value : Unbounded_String;
 444begin
 445   My_Cache.Read (Key      => "Foo",
 446                  Is_Valid => Valid,
 447                  Value    => Value);
 448   if Valid then
 449      --  do something interesting with the data
 450   else
 451      --  the Foo data is invalid.
 452   end if;
 453end;
 454\end{lstlisting}
 455%
 456\end{minipage}
 457
 458In order for an element to be valid (the\emph{ Is\_Valid} parameter
 459is true), it must:
 460\begin{enumerate}
 461\item have been added to the cache in the first place
 462\item be younger than \emph{Max\_Element\_Age}
 463\end{enumerate}
 464If \emph{Is\_Valid} is \emph{False}, then \emph{Value} contains undefined
 465garbage. Note that if \emph{Is\_Valid} is \emph{False} then \emph{Key}
 466is removed from the cache, if it exists.
 467
 468
 469\subsection{Checking if a key is valid}
 470
 471If you need to check whether a specific key exists in the cache and
 472is valid, then you need to use the \emph{Is\_Valid} function.
 473
 474\begin{minipage}[t]{1\columnwidth}%
 475\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
 476if My_Cache.Is_Valid ("Foo") then
 477   --  Foo is good!
 478else
 479   --  Foo is bad!
 480end if;
 481\end{lstlisting}
 482%
 483\end{minipage}
 484
 485This follows the same rules as the \emph{Is\_Valid} parameter for
 486the \emph{Read} procedure.
 487
 488
 489\subsection{Clearing keys and the entire cache}
 490
 491For clearing of keys and the entire cache we have, naturally, two
 492\emph{Clear} procedures:
 493
 494\begin{minipage}[t]{1\columnwidth}%
 495\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
 496-- First we clear the Foo key
 497My_Cache.Clear (Key => "Foo");
 498
 499--  And then we clear the entire cache
 500My_Cache.Clear;
 501\end{lstlisting}
 502%
 503\end{minipage}
 504
 505
 506\subsection{How much is in there?}
 507
 508With the \emph{Discrete\_Keys} cache we obviously always know the
 509exact amount of keys available, since we've defined the keys ourselves.
 510This is not the case with the \emph{String\_Keys} cache, where any
 511\emph{String} can be a key. If we need to know how many elements that
 512are currently in the cache, we call the \emph{Length} function:
 513
 514\begin{minipage}[t]{1\columnwidth}%
 515\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
 516if My_Cache.Length > 1000 then
 517   --  Woa! Lots of stuff in the cache..
 518end if;
 519\end{lstlisting}
 520%
 521\end{minipage}
 522
 523Note that \emph{Length} count both valid and invalid elements.
 524
 525
 526\subsection{Cleanup - Keeping cache size in check}
 527
 528if \emph{Cleanup\_On\_Write} is \emph{True}, then \emph{Cleanup} is
 529called by \emph{Write }whenever the size of the cache reach \emph{Cleanup\_Size}.
 530It is of course also possible to call it manually:
 531
 532\begin{minipage}[t]{1\columnwidth}%
 533\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
 534if My_Cache.Length > 1000 then
 535   My_Cache.Cleanup;
 536end if;
 537\end{lstlisting}
 538%
 539\end{minipage}
 540
 541If you've set \emph{Cleanup\_On\_Write} to Boolean \emph{False} and
 542the String keys are coming from outside sources, then you really should
 543make sure you call \emph{Cleanup} on a regular basis.
 544
 545
 546\section{Yolk.Command\_Line}
 547
 548This package enables you to fetch the value of a given commandline
 549parameter using the \emph{Get} function:
 550
 551\begin{minipage}[t]{1\columnwidth}%
 552\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
 553function Get       
 554  (Parameter : in String;       
 555   Default   : in String := "")        
 556   return String;
 557\end{lstlisting}
 558%
 559\end{minipage}
 560
 561If \emph{Parameter} is found \emph{Get} will return the value immediately
 562following \emph{Parameter.} If \emph{Parameter} isn't found \emph{Default}
 563is returned. 
 564
 565
 566\section{Yolk.Config\_File\_Parser}
 567
 568This package enables you to access KEY/VALUE pairs in configuration
 569files that are written in the style:
 570\begin{lyxcode}
 571\#~This~is~a~comment
 572
 573-{}-~This~is~also~a~comment
 574
 575KEY~VALUE
 576\end{lyxcode}
 577Keys are case-insensitive, so \emph{FOO}, \emph{foo} and \emph{fOo}
 578are all the same.\emph{ }Blank lines and comments are ignored and
 579so is pre/postfixed whitespace. It is not necessary to quote values
 580that contain whitespace, to this:
 581\begin{lyxcode}
 582KEY~some~value~with~whitespace
 583\end{lyxcode}
 584is perfectly valid, and will return {}``\emph{some value with whitespace}''
 585when calling \emph{Get (KEY)}. If VALUE is \emph{Boolean} \emph{True}
 586or \emph{False} (case-insensitive), then the KEY can be returned as
 587a \emph{String} or a \emph{Boolean}, depending on the target type.
 588If the target type does not match the VALUE and no sensible conversion
 589can be made, then a \emph{Conversion\_Error} exception is raised.
 590No dummy values are returned at any time.
 591
 592To clear a default value, simply add the key to the configuration
 593file, with no value set.
 594
 595
 596\subsection{The generic formal parameters}
 597
 598These are:
 599
 600\begin{minipage}[t]{1\columnwidth}%
 601\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
 602generic
 603   use Ada.Strings.Unbounded;
 604   type Key_Type is (<>);
 605   type Defaults_Array_Type is array (Key_Type) of Unbounded_String;
 606   Defaults    : in Defaults_Array_Type;    
 607   Config_File : in String;
 608package Yolk.Config_File_Parser is
 609...
 610\end{lstlisting}
 611%
 612\end{minipage}
 613
 614\emph{Config\_File} is of course the name and location of the configuration
 615file.
 616
 617
 618\subsection{Exceptions}
 619
 620There are 3 different exceptions that can be raised by the \emph{Yolk.Config\_File\_Parser}
 621package. These are:
 622\begin{itemize}
 623\item \emph{Unknown\_Key}. This is raised if an unknown key has been found
 624in the configuration file given when instantiating the package or
 625when \emph{Load\_File} is called.
 626\item \emph{Cannot\_Open\_Config\_File}. This is raised when \emph{Config\_File}
 627cannot be read.
 628\item \emph{Conversion\_Error}. This is raised when a value cannot be converted
 629to the target type, ie. the value {}``42'' to a \emph{Boolean}.
 630\end{itemize}
 631
 632\subsection{Instantiation}
 633
 634\emph{Yolk.Config\_File\_Parser} is a generic package, so in order
 635to use it, you have to instantiate it, like this:
 636
 637\begin{minipage}[t]{1\columnwidth}%
 638\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
 639package My_Configuration is
 640
 641   type Keys is (Foo, Bar);
 642   type Defaults_Array is array (Keys) of Unbounded_String;
 643
 644   Default_Values : constant Defaults_Array :=
 645                      (Foo => To_Unbounded_String ("some foo"),
 646                       Bar => To_Unbounded_String ("some bar"));
 647   
 648   package Config is new Yolk.Config_File_Parser
 649     (Key_Type => Keys,
 650      Defaults_Array_Type => Defaults_Array,
 651      Defaults => Default_Value,
 652      Config_File => "config.ini");
 653
 654end My_Configuration;
 655\end{lstlisting}
 656%
 657\end{minipage}
 658
 659Here we instantiate the \emph{Config} package with \emph{config.ini}
 660as the configuration file. This means that KEY/VALUE pairs found in
 661this file will overwrite the default values set in the \emph{Default\_Values}
 662array. Setting a default value to \emph{Null\_Unbounded\_String} means
 663the value is empty.
 664
 665Note that the \emph{config.ini} file does not have to contain all
 666the valid keys. It is perfectly fine to only add those keys that have
 667non-default values to the configuration file.
 668
 669
 670\subsection{Re-loading configuration files}
 671
 672With the \emph{Load\_File} procedure you can re-load a new configuration
 673file into your \emph{Config} package:
 674
 675\begin{minipage}[t]{1\columnwidth}%
 676\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
 677My_Configuration.Config.Load_File ("new_config.ini");
 678\end{lstlisting}
 679%
 680\end{minipage}
 681
 682Now the KEY/VALUE pairs of \emph{new\_config.ini} will overwrite the
 683ones originally found in the \emph{config.ini} file the package was
 684instantiated with. You can do this as many times as you like. Note
 685that you cannot change what KEY's are valid, so if the \emph{new\_config.ini}
 686file contains unknown keys, \emph{Load\_File} will raise the \emph{Unknown\_Key}
 687exception.
 688
 689
 690\subsection{Getting values}
 691
 692With instantiation and loading of configuration files out of the way,
 693it is now time to get to the configuration values. To get the value
 694of the \emph{Foo} key, you do:
 695
 696\begin{minipage}[t]{1\columnwidth}%
 697\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
 698My_Configuration.Config.Get (Foo);
 699\end{lstlisting}
 700%
 701\end{minipage}
 702
 703There are Get functions for the following types:
 704\begin{itemize}
 705\item \emph{Boolean}
 706\item \emph{Duration}
 707\item \emph{Float}
 708\item \emph{Integer}
 709\item \emph{String}
 710\item \emph{Unbounded\_String}
 711\end{itemize}
 712Empty keys simply return an empty \emph{String} or a \emph{Null\_Unbounded\_String},
 713depending on the target type. If a key is empty and the target type
 714is not a \emph{String} or an \emph{Unbounded\_String}, then the \emph{Conversion\_Error}
 715exception is raised.
 716
 717
 718\subsection{Checking if a KEY has a VALUE}
 719
 720You can check if a key has a value with the \emph{Has\_Value} function:
 721
 722\begin{minipage}[t]{1\columnwidth}%
 723\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
 724if Has_Value (Foo) then
 725   Put_Line ("Foo has a value");
 726end if;
 727\end{lstlisting}
 728%
 729\end{minipage}
 730
 731Basically all this function does is return \emph{Boolean} \emph{True}
 732if the value of the given key is not a \emph{Null\_Unbounded\_String}.
 733
 734
 735\section{Yolk.Configuration}
 736
 737This package is a bit of an oddball, as all it does is instantiate
 738the \emph{Yolk.Config\_File\_Parser} generic with the default AWS
 739and Yolk configuration values. This is used by Yolk internally, but
 740also by the AWS component of your application. The instantiation looks
 741like this:
 742
 743\begin{minipage}[t]{1\columnwidth}%
 744\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
 745package Config is new Config_File_Parser
 746  (Key_Type            => Keys,
 747   Defaults_Array_Type => Defaults_Array,
 748   Defaults            => Default_Values,
 749   Config_File         => Config_File);
 750\end{lstlisting}
 751%
 752\end{minipage}
 753
 754The \emph{Config\_File} function call return either the default Yolk
 755configuration file (\emph{configuration/config.ini}) or a user specified
 756configuration file given by the \emph{--yolk-config-file} command
 757line argument, so\emph{ }starting for example the Yolk demo like this:
 758\begin{lyxcode}
 759./yolk\_demo~-{}-yolk-config-file~/etc/yolk-config.ini
 760\end{lyxcode}
 761will force the demo to look for the \emph{/etc/yolk-config.ini} configuration
 762file.
 763
 764There's a fully commented \emph{config.ini.dist} file available in
 765the \emph{extras/} directory. I recommend taking a look at the Yolk
 766demo application to see how the \emph{Yolk.Configuration} package
 767is used.
 768
 769
 770\subsection{Get the AWS specific configuration settings}
 771
 772On some occassions it might be necessary to get the AWS configuration
 773object. This can easily be accomplished by calling the \emph{Get\_AWS\_Configuration}
 774function:
 775
 776\begin{minipage}[t]{1\columnwidth}%
 777\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
 778AWS_Config : constant AWS.Config.Object := 
 779  Yolk.Configuration.Get_AWS_Configuration;
 780\end{lstlisting}
 781%
 782\end{minipage}
 783
 784
 785\section{Yolk.Email}
 786
 787Using \emph{Yolk.Email} and the child package \emph{Yolk.Email.Composer}
 788you can build and send more or less any kind of email:
 789\begin{itemize}
 790\item Plain text
 791\item Multipart/Alternative
 792\item Multipart/Mixed
 793\end{itemize}
 794The package supports adding multiple SMTP servers, meaning you can
 795add as many as you need, and the email will then be send via the first
 796one that accepts it.
 797
 798The \emph{Yolk.Email} package define 4 exceptions and 3 types. The
 799facilities for actually constructing and sending the email are found
 800in \emph{Yolk.Email.Composer}.
 801
 802
 803\subsection{Exceptions}
 804
 805These are:
 806\begin{itemize}
 807\item \emph{Attachment\_File\_Not\_Found}. Is raised if a file attachment
 808is not found at the given path.
 809\item \emph{No\_Address\_Set}. Is raised if the address component of a To,
 810Reply-To, From, Bcc/Cc header is missing.
 811\item \emph{No\_Sender\_Set\_With\_Multiple\_From}. Is raised when an email
 812contains multiple From headers but no Sender header, as per RFC-5322,
 8133.6.2. http://tools.ietf.org/html/rfc5322
 814\item \emph{No\_SMTP\_Host\_Set}. Is raised if the SMTP host list is empty,
 815ie. no SMTP host has been set for sending the email.
 816\end{itemize}
 817
 818\subsection{The Yolk.Email types}
 819
 820When using \emph{Yolk.Email.Composer} to build and send emails, three
 821types declared in \emph{Yolk.Email} are central:
 822\begin{enumerate}
 823\item \emph{Character\_Set}
 824\item \emph{Recipient\_Kind}
 825\item \emph{Structure}
 826\end{enumerate}
 827The \emph{Character\_Set} type define what character set is used when
 828data is added to an email \emph{Structure} object. For example looking
 829at the \emph{Yolk.Email.Composer.Add\_From} procedure, we see that
 830the \emph{Charset} parameter defaults to \emph{US\_ASCII}:
 831
 832\begin{minipage}[t]{1\columnwidth}%
 833\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
 834procedure Add_From      
 835  (ES        : in out Structure;       
 836   Address   : in     String;       
 837   Name      : in     String := "";       
 838   Charset   : in     Character_Set := US_ASCII);
 839\end{lstlisting}
 840%
 841\end{minipage}
 842
 843This does not mean that \emph{Yolk.Email.Composer.Add\_From} will
 844encode \emph{Name} as \emph{US\_ASCII}, instead it means that the
 845data given in \emph{Name} already is \emph{US\_ASCII}. So if \emph{Name}
 846had contained an ISO-8859-1 encoded \emph{String}, then the call would've
 847looked like this:
 848
 849\begin{minipage}[t]{1\columnwidth}%
 850\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
 851declare
 852   use Yolk.Email;
 853
 854   Email : Structure;
 855begin
 856   Composer.Add_From      
 857     (ES        => Email,       
 858      Address   => "alice@domain.tld",
 859      Name      => "Alice",
 860      Charset   => ISO_8859_1);
 861end;
 862\end{lstlisting}
 863%
 864\end{minipage}
 865
 866In this case you will end up with a From header looking like this:
 867\begin{lyxcode}
 868From:~=?ISO-8859-1?Q?Alice?=~<alice@domain.tld>
 869\end{lyxcode}
 870So bear in mind that it is your responsibility to ensure that your
 871data, and the \emph{Character\_Set} parameter match.
 872
 873The \emph{Recipient\_Kind} type define the kind of recipient that
 874is being added to an email. If you've worked with email, these three
 875should be familiar to you:
 876\begin{enumerate}
 877\item \emph{Bcc}
 878\item \emph{Cc}
 879\item \emph{To}
 880\end{enumerate}
 881When adding recipients to an email \emph{Structure} the default is
 882\emph{To}, but since not all recipients are equal, you can change
 883the kind of recipient to \emph{Bcc} or \emph{Cc}, according to your
 884needs.
 885
 886The \emph{Structure} type is at the core of it all. You declare an
 887object to be of the \emph{Structure} type, and then you use the \emph{Yolk.Email.Composer}
 888facilities to build and send the email.
 889
 890
 891\section{Yolk.Email.Composer}
 892
 893The actual tools for building and sending an email is found in this
 894package. Here are tools for building emails from the ground up and
 895there are a few convenience procedures if you just need to send a
 896simple email with no bells or whistles.
 897
 898I'm not going to go through ever procedure in this package, instead
 899I'll show an example on how to build an email from the ground up and
 900how to use one of the convenience procedures.
 901
 902
 903\subsection{Building and sending an email, the easy way}
 904
 905There are two convenience procedures in \emph{Yolk.Email.Composer}
 906for sending emails without having to do a whole lot of work/thinking.
 907They are both named \emph{Send} and they look like this:
 908
 909\begin{minipage}[t]{1\columnwidth}%
 910\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
 911procedure Send      
 912  (ES             : in out Structure;       
 913   From_Address   : in     String;       
 914   From_Name      : in     String := "";       
 915   To_Address     : in     String;       
 916   To_Name        : in     String := "";       
 917   Subject        : in     String;       
 918   Text_Part      : in     String;       
 919   SMTP_Server    : in     String := "localhost";       
 920   SMTP_Port      : in     Positive := 25;       
 921   Charset        : in     Character_Set := US_ASCII);    
 922   
 923procedure Send      
 924  (ES             : in out Structure;       
 925   From_Address   : in     String;       
 926   From_Name      : in     String := "";       
 927   To_Address     : in     String;       
 928   To_Name        : in     String := "";       
 929   Subject        : in     String;       
 930   Text_Part      : in     String;       
 931   HTML_Part      : in     String;       
 932   SMTP_Server    : in     String := "localhost";       
 933   SMTP_Port      : in     Positive := 25;       
 934   Charset        : in     Character_Set := US_ASCII);
 935\end{lstlisting}
 936%
 937\end{minipage}
 938
 939As you can see, the only difference between these two is that the
 940first one sends plain text emails, while the second one sends \emph{multipart/alternative}
 941with both plain text and HTML parts. Usage is as simple as:
 942
 943\begin{minipage}[t]{1\columnwidth}%
 944\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
 945declare
 946   use Yolk.Email;
 947
 948   Email : Structure;
 949begin
 950   Composer.Send (ES           => Email,
 951                  From_Address => "alice@domain.tld",
 952                  From_Name    => "Alice",
 953                  To_Address   => "bob@domain.tld",
 954                  To_Name      => "Bob",
 955                  Subject      => "Is this thing on?",
 956                  Text_Part    => "Hey you!",
 957                  Charset      => ISO_8859_1);
 958               
 959   if Composer.Is_Send (Email) then
 960      --  Success!               
 961   else                   
 962      --  Failure!
 963   end if;
 964end;
 965\end{lstlisting}
 966%
 967\end{minipage}
 968
 969It is possible, and allowed, to call some of the various other procedures
 970prior to calling one of the convenience procedures. If for example
 971you want to add a custom header, it can be done like this:
 972
 973\begin{minipage}[t]{1\columnwidth}%
 974\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
 975declare
 976   use Yolk.Email;
 977
 978   Email : Structure;
 979begin
 980   Composer.Add_Custom_Header (ES      => Email,
 981                               Name    => "User-Agent",
 982                               Value   => "My User Agent");
 983
 984   Composer.Send (ES           => Email,
 985                  From_Address => "alice@domain.tld",
 986                  From_Name    => "Alice",
 987                  To_Address   => "bob@domain.tld",
 988                  To_Name      => "Bob",
 989                  Subject      => "Is this thing on?",
 990                  Text_Part    => "Hey you!",
 991                  Charset      => ISO_8859_1);
 992               
 993   if Composer.Is_Send (Email) then
 994      --  Success!               
 995   else                   
 996      --  Failure!
 997   end if;
 998end;
 999\end{lstlisting}
1000%
1001\end{minipage}
1002
1003And with that, the header \emph{User-Agent:} is now added to the email:
1004\begin{lyxcode}
1005User-Agent:~My~User~Agent
1006\end{lyxcode}
1007It hardly gets any easier than that. Lets move on and see how the
1008above is accomplished the hard way.
1009
1010
1011\subsection{Building and sending email, the hard way}
1012
1013It is possible to build an email from the ground up, which obviously
1014allows for a more fine grained control over what is added. It is also
1015a bit more complicated, but not much. Lets try and mimick the easy
1016examples, the {}``hard'' way:
1017
1018\begin{minipage}[t]{1\columnwidth}%
1019\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
1020declare
1021   use Yolk.Email;
1022
1023   Email : Structure;
1024begin
1025   Composer.Add_Custom_Header (ES    => Email,
1026                               Name  => "User-Agent",
1027                               Value => "My User Agent");
1028
1029   Composer.Add_From (ES      => Email,
1030                      Address => "alice@domain.tld",
1031                      Name    => "Alice",
1032                      Charset => ISO_8859_1);
1033
1034   Composer.Add_Recipient (ES      => Email,
1035                           Address => "bob@domain.tld",
1036                           Name    => "Bob");
1037 
1038   Composer.Set_Subject (ES      => Email,
1039                         Subject => "Is this thing on?");
1040
1041   Composer.Set_Text_Part (ES   => Email,
1042                           Part => "Hey you!");
1043
1044   Composer.Add_SMTP_Server (ES   => Email,
1045                             Host => "localhost");
1046                           
1047   Composer.Send (ES => Email);
1048               
1049   if Composer.Is_Send (Email) then
1050      --  Success!               
1051   else                   
1052      --  Failure!
1053   end if;
1054end;
1055\end{lstlisting}
1056%
1057\end{minipage}
1058
1059Harder yes, but really not all that much more difficult.
1060
1061
1062\section{Yolk.Handlers}
1063
1064Most web applications will need to handle static content, such as
1065PNG, HTML and CSS files. \emph{Yolk.Handlers} helps you accomplish
1066that, so you don't have to build your own handlers for these kinds
1067of files.
1068
1069The following filetypes are supported by \emph{Yolk.Handlers}:
1070\begin{itemize}
1071\item CSS
1072\item GIF
1073\item HTML
1074\item ICO
1075\item JPG
1076\item JS
1077\item PNG
1078\item SVG
1079\item XML
1080\item XSL
1081\end{itemize}
1082The filetypes that are textual, are compressed according to the \emph{Yolk.Configuration}
1083parameter \emph{Compress\_Static\_Content} which defaults to \emph{False}.
1084The regular expressions for identifying these filetypes are also defined
1085in \emph{Yolk.Configuration} by the \emph{Handler\_{*}} parameters.
1086These regular expressions are registered by the \emph{AWS.Services.Dispatchers.URI.Register\_Regexp}
1087procedure.
1088
1089There's only one procedure in the \emph{Yolk.Handlers} package:
1090
1091\begin{minipage}[t]{1\columnwidth}%
1092\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
1093procedure Set (RH : out AWS.Services.Dispatchers.URI.Handler);
1094\end{lstlisting}
1095%
1096\end{minipage}
1097
1098You can see an example on how this is used in the demo file \emph{my\_handlers.adb}.
1099There's really very little reason not to use this package for handling
1100of static content, but it is of course not mandatory.
1101
1102This package makes use of the \emph{Yolk.Static\_Content} package
1103for the actual delivery of the content to the user.
1104
1105
1106\section{Yolk.Log}
1107
1108This package serves two purposes:
1109\begin{enumerate}
1110\item It contains the two callback procedures used to write AWS logging
1111data (access and error) to syslogd.
1112\item It creates the SQL, SQL\_Cache, SQL\_Error, SQL\_Select, Alert, Critical,
1113Debug, Emergency, Error, Info, Notice and Warning trace handles, and
1114activates them according to the values defined in the configuration
1115file.
1116\end{enumerate}
1117Out of the box, a Yolk application requires a running syslogd daemon,
1118as all log data is sent to syslogd. If for some reason you don't want
1119to use syslogd, you're going to have to hack the \emph{Yolk.Log} package,
1120or remove it entirely.
1121
1122The two procedures named \emph{AWS\_{*}} are used by the AWS HTTP(S)
1123server. These should not be used for anything else - or rather: If
1124you use them for anything else, the \emph{Message} given is going
1125to be written to syslogd with either the AWS access log label or AWS
1126error log label. There's absolutely no harm in this, except it might
1127be a bit confusing when reading the log data.
1128
1129The \emph{Trace} procedure is the one that you will be using in your
1130application. You can send log data to the trace handles defined in
1131\emph{Yolk.Log.Trace\_Handles}. All log data is then sent to the syslogd
1132daemon using the facilities set in the configuration file for the
1133given trace handle.
1134
1135Using \emph{Trace} is about as easy as it gets:
1136
1137\begin{minipage}[t]{1\columnwidth}%
1138\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
1139Yolk.Log.Trace (Handle  => Error,
1140                Message => "Secret sauce to Error!");
1141\end{lstlisting}
1142%
1143\end{minipage}
1144
1145If you haven't activated a trace handle, then calling \emph{Trace}
1146for that handle does nothing, ie. you don't have to remove all your
1147\emph{Trace} calls from the code if you don't use them.
1148
1149Note that on many systems the Emergency messages are written to console,
1150so be cautious about using this specific level, unless you've made
1151certain that you can get to the messages.
1152
1153
1154\section{Yolk.Not\_Found}
1155
1156The job of this package is to return a HTTP 404 status code and an
1157accompanying simple \emph{not found} HTML page. It's sole function
1158\emph{Generate} is about as simple as they come:
1159
1160\begin{minipage}[t]{1\columnwidth}%
1161\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
1162function Generate      
1163  (Request : in AWS.Status.Data)       
1164   return AWS.Response.Data;
1165\end{lstlisting}
1166%
1167\end{minipage}
1168
1169It relies on the template file \emph{demo/exe/templates/system/404.tmpl}
1170to generate the generic 404 HTML page, so if you want to use \emph{Yolk.Not\_Found}
1171in your own application, then remember to bring along this file. Where
1172the \emph{404.tmpl} is placed is defined in the configuration parameter
1173\emph{System\_Templates\_Path}.
1174
1175Also worth noting is that the \emph{Yolk.Not\_Found.Generate} function
1176is used as the default callback in the demo application. This means
1177that all requested resources that doesn't match a registered dispatcher,
1178is served by \emph{Yolk.Not\_Found.Generate} ie. a 404 is returned.
1179See the \emph{demo/src/my\_handlers.adb} file for more information.
1180
1181
1182\section{Yolk.Process\_Control}
1183
1184With \emph{Yolk.Process\_Control} you get the ability to control your
1185application using the SIGINT, SIGPWR and SIGTERM signals. If you give
1186your Yolk application the \emph{--pid-file} commandline argument when
1187starting it, \emph{Yolk.Process\_Control} will create a PID file on
1188the given location, if it is allowed to do so. This PID file will
1189also be deleted when the application terminates. Note that the \emph{extras/rc.yolk}
1190script handles all this transparently.
1191
1192
1193\subsection{Exceptions}
1194
1195These are:
1196\begin{itemize}
1197\item \emph{Cannot\_Create\_PID\_File}. Is raised if the \emph{PID\_File}
1198cannot be created, eg. if the application lacks permissions to write
1199to the directory where the \emph{PID\_File} is located.
1200\item \emph{Cannot\_Delete\_PID\_File}. Is raised if the \emph{PID\_file}
1201cannot be deleted, eg. if the application lacks permissions to write
1202to the directory where the \emph{PID\_File} is located, or to the
1203\emph{PID\_File} itself.
1204\item \emph{PID\_File\_Exists}. Is raised when the \emph{PID\_File} already
1205exists, ie. the application is already running or it was shutdown
1206incorrectly.
1207\end{itemize}
1208
1209\subsection{Using Yolk.Process\_Control}
1210
1211When you use the \emph{Yolk.Process\_Control} package the \emph{Unreserve\_All\_Interrupts}
1212pragma is used. This means that depending on the compiler used one
1213or more interrupt signals may be affected. In the case of the GNAT
1214compiler, this is specifically mentioned in the source of the \emph{Ada.Interrupts.Names}
1215package:
1216\begin{quote}
1217-- The pragma Unreserve\_All\_Interrupts affects the following signal(s):
1218
1219-- SIGINT: made available for Ada handler
1220\end{quote}
1221Since neither SIGPWR or SIGTERM are reserved by the compiler, the
1222\emph{Yolk.Process\_Control} package is able to assume control of
1223these signals. You can read more about the \href{http://gcc.gnu.org/onlinedocs/gnat_rm/Pragma-Unreserve_005fAll_005fInterrupts.html}{pragma Unreserve\_{}All\_{}Interrupts here}.
1224If you compile Yolk with a different compiler than GNAT, then please
1225check if one of the affected signals are reserved.
1226
1227There are two procedures in the \emph{Yolk.Process\_Control} package:
1228
1229\begin{minipage}[t]{1\columnwidth}%
1230\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
1231procedure Stop;
1232
1233procedure Wait;
1234\end{lstlisting}
1235%
1236\end{minipage}
1237
1238When you call the \emph{Wait} procedure, you basically hang there
1239until
1240\begin{enumerate}
1241\item The \emph{Stop} procedure is called
1242\item The application receives a SIGINT, SIGPWR or SIGTERM signal
1243\end{enumerate}
1244This is quite handy for applications, that need some sort of loop
1245to keep them from terminating. You can see an example on how this
1246can be done in the \emph{demo/src/yolk\_demo.adb} file.
1247
1248When \emph{Wait} is called, subsequent calls to \emph{Wait} are ignored,
1249unless a call to \emph{Stop} has been made or the application has
1250received one of the SIGINT, SIGPWR or SIGTERM signals. So it's perfectly
1251valid to do:
1252
1253\begin{minipage}[t]{1\columnwidth}%
1254\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
1255Wait;
1256--  Stop called from somewhere in the app
1257--  Do something...
1258Wait;
1259--  The app receives a SIGINT signal
1260--  Do something...
1261Wait;
1262\end{lstlisting}
1263%
1264\end{minipage}
1265
1266Whether or not this is actually useful I don't know, but it is possible.
1267
1268
1269\section{Yolk.Process\_Owner}
1270
1271When it is necessary to change the owner of a process, the \emph{Yolk.Process\_Owner}
1272package is the solution. Obviously this can also be done when starting
1273the application, using various shell tricks, but I find it it much
1274cleaner to just let the application handle it by itself.
1275
1276
1277\subsection{Exceptions}
1278
1279There's only one:
1280\begin{enumerate}
1281\item \emph{Username\_Does\_Not\_Exist}. This is raised if the given username
1282doesn't exist on the system.
1283\end{enumerate}
1284
1285\subsection{Using Yolk.Process\_Owner}
1286
1287There's only a single procedure in this package and its specification
1288looks like this:
1289
1290\begin{minipage}[t]{1\columnwidth}%
1291\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
1292procedure Set_User      
1293  (Username : in String);    
1294  --  Set the process owner to Username.
1295\end{lstlisting}
1296%
1297\end{minipage}
1298
1299Please note that when changing the user ID of the application with
1300\emph{Set\_User}, the group ID is changed to the first group the given
1301user is a member of.
1302
1303Usage is as simple as expected:
1304
1305\begin{minipage}[t]{1\columnwidth}%
1306\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
1307declare
1308begin
1309   Set_User (Username => "billybob");
1310exception
1311   when Username_Does_Not_Exist =>
1312      --  User is missing. Do something!
1313end;
1314\end{lstlisting}
1315%
1316\end{minipage}
1317
1318In the file \emph{demo/src/yolk\_demo.adb} you'll find that \emph{Yolk.Process\_Owner.Set\_User}
1319is used in conjunction with the \emph{Yolk.Configuration.Yolk\_User}
1320parameter.
1321
1322
1323\section{Yolk.Server}
1324
1325This is a convenience package to handle creating, starting and stopping
1326an AWS HTTP server. The biggest drawback to this package is that it
1327can only create and manage \emph{one} AWS server.
1328
1329Note a potential manual operation when using the \emph{Yolk.Server
1330}package : Setting the \emph{Cache-Control} header. This can become
1331necessary if you
1332\begin{enumerate}
1333\item use \emph{Yolk.Server} to create and start your AWS server AND
1334\item use the \emph{Yolk.Handlers} package to register dispatchers for static
1335content AND
1336\item have the \emph{Compress\_Static\_Content} configuration parameter
1337set to \emph{True }AND
1338\item aren't content with the default \emph{Cache-Control} header
1339\end{enumerate}
1340In that case you can use the \emph{Yolk.Static\_Content.Set\_Cache\_Options}
1341procedure to work your own magic on the \emph{Cache-Control} header
1342sent to clients requesting static content. See the Yolk.Static\_Content
1343chapter for more information.
1344
1345
1346\subsection{Yolk.Server.Create}
1347
1348Creating a server is done by calling the \emph{Create} function. This
1349function accepts one parameter that should be fairly self-explanatory.
1350
1351\begin{minipage}[t]{1\columnwidth}%
1352\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
1353type HTTP is tagged limited private;
1354
1355function Create
1356  (Unexpected : in AWS.Exceptions.Unexpected_Exception_Handler)       
1357   return HTTP;    
1358\end{lstlisting}
1359%
1360\end{minipage}
1361
1362
1363\subsection{Yolk.Server.Start}
1364
1365\begin{minipage}[t]{1\columnwidth}%
1366\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em]
1367procedure Start 
1368  (WS          : in out HTTP;
1369   Dispatchers : in     AWS.Dispatchers.Handler'Class);
1370\end{lstlisting}
1371%
1372\end{minipage}
1373
1374This does as expected: Starts the server with\emph{ Dispatchers.}
1375
1376When calling \emph{Start} several things happen:
1377\begin{enumerate}
1378\item If the configuration parameter \emph{Load\_MIME\_Types\_File} is \emph{True}
1379then the MIME types file given in \emph{MIME\_Types\_File} is loaded
1380into AWS. 
1381\item If the configuration parameter \emph{Start\_WebSocket\_Servers} is
1382\emph{True} then the AWS WebSocket servers are started.
1383\item \emph{Yolk.Static\_Content.Static\_Content\_Cache\_Setup} is called
1384with its default parameters if the configuration parameter \emph{Compress\_Static\_Content}
1385is \emph{True}.
1386\item If session support is turned on for the server and the \emph{Session\_Data\_File}
1387exists, then the session data is loaded from this file.
1388\item The \emph{Yolk.Log.AWS\_Access\_Log\_Writer} procedure is registered
1389to handle all AWS access log data if the configuration parameter \emph{AWS\_Access\_Log\_Activate}
1390is \emph{True} .
1391\item The \emph{Yolk.Log.AWS\_Error\_Log\_Writer} procedure is registered
1392to handle all AWS error log data if the configuration parameter \emph{AWS\_Error\_Log\_Activate}
1393is \emph{True} .
1394\end{enumerate}
1395
1396\subsection{Yolk.Server.Stop}
1397
1398\begin{minipage}[t]{1\columnwidth}%
1399\begin{lstlisting}[basicstyle={\small\sffamily},frame=tblr,language=Ada,sho…

Large files files are truncated, but you can click here to view the full file