/docs/yolk.lyx
Unknown | 7590 lines | 5787 code | 1803 blank | 0 comment | 0 complexity | 8005ac7db6ca7f09b6666c4d96179f72 MD5 | raw file
Possible License(s): AGPL-1.0
- #LyX 2.0 created this file. For more info see http://www.lyx.org/
- \lyxformat 413
- \begin_document
- \begin_header
- \textclass article
- \use_default_options true
- \maintain_unincluded_children false
- \language english
- \language_package default
- \inputencoding auto
- \fontencoding global
- \font_roman default
- \font_sans helvet
- \font_typewriter default
- \font_default_family sfdefault
- \use_non_tex_fonts false
- \font_sc false
- \font_osf false
- \font_sf_scale 100
- \font_tt_scale 100
- \graphics default
- \default_output_format default
- \output_sync 0
- \bibtex_command default
- \index_command default
- \paperfontsize 12
- \spacing single
- \use_hyperref false
- \papersize a4paper
- \use_geometry true
- \use_amsmath 1
- \use_esint 1
- \use_mhchem 1
- \use_mathdots 1
- \cite_engine basic
- \use_bibtopic false
- \use_indices false
- \paperorientation portrait
- \suppress_date false
- \use_refstyle 0
- \index Index
- \shortcut idx
- \color #008000
- \end_index
- \leftmargin 2cm
- \topmargin 2cm
- \rightmargin 2cm
- \bottommargin 2cm
- \secnumdepth 3
- \tocdepth 3
- \paragraph_separation skip
- \defskip medskip
- \quotes_language english
- \papercolumns 1
- \papersides 1
- \paperpagestyle default
- \tracking_changes false
- \output_changes false
- \html_math_output 0
- \html_css_as_file 0
- \html_be_strict false
- \end_header
- \begin_body
- \begin_layout Title
- Yolk Manual
- \end_layout
- \begin_layout Date
- Revised December 11th.
- 2012
- \end_layout
- \begin_layout Standard
- \begin_inset Newpage newpage
- \end_inset
- \end_layout
- \begin_layout Standard
- \begin_inset CommandInset toc
- LatexCommand tableofcontents
- \end_inset
- \end_layout
- \begin_layout Standard
- \begin_inset Newpage newpage
- \end_inset
- \end_layout
- \begin_layout Part
- General Information
- \end_layout
- \begin_layout Section
- Copyright and License
- \end_layout
- \begin_layout Standard
- This document is copyright (C) 2010-, Thomas Løcke.
- You may copy this document, in whole or in part, in any form or by any
- means, as is or with alterations, provided that (1) alterations are clearly
- marked as alterations and (2) this copyright notice is included unmodified
- in any copy.
- \end_layout
- \begin_layout Standard
- Yolk is GPLv3 software.
- You should have received a copy of the GNU General Public License and a
- copy of the GCC Runtime Library Exception along with this program; see
- the files COPYING3 and COPYING.RUNTIME respectively.
- If not, see
- \begin_inset CommandInset href
- LatexCommand href
- name "http://www.gnu.org/licenses/"
- target "http://www.gnu.org/licenses/"
- \end_inset
- .
-
- \end_layout
- \begin_layout Section
- What is Yolk?
- \end_layout
- \begin_layout Standard
- Yolk is a collection of packages that aim to help build solid web-applications
- using Ada.
- Yolk itself doesn't do a whole lot that can't be accomplished simply by
- using
- \begin_inset CommandInset href
- LatexCommand href
- name "AWS"
- target "http://libre.adacore.com/libre/tools/aws/"
- \end_inset
- and the
- \begin_inset CommandInset href
- LatexCommand href
- name "GNAT Component Collection (GNATcoll)"
- target "http://libre.adacore.com/libre/tools/gnat-component-collection/"
- \end_inset
- , but it does make the job of building complete web-applications a bit simpler.
- Things like changing user for the running application, catching POSIX signals
- such as SIGKILL, sending log data to syslogd, adding basic static content
- handlers, creating and starting/stopping an AWS powered HTTP server and
- building Atom syndication XML are all made a bit easier with Yolk.
- \end_layout
- \begin_layout Standard
- A Yolk application is in reality an AWS application, with some sugar added,
- so you're not really building a Yolk web-application, as much as you're
- building an AWS web-application.
- What I'm getting at, is that you need to understand how to use AWS, in
- order for Yolk to make any kind of sense.
- What you get when using Yolk is the little things that AWS does not readily
- provide.
- \end_layout
- \begin_layout Subsection
- The Yolk demo application
- \end_layout
- \begin_layout Standard
- Reading this manual will of course (I hope!) help you understand how to
- use Yolk, but please consider taking a closer look at the Yolk demo application
- to get a feel for how Yolk is actually used.
- The demo is heavily commented, so it should be fairly easy to understand
- what's going on.
- The demo application is also very suitable as a foundation for other AWS/Yolk
- applications.
- \end_layout
- \begin_layout Standard
- It is much easier to show how to use Yolk, than it is to write down all
- possible usage scenarios.
- With the combination of this manual, the Yolk source files and the demo
- application, you should be able to make full use of the Yolk packages in
- your own applications.
- \end_layout
- \begin_layout Subsection
- The source code
- \end_layout
- \begin_layout Standard
- The Yolk source code is the best documentation there is.
- This document is never going to be as comprehensive as the actual source,
- so I'll strongly suggest having the source code available as you read this
- document.
- What you will find in this document are short descriptions of what a package
- is meant to do and perhaps small usage examples, not a complete rundown
- of every type and procedure in a package.
- \end_layout
- \begin_layout Subsection
- Building and installing Yolk
- \end_layout
- \begin_layout Standard
- See the README and INSTALL files.
- These are found in the Yolk root directory.
- \end_layout
- \begin_layout Subsection
- The files Yolk depend upon
- \end_layout
- \begin_layout Standard
- When you read this document and the Yolk source code, you'll notice that
- quite a few packages depend on various files being available at specified
- locations.
- This is for example the case with the
- \emph on
- Yolk.Whoops
- \emph default
- package that expects its template file to be found at the path
- \emph on
- templates/system/500.tmpl
- \end_layout
- \begin_layout Standard
- All such
- \begin_inset Quotes eld
- \end_inset
- dependencies
- \begin_inset Quotes erd
- \end_inset
- will of course be noted accordingly as we go along, but instead of forgetting
- one or more in your own application, I'd much rather encourage using the
- demo application as a foundation for your own applications, since all these
- fixed paths and files has been properly added to the demo.
- \end_layout
- \begin_layout Standard
- I also recommend compiling and running the demo, to make sure your Yolk
- install is working as intended.
- Just read the
- \emph on
- demo/README
- \emph default
- and
- \emph on
- demo/INSTALL
- \emph default
- files for instructions on how to get it up and running.
- \end_layout
- \begin_layout Subsection
- The Yolk packages naming
- \end_layout
- \begin_layout Standard
- The Yolk packages are pretty diverse, ranging from process control to sending
- email.
- I've tried naming them as sensibly as possible, in the hope that the package
- names alone give away their function.
- If I've failed, well, you're just going to have to refer to this document
- or take a look at the source for yourself.
- \end_layout
- \begin_layout Standard
- \begin_inset Newpage newpage
- \end_inset
- \end_layout
- \begin_layout Part
- The Yolk Packages
- \end_layout
- \begin_layout Section
- Yolk
- \end_layout
- \begin_layout Standard
- The Yolk main package currently only contain only a few things: The Yolk
-
- \emph on
- Version
- \emph default
- string, a
- \emph on
- Config_File
- \emph default
- function to get the location of the configuration file and a
- \emph on
- PID_File
- \emph default
- function to get the location of the PID file.
- These are used in a few places, for example in the
- \emph on
- directory.tmpl
- \emph default
- template file (the version string), in the
- \emph on
- Yolk.Configuration
- \emph default
- package (the
- \emph on
- Config_File
- \emph default
- function) and in the
- \emph on
- Yolk.Process_Control
- \emph default
- package (the
- \emph on
- PID_File
- \emph default
- function).
- \end_layout
- \begin_layout Standard
- All Yolk applications accepts two commandline arguments:
- \end_layout
- \begin_layout Itemize
- \emph on
- --yolk-config-file
- \emph default
- : Defines the location of the configuration file.
- If empty or not set, then use the default location
- \emph on
- configuration/config.ini
- \emph default
- .
- \end_layout
- \begin_layout Itemize
- \emph on
- --pid-file
- \emph default
- : Defines the location of the PID file.
- If empty or not set, then don't write a PID file.
- Note that if you use the
- \emph on
- extras/rc.yolk
- \emph default
- script to control your application, then this is handled for you transparently.
- \end_layout
- \begin_layout Section
- Yolk.Cache.Discrete_Keys
- \end_layout
- \begin_layout Standard
- If a piece of data doesn't change very often and it is expensive to build,
- then caching it might be worthwhile.
- Instead of going to a file or database on every hit, you simply go to the
- cache and grab the latest version from there.
- This is
- \series bold
- \emph on
- very
- \series default
- \emph default
- fast, at the cost of some memory.
- \end_layout
- \begin_layout Standard
- If you know exactly what you want to cache, the
- \emph on
- Yolk.Cache.Discrete_Keys
- \emph default
- package might be just what you need.
- \end_layout
- \begin_layout Subsection
- The generic formal parameters
- \end_layout
- \begin_layout Standard
- These are:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- generic
- \end_layout
- \begin_layout Plain Layout
- type Key_Type is (<>);
- \end_layout
- \begin_layout Plain Layout
- type Element_Type is private;
- \end_layout
- \begin_layout Plain Layout
- Max_Element_Age : Duration := 3600.0;
- \end_layout
- \begin_layout Plain Layout
- package Yolk.Cache.Discrete_Keys is
- \end_layout
- \begin_layout Plain Layout
- ...
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- The
- \emph on
- Max_Element_Age
- \emph default
- defaults to one hour.
- You should obviously set this to whatever suits your needs.
- This timer is used for all content in the cache.
- You cannot set this individually for each element.
- \end_layout
- \begin_layout Subsection
- Instantiation
- \end_layout
- \begin_layout Standard
- If for example we have two different sets of data (Foo and Bar) that are
- expensive to build, we can instantiate a
- \emph on
- Discrete_Keys
- \emph default
- package to handle this:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- type Cache_Keys is (Foo, Bar);
- \end_layout
- \begin_layout Plain Layout
- package My_Cache is new Yolk.Cache.Discrete_Keys
- \end_layout
- \begin_layout Plain Layout
- (Key_Type => Cache_Keys,
- \end_layout
- \begin_layout Plain Layout
- Element_Type => Unbounded_String);
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- And that is all.
- We now have a
- \emph on
- My_Cache
- \emph default
- object that can hold two objects:
- \emph on
- Foo
- \emph default
- and
- \emph on
- Bar
- \emph default
- .
- These are of the type
- \emph on
- Unbounded_String
- \emph default
- and they have a
- \emph on
- Max_Element_Age
- \emph default
- of 3600.0 seconds.
- \end_layout
- \begin_layout Subsection
- Writing to the cache
- \end_layout
- \begin_layout Standard
- Before we can read something from the cache, we must first write something
- to it:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- declare
- \end_layout
- \begin_layout Plain Layout
- Foo_Value : Unbounded_String := To_Unbounded_String ("Foo");
- \end_layout
- \begin_layout Plain Layout
- begin
- \end_layout
- \begin_layout Plain Layout
- My_Cache.Write (Key => Foo,
- \end_layout
- \begin_layout Plain Layout
- Value => Foo_Value);
- \end_layout
- \begin_layout Plain Layout
- end;
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- That is all it takes:
- \begin_inset Quotes eld
- \end_inset
- Foo
- \begin_inset Quotes erd
- \end_inset
- is now safely tucked away in the
- \emph on
- My_Cache
- \emph default
- object, and will be so for 3600.0 seconds.
- Calling
- \emph on
- Write
- \emph default
- with the
- \emph on
- Foo
- \emph default
- key will always overwrite earlier written
- \emph on
- Foo
- \emph default
- elements, no matter their age.
- \end_layout
- \begin_layout Subsection
- Reading from the cache
- \end_layout
- \begin_layout Standard
- A cache obviously only makes sense if you intend to read from it.
- In our case we want to get our hands on the previously written
- \begin_inset Quotes eld
- \end_inset
- Foo
- \begin_inset Quotes erd
- \end_inset
- value:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- declare
- \end_layout
- \begin_layout Plain Layout
- Valid : Boolean := False;
- \end_layout
- \begin_layout Plain Layout
- Value : Unbounded_String;
- \end_layout
- \begin_layout Plain Layout
- begin
- \end_layout
- \begin_layout Plain Layout
- My_Cache.Read (Key => Foo,
- \end_layout
- \begin_layout Plain Layout
- Is_Valid => Valid,
- \end_layout
- \begin_layout Plain Layout
- Value => Value);
- \end_layout
- \begin_layout Plain Layout
- if Valid then
- \end_layout
- \begin_layout Plain Layout
- -- do something interesting with the data
- \end_layout
- \begin_layout Plain Layout
- else
- \end_layout
- \begin_layout Plain Layout
- -- the Foo data is invalid.
- \end_layout
- \begin_layout Plain Layout
- end if;
- \end_layout
- \begin_layout Plain Layout
- end;
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- In order for an element to be valid (the
- \emph on
- Is_Valid
- \emph default
- parameter is true), it must:
- \end_layout
- \begin_layout Enumerate
- have been added to the cache in the first place
- \end_layout
- \begin_layout Enumerate
- be younger than
- \emph on
- Max_Element_Age
- \end_layout
- \begin_layout Standard
- If
- \emph on
- Is_Valid
- \emph default
- is
- \emph on
- False
- \emph default
- , then
- \emph on
- Value
- \emph default
- is undefined.
- Note that if
- \emph on
- Is_Valid
- \emph default
- is
- \emph on
- False
- \emph default
- then
- \emph on
- Key
- \emph default
- is removed from the cache, if it exists.
- \end_layout
- \begin_layout Subsection
- Checking if a key is valid
- \end_layout
- \begin_layout Standard
- If you need to check whether a specific key exists in the cache and is valid,
- then you must use the
- \emph on
- Is_Valid
- \emph default
- function.
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- if My_Cache.Is_Valid (Foo) then
- \end_layout
- \begin_layout Plain Layout
- -- Foo is good!
- \end_layout
- \begin_layout Plain Layout
- else
- \end_layout
- \begin_layout Plain Layout
- -- Foo is bad!
- \end_layout
- \begin_layout Plain Layout
- end if;
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- This follows the same rules as the
- \emph on
- Is_Valid
- \emph default
- parameter for the
- \emph on
- Read
- \emph default
- procedure.
- \end_layout
- \begin_layout Subsection
- Clearing keys and the entire cache
- \end_layout
- \begin_layout Standard
- For clearing of keys and the entire cache we have, naturally, two
- \emph on
- Clear
- \emph default
- procedures:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- -- First we clear the Foo key
- \end_layout
- \begin_layout Plain Layout
- My_Cache.Clear (Key => Foo);
- \end_layout
- \begin_layout Plain Layout
- \end_layout
- \begin_layout Plain Layout
- -- And then we clear the entire cache
- \end_layout
- \begin_layout Plain Layout
- My_Cache.Clear;
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- And that's all it takes.
- \end_layout
- \begin_layout Subsection
- Cleanup - Getting rid of stale elements
- \end_layout
- \begin_layout Standard
- Calling Cleanup will delete all stale elements from the cache:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- My_Cache.Cleanup;
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- Note that this is potentially a very expensive operation if the cache is
- large, as the entire cache is iterated and every element tested for its
- age.
- Use with care.
- \end_layout
- \begin_layout Section
- Yolk.Cache.String_Keys
- \end_layout
- \begin_layout Standard
- This package is almost similar to the
- \emph on
- Yolk.Cache.Discrete_Keys
- \emph default
- package.
- The biggest difference is that where the
- \emph on
- Discrete_Keys
- \emph default
- cache package requires that you define a type for the keys, this package
- use regular
- \emph on
- String
- \emph default
- as keys.
- \end_layout
- \begin_layout Standard
- The implications of this difference between the two cache packages are subtle.
- Both have the same
- \emph on
- Read
- \emph default
- ,
- \emph on
- Write
- \emph default
- ,
- \emph on
- Is_Valid
- \emph default
- and
- \emph on
- Clear
- \emph default
- procedures and functions, so in that sense the two packages are the same.
- The biggest difference lies in the available generic formal parameters
- and the functionality of the
- \emph on
- Cleanup
- \emph default
- procedure.
- \end_layout
- \begin_layout Subsection
- The generic formal parameters
- \end_layout
- \begin_layout Standard
- These are:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- generic
- \end_layout
- \begin_layout Plain Layout
- type Element_Type is private;
- \end_layout
- \begin_layout Plain Layout
- Cleanup_Size : Positive := 200;
- \end_layout
- \begin_layout Plain Layout
- Cleanup_On_Write : Boolean := True;
- \end_layout
- \begin_layout Plain Layout
- Max_Element_Age : Duration := 3600.0;
- \end_layout
- \begin_layout Plain Layout
- Reserved_Capacity : Positive := 100;
- \end_layout
- \begin_layout Plain Layout
- package Yolk.Cache.Discrete_Keys is
- \end_layout
- \begin_layout Plain Layout
- ...
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- When the amount of elements in the cache >=
- \emph on
- Cleanup_Size
- \emph default
- , then the
- \emph on
- Cleanup
- \emph default
- procedure is called by
- \emph on
- Write
- \emph default
- , if
- \emph on
- Cleanup_On_Write
- \emph default
- is set to Boolean
- \emph on
- True
- \emph default
- .
-
- \emph on
- Cleanup_Size
- \emph default
- is a sort of failsafe for this cache package.
- Since we can't know for sure what is being added (we don't know the keys
- beforehand), we need to make sure it doesn't gobble up all available resources.
- Set this number high enough that it'll never tricker under normal circumstances
- , but low enough that it'll prevent resource exhaustion in case of errors.
- \end_layout
- \begin_layout Standard
- The
- \emph on
- Max_Element_Age
- \emph default
- defaults to one hour.
- You should obviously set this to whatever suits your needs.
- This timer is used for all content in the cache.
- You cannot set this individually for each element.
- \end_layout
- \begin_layout Standard
- \emph on
- Reserved_Capacity
- \emph default
- should be set as close as possible to the expected final size of the cache.
- If your best guestimate is 200 elements in the cache, then set this to
- 200.
- Note that this setting has no bearing on the actual size of the cache.
- The cache will happily grow beyond the
- \emph on
- Reserved_Capacity
- \emph default
- value.
- \end_layout
- \begin_layout Subsection
- Instantiation
- \end_layout
- \begin_layout Standard
- Instantiating
- \emph on
- String_Keys
- \emph default
- is done like this:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- package My_Cache is new Yolk.Cache.String_Keys
- \end_layout
- \begin_layout Plain Layout
- (Element_Type => Unbounded_String,
- \end_layout
- \begin_layout Plain Layout
- Reserved_Capacity => 200);
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- And that is all.
- We now have a
- \emph on
- My_Cache
- \emph default
- object that can hold objects of the type
- \emph on
- Unbounded_String
- \emph default
- , all of which have a
- \emph on
- Max_Element_Age
- \emph default
- of 3600.0 seconds.
- Also we've told the cache to set aside at least 200 positions for content.
- \end_layout
- \begin_layout Subsection
- Writing to the cache
- \end_layout
- \begin_layout Standard
- Before we can read something from the cache, we must first write something
- to it:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- declare
- \end_layout
- \begin_layout Plain Layout
- Value : Unbounded_String := To_Unbounded_String ("42");
- \end_layout
- \begin_layout Plain Layout
- begin
- \end_layout
- \begin_layout Plain Layout
- My_Cache.Write (Key => "Foo",
- \end_layout
- \begin_layout Plain Layout
- Value => Value);
- \end_layout
- \begin_layout Plain Layout
- end;
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- \begin_inset Quotes eld
- \end_inset
- 42
- \begin_inset Quotes erd
- \end_inset
- is now safely tucked away in the
- \emph on
- My_Cache
- \emph default
- object under the key
- \begin_inset Quotes eld
- \end_inset
- Foo
- \begin_inset Quotes erd
- \end_inset
- , and will be so for 3600.0 seconds.
- Calling
- \emph on
- Write
- \emph default
- with the
- \begin_inset Quotes eld
- \end_inset
- Foo
- \begin_inset Quotes erd
- \end_inset
- \emph on
-
- \emph default
- String will always overwrite earlier written
- \begin_inset Quotes eld
- \end_inset
- Foo
- \begin_inset Quotes erd
- \end_inset
- elements, no matter their age.
- \end_layout
- \begin_layout Subsection
- Reading from the cache
- \end_layout
- \begin_layout Standard
- A cache obviously only makes sense if you intend to read from it.
- In our case we want to get our hands on the previously written
- \begin_inset Quotes eld
- \end_inset
- Foo
- \begin_inset Quotes erd
- \end_inset
- value:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- declare
- \end_layout
- \begin_layout Plain Layout
- Valid : Boolean := False;
- \end_layout
- \begin_layout Plain Layout
- Value : Unbounded_String;
- \end_layout
- \begin_layout Plain Layout
- begin
- \end_layout
- \begin_layout Plain Layout
- My_Cache.Read (Key => "Foo",
- \end_layout
- \begin_layout Plain Layout
- Is_Valid => Valid,
- \end_layout
- \begin_layout Plain Layout
- Value => Value);
- \end_layout
- \begin_layout Plain Layout
- if Valid then
- \end_layout
- \begin_layout Plain Layout
- -- do something interesting with the data
- \end_layout
- \begin_layout Plain Layout
- else
- \end_layout
- \begin_layout Plain Layout
- -- the Foo data is invalid.
- \end_layout
- \begin_layout Plain Layout
- end if;
- \end_layout
- \begin_layout Plain Layout
- end;
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- In order for an element to be valid (the
- \emph on
- Is_Valid
- \emph default
- parameter is true), it must:
- \end_layout
- \begin_layout Enumerate
- have been added to the cache in the first place
- \end_layout
- \begin_layout Enumerate
- be younger than
- \emph on
- Max_Element_Age
- \end_layout
- \begin_layout Standard
- If
- \emph on
- Is_Valid
- \emph default
- is
- \emph on
- False
- \emph default
- , then
- \emph on
- Value
- \emph default
- contains undefined garbage.
- Note that if
- \emph on
- Is_Valid
- \emph default
- is
- \emph on
- False
- \emph default
- then
- \emph on
- Key
- \emph default
- is removed from the cache, if it exists.
- \end_layout
- \begin_layout Subsection
- Checking if a key is valid
- \end_layout
- \begin_layout Standard
- If you need to check whether a specific key exists in the cache and is valid,
- then you need to use the
- \emph on
- Is_Valid
- \emph default
- function.
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- if My_Cache.Is_Valid ("Foo") then
- \end_layout
- \begin_layout Plain Layout
- -- Foo is good!
- \end_layout
- \begin_layout Plain Layout
- else
- \end_layout
- \begin_layout Plain Layout
- -- Foo is bad!
- \end_layout
- \begin_layout Plain Layout
- end if;
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- This follows the same rules as the
- \emph on
- Is_Valid
- \emph default
- parameter for the
- \emph on
- Read
- \emph default
- procedure.
- \end_layout
- \begin_layout Subsection
- Clearing keys and the entire cache
- \end_layout
- \begin_layout Standard
- For clearing of keys and the entire cache we have, naturally, two
- \emph on
- Clear
- \emph default
- procedures:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- -- First we clear the Foo key
- \end_layout
- \begin_layout Plain Layout
- My_Cache.Clear (Key => "Foo");
- \end_layout
- \begin_layout Plain Layout
- \end_layout
- \begin_layout Plain Layout
- -- And then we clear the entire cache
- \end_layout
- \begin_layout Plain Layout
- My_Cache.Clear;
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Subsection
- How much is in there?
- \end_layout
- \begin_layout Standard
- With the
- \emph on
- Discrete_Keys
- \emph default
- cache we obviously always know the exact amount of keys available, since
- we've defined the keys ourselves.
- This is not the case with the
- \emph on
- String_Keys
- \emph default
- cache, where any
- \emph on
- String
- \emph default
- can be a key.
- If we need to know how many elements that are currently in the cache, we
- call the
- \emph on
- Length
- \emph default
- function:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- if My_Cache.Length > 1000 then
- \end_layout
- \begin_layout Plain Layout
- -- Woa! Lots of stuff in the cache..
- \end_layout
- \begin_layout Plain Layout
- end if;
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- Note that
- \emph on
- Length
- \emph default
- count both valid and invalid elements.
- \end_layout
- \begin_layout Subsection
- Cleanup - Keeping cache size in check
- \end_layout
- \begin_layout Standard
- if
- \emph on
- Cleanup_On_Write
- \emph default
- is
- \emph on
- True
- \emph default
- , then
- \emph on
- Cleanup
- \emph default
- is called by
- \emph on
- Write
- \emph default
- whenever the size of the cache reach
- \emph on
- Cleanup_Size
- \emph default
- .
- It is of course also possible to call it manually:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- if My_Cache.Length > 1000 then
- \end_layout
- \begin_layout Plain Layout
- My_Cache.Cleanup;
- \end_layout
- \begin_layout Plain Layout
- end if;
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- If you've set
- \emph on
- Cleanup_On_Write
- \emph default
- to Boolean
- \emph on
- False
- \emph default
- and the String keys are coming from outside sources, then you really should
- make sure you call
- \emph on
- Cleanup
- \emph default
- on a regular basis.
- \end_layout
- \begin_layout Section
- Yolk.Command_Line
- \end_layout
- \begin_layout Standard
- This package enables you to fetch the value of a given commandline parameter
- using the
- \emph on
- Get
- \emph default
- function:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- function Get
- \end_layout
- \begin_layout Plain Layout
- (Parameter : in String;
- \end_layout
- \begin_layout Plain Layout
- Default : in String := "")
- \end_layout
- \begin_layout Plain Layout
- return String;
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- If
- \emph on
- Parameter
- \emph default
- is found
- \emph on
- Get
- \emph default
- will return the value immediately following
- \emph on
- Parameter.
- \emph default
- If
- \emph on
- Parameter
- \emph default
- isn't found
- \emph on
- Default
- \emph default
- is returned.
-
- \end_layout
- \begin_layout Section
- Yolk.Config_File_Parser
- \end_layout
- \begin_layout Standard
- This package enables you to access KEY/VALUE pairs in configuration files
- that are written in the style:
- \end_layout
- \begin_layout LyX-Code
- # This is a comment
- \end_layout
- \begin_layout LyX-Code
- -- This is also a comment
- \end_layout
- \begin_layout LyX-Code
- KEY VALUE
- \end_layout
- \begin_layout Standard
- Keys are case-insensitive, so
- \emph on
- FOO
- \emph default
- ,
- \emph on
- foo
- \emph default
- and
- \emph on
- fOo
- \emph default
- are all the same.
- \emph on
-
- \emph default
- Blank lines and comments are ignored and so is pre/postfixed whitespace.
- It is not necessary to quote values that contain whitespace, to this:
- \end_layout
- \begin_layout LyX-Code
- KEY some value with whitespace
- \end_layout
- \begin_layout Standard
- is perfectly valid, and will return
- \begin_inset Quotes eld
- \end_inset
- \emph on
- some value with whitespace
- \emph default
- \begin_inset Quotes erd
- \end_inset
- when calling
- \emph on
- Get (KEY)
- \emph default
- .
- If VALUE is
- \emph on
- Boolean
- \emph default
-
- \emph on
- True
- \emph default
- or
- \emph on
- False
- \emph default
- (case-insensitive), then the KEY can be returned as a
- \emph on
- String
- \emph default
- or a
- \emph on
- Boolean
- \emph default
- , depending on the target type.
- If the target type does not match the VALUE and no sensible conversion
- can be made, then a
- \emph on
- Conversion_Error
- \emph default
- exception is raised.
- No dummy values are returned at any time.
- \end_layout
- \begin_layout Standard
- To clear a default value, simply add the key to the configuration file,
- with no value set.
- \end_layout
- \begin_layout Subsection
- The generic formal parameters
- \end_layout
- \begin_layout Standard
- These are:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- generic
- \end_layout
- \begin_layout Plain Layout
- use Ada.Strings.Unbounded;
- \end_layout
- \begin_layout Plain Layout
- type Key_Type is (<>);
- \end_layout
- \begin_layout Plain Layout
- type Defaults_Array_Type is array (Key_Type) of Unbounded_String;
- \end_layout
- \begin_layout Plain Layout
- Defaults : in Defaults_Array_Type;
- \end_layout
- \begin_layout Plain Layout
- Config_File : in String;
- \end_layout
- \begin_layout Plain Layout
- package Yolk.Config_File_Parser is
- \end_layout
- \begin_layout Plain Layout
- ...
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- \emph on
- Config_File
- \emph default
- is of course the name and location of the configuration file.
- \end_layout
- \begin_layout Subsection
- Exceptions
- \end_layout
- \begin_layout Standard
- There are 3 different exceptions that can be raised by the
- \emph on
- Yolk.Config_File_Parser
- \emph default
- package.
- These are:
- \end_layout
- \begin_layout Itemize
- \emph on
- Unknown_Key
- \emph default
- .
- This is raised if an unknown key has been found in the configuration file
- given when instantiating the package or when
- \emph on
- Load_File
- \emph default
- is called.
- \end_layout
- \begin_layout Itemize
- \emph on
- Cannot_Open_Config_File
- \emph default
- .
- This is raised when
- \emph on
- Config_File
- \emph default
- cannot be read.
- \end_layout
- \begin_layout Itemize
- \emph on
- Conversion_Error
- \emph default
- .
- This is raised when a value cannot be converted to the target type, ie.
- the value
- \begin_inset Quotes eld
- \end_inset
- 42
- \begin_inset Quotes erd
- \end_inset
- to a
- \emph on
- Boolean
- \emph default
- .
- \end_layout
- \begin_layout Subsection
- Instantiation
- \end_layout
- \begin_layout Standard
- \emph on
- Yolk.Config_File_Parser
- \emph default
- is a generic package, so in order to use it, you have to instantiate it,
- like this:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- package My_Configuration is
- \end_layout
- \begin_layout Plain Layout
- \end_layout
- \begin_layout Plain Layout
- type Keys is (Foo, Bar);
- \end_layout
- \begin_layout Plain Layout
- type Defaults_Array is array (Keys) of Unbounded_String;
- \end_layout
- \begin_layout Plain Layout
- \end_layout
- \begin_layout Plain Layout
- Default_Values : constant Defaults_Array :=
- \end_layout
- \begin_layout Plain Layout
- (Foo => To_Unbounded_String ("some foo"),
- \end_layout
- \begin_layout Plain Layout
- Bar => To_Unbounded_String ("some bar"));
- \end_layout
- \begin_layout Plain Layout
-
- \end_layout
- \begin_layout Plain Layout
- package Config is new Yolk.Config_File_Parser
- \end_layout
- \begin_layout Plain Layout
- (Key_Type => Keys,
- \end_layout
- \begin_layout Plain Layout
- Defaults_Array_Type => Defaults_Array,
- \end_layout
- \begin_layout Plain Layout
- Defaults => Default_Value,
- \end_layout
- \begin_layout Plain Layout
- Config_File => "config.ini");
- \end_layout
- \begin_layout Plain Layout
- \end_layout
- \begin_layout Plain Layout
- end My_Configuration;
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- Here we instantiate the
- \emph on
- Config
- \emph default
- package with
- \emph on
- config.ini
- \emph default
- as the configuration file.
- This means that KEY/VALUE pairs found in this file will overwrite the default
- values set in the
- \emph on
- Default_Values
- \emph default
- array.
- Setting a default value to
- \emph on
- Null_Unbounded_String
- \emph default
- means the value is empty.
- \end_layout
- \begin_layout Standard
- Note that the
- \emph on
- config.ini
- \emph default
- file does not have to contain all the valid keys.
- It is perfectly fine to only add those keys that have non-default values
- to the configuration file.
- \end_layout
- \begin_layout Subsection
- Re-loading configuration files
- \end_layout
- \begin_layout Standard
- With the
- \emph on
- Load_File
- \emph default
- procedure you can re-load a new configuration file into your
- \emph on
- Config
- \emph default
- package:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- My_Configuration.Config.Load_File ("new_config.ini");
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- Now the KEY/VALUE pairs of
- \emph on
- new_config.ini
- \emph default
- will overwrite the ones originally found in the
- \emph on
- config.ini
- \emph default
- file the package was instantiated with.
- You can do this as many times as you like.
- Note that you cannot change what KEY's are valid, so if the
- \emph on
- new_config.ini
- \emph default
- file contains unknown keys,
- \emph on
- Load_File
- \emph default
- will raise the
- \emph on
- Unknown_Key
- \emph default
- exception.
- \end_layout
- \begin_layout Subsection
- Getting values
- \end_layout
- \begin_layout Standard
- With instantiation and loading of configuration files out of the way, it
- is now time to get to the configuration values.
- To get the value of the
- \emph on
- Foo
- \emph default
- key, you do:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- My_Configuration.Config.Get (Foo);
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- There are Get functions for the following types:
- \end_layout
- \begin_layout Itemize
- \emph on
- Boolean
- \end_layout
- \begin_layout Itemize
- \emph on
- Duration
- \end_layout
- \begin_layout Itemize
- \emph on
- Float
- \end_layout
- \begin_layout Itemize
- \emph on
- Integer
- \end_layout
- \begin_layout Itemize
- \emph on
- String
- \end_layout
- \begin_layout Itemize
- \emph on
- Unbounded_String
- \end_layout
- \begin_layout Standard
- Empty keys simply return an empty
- \emph on
- String
- \emph default
- or a
- \emph on
- Null_Unbounded_String
- \emph default
- , depending on the target type.
- If a key is empty and the target type is not a
- \emph on
- String
- \emph default
- or an
- \emph on
- Unbounded_String
- \emph default
- , then the
- \emph on
- Conversion_Error
- \emph default
- exception is raised.
- \end_layout
- \begin_layout Subsection
- Checking if a KEY has a VALUE
- \end_layout
- \begin_layout Standard
- You can check if a key has a value with the
- \emph on
- Has_Value
- \emph default
- function:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- if Has_Value (Foo) then
- \end_layout
- \begin_layout Plain Layout
- Put_Line ("Foo has a value");
- \end_layout
- \begin_layout Plain Layout
- end if;
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- Basically all this function does is return
- \emph on
- Boolean
- \emph default
-
- \emph on
- True
- \emph default
- if the value of the given key is not a
- \emph on
- Null_Unbounded_String
- \emph default
- .
- \end_layout
- \begin_layout Section
- Yolk.Configuration
- \end_layout
- \begin_layout Standard
- This package is a bit of an oddball, as all it does is instantiate the
- \emph on
- Yolk.Config_File_Parser
- \emph default
- generic with the default AWS and Yolk configuration values.
- This is used by Yolk internally, but also by the AWS component of your
- application.
- The instantiation looks like this:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- package Config is new Config_File_Parser
- \end_layout
- \begin_layout Plain Layout
- (Key_Type => Keys,
- \end_layout
- \begin_layout Plain Layout
- Defaults_Array_Type => Defaults_Array,
- \end_layout
- \begin_layout Plain Layout
- Defaults => Default_Values,
- \end_layout
- \begin_layout Plain Layout
- Config_File => Config_File);
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- The
- \emph on
- Config_File
- \emph default
- function call return either the default Yolk configuration file (
- \emph on
- configuration/config.ini
- \emph default
- ) or a user specified configuration file given by the
- \emph on
- --yolk-config-file
- \emph default
- command line argument, so
- \emph on
-
- \emph default
- starting for example the Yolk demo like this:
- \end_layout
- \begin_layout LyX-Code
- ./yolk_demo --yolk-config-file /etc/yolk-config.ini
- \end_layout
- \begin_layout Standard
- will force the demo to look for the
- \emph on
- /etc/yolk-config.ini
- \emph default
- configuration file.
- \end_layout
- \begin_layout Standard
- There's a fully commented
- \emph on
- config.ini.dist
- \emph default
- file available in the
- \emph on
- extras/
- \emph default
- directory.
- I recommend taking a look at the Yolk demo application to see how the
- \emph on
- Yolk.Configuration
- \emph default
- package is used.
- \end_layout
- \begin_layout Subsection
- Get the AWS specific configuration settings
- \end_layout
- \begin_layout Standard
- On some occassions it might be necessary to get the AWS configuration object.
- This can easily be accomplished by calling the
- \emph on
- Get_AWS_Configuration
- \emph default
- function:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- AWS_Config : constant AWS.Config.Object :=
- \end_layout
- \begin_layout Plain Layout
- Yolk.Configuration.Get_AWS_Configuration;
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Section
- Yolk.Email
- \end_layout
- \begin_layout Standard
- Using
- \emph on
- Yolk.Email
- \emph default
- and the child package
- \emph on
- Yolk.Email.Composer
- \emph default
- you can build and send more or less any kind of email:
- \end_layout
- \begin_layout Itemize
- Plain text
- \end_layout
- \begin_layout Itemize
- Multipart/Alternative
- \end_layout
- \begin_layout Itemize
- Multipart/Mixed
- \end_layout
- \begin_layout Standard
- The package supports adding multiple SMTP servers, meaning you can add as
- many as you need, and the email will then be send via the first one that
- accepts it.
- \end_layout
- \begin_layout Standard
- The
- \emph on
- Yolk.Email
- \emph default
- package define 4 exceptions and 3 types.
- The facilities for actually constructing and sending the email are found
- in
- \emph on
- Yolk.Email.Composer
- \emph default
- .
- \end_layout
- \begin_layout Subsection
- Exceptions
- \end_layout
- \begin_layout Standard
- These are:
- \end_layout
- \begin_layout Itemize
- \emph on
- Attachment_File_Not_Found
- \emph default
- .
- Is raised if a file attachment is not found at the given path.
- \end_layout
- \begin_layout Itemize
- \emph on
- No_Address_Set
- \emph default
- .
- Is raised if the address component of a To, Reply-To, From, Bcc/Cc header
- is missing.
- \end_layout
- \begin_layout Itemize
- \emph on
- No_Sender_Set_With_Multiple_From
- \emph default
- .
- Is raised when an email contains multiple From headers but no Sender header,
- as per RFC-5322, 3.6.2.
- http://tools.ietf.org/html/rfc5322
- \end_layout
- \begin_layout Itemize
- \emph on
- No_SMTP_Host_Set
- \emph default
- .
- Is raised if the SMTP host list is empty, ie.
- no SMTP host has been set for sending the email.
- \end_layout
- \begin_layout Subsection
- The Yolk.Email types
- \end_layout
- \begin_layout Standard
- When using
- \emph on
- Yolk.Email.Composer
- \emph default
- to build and send emails, three types declared in
- \emph on
- Yolk.Email
- \emph default
- are central:
- \end_layout
- \begin_layout Enumerate
- \emph on
- Character_Set
- \end_layout
- \begin_layout Enumerate
- \emph on
- Recipient_Kind
- \end_layout
- \begin_layout Enumerate
- \emph on
- Structure
- \end_layout
- \begin_layout Standard
- The
- \emph on
- Character_Set
- \emph default
- type define what character set is used when data is added to an email
- \emph on
- Structure
- \emph default
- object.
- For example looking at the
- \emph on
- Yolk.Email.Composer.Add_From
- \emph default
- procedure, we see that the
- \emph on
- Charset
- \emph default
- parameter defaults to
- \emph on
- US_ASCII
- \emph default
- :
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- procedure Add_From
- \end_layout
- \begin_layout Plain Layout
- (ES : in out Structure;
- \end_layout
- \begin_layout Plain Layout
- Address : in String;
- \end_layout
- \begin_layout Plain Layout
- Name : in String := "";
- \end_layout
- \begin_layout Plain Layout
- Charset : in Character_Set := US_ASCII);
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- This does not mean that
- \emph on
- Yolk.Email.Composer.Add_From
- \emph default
- will encode
- \emph on
- Name
- \emph default
- as
- \emph on
- US_ASCII
- \emph default
- , instead it means that the data given in
- \emph on
- Name
- \emph default
- already is
- \emph on
- US_ASCII
- \emph default
- .
- So if
- \emph on
- Name
- \emph default
- had contained an ISO-8859-1 encoded
- \emph on
- String
- \emph default
- , then the call would've looked like this:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- declare
- \end_layout
- \begin_layout Plain Layout
- use Yolk.Email;
- \end_layout
- \begin_layout Plain Layout
- \end_layout
- \begin_layout Plain Layout
- Email : Structure;
- \end_layout
- \begin_layout Plain Layout
- begin
- \end_layout
- \begin_layout Plain Layout
- Composer.Add_From
- \end_layout
- \begin_layout Plain Layout
- (ES => Email,
- \end_layout
- \begin_layout Plain Layout
- Address => "alice@domain.tld",
- \end_layout
- \begin_layout Plain Layout
- Name => "Alice",
- \end_layout
- \begin_layout Plain Layout
- Charset => ISO_8859_1);
- \end_layout
- \begin_layout Plain Layout
- end;
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- In this case you will end up with a From header looking like this:
- \end_layout
- \begin_layout LyX-Code
- From: =?ISO-8859-1?Q?Alice?= <alice@domain.tld>
- \end_layout
- \begin_layout Standard
- So bear in mind that it is your responsibility to ensure that your data,
- and the
- \emph on
- Character_Set
- \emph default
- parameter match.
- \end_layout
- \begin_layout Standard
- The
- \emph on
- Recipient_Kind
- \emph default
- type define the kind of recipient that is being added to an email.
- If you've worked with email, these three should be familiar to you:
- \end_layout
- \begin_layout Enumerate
- \emph on
- Bcc
- \end_layout
- \begin_layout Enumerate
- \emph on
- Cc
- \end_layout
- \begin_layout Enumerate
- \emph on
- To
- \end_layout
- \begin_layout Standard
- When adding recipients to an email
- \emph on
- Structure
- \emph default
- the default is
- \emph on
- To
- \emph default
- , but since not all recipients are equal, you can change the kind of recipient
- to
- \emph on
- Bcc
- \emph default
- or
- \emph on
- Cc
- \emph default
- , according to your needs.
- \end_layout
- \begin_layout Standard
- The
- \emph on
- Structure
- \emph default
- type is at the core of it all.
- You declare an object to be of the
- \emph on
- Structure
- \emph default
- type, and then you use the
- \emph on
- Yolk.Email.Composer
- \emph default
- facilities to build and send the email.
- \end_layout
- \begin_layout Section
- Yolk.Email.Composer
- \end_layout
- \begin_layout Standard
- The actual tools for building and sending an email is found in this package.
- Here are tools for building emails from the ground up and there are a few
- convenience procedures if you just need to send a simple email with no
- bells or whistles.
- \end_layout
- \begin_layout Standard
- I'm not going to go through ever procedure in this package, instead I'll
- show an example on how to build an email from the ground up and how to
- use one of the convenience procedures.
- \end_layout
- \begin_layout Subsection
- Building and sending an email, the easy way
- \end_layout
- \begin_layout Standard
- There are two convenience procedures in
- \emph on
- Yolk.Email.Composer
- \emph default
- for sending emails without having to do a whole lot of work/thinking.
- They are both named
- \emph on
- Send
- \emph default
- and they look like this:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- procedure Send
- \end_layout
- \begin_layout Plain Layout
- (ES : in out Structure;
- \end_layout
- \begin_layout Plain Layout
- From_Address : in String;
- \end_layout
- \begin_layout Plain Layout
- From_Name : in String := "";
- \end_layout
- \begin_layout Plain Layout
- To_Address : in String;
- \end_layout
- \begin_layout Plain Layout
- To_Name : in String := "";
- \end_layout
- \begin_layout Plain Layout
- Subject : in String;
- \end_layout
- \begin_layout Plain Layout
- Text_Part : in String;
- \end_layout
- \begin_layout Plain Layout
- SMTP_Server : in String := "localhost";
- \end_layout
- \begin_layout Plain Layout
- SMTP_Port : in Positive := 25;
- \end_layout
- \begin_layout Plain Layout
- Charset : in Character_Set := US_ASCII);
- \end_layout
- \begin_layout Plain Layout
-
- \end_layout
- \begin_layout Plain Layout
- procedure Send
- \end_layout
- \begin_layout Plain Layout
- (ES : in out Structure;
- \end_layout
- \begin_layout Plain Layout
- From_Address : in String;
- \end_layout
- \begin_layout Plain Layout
- From_Name : in String := "";
- \end_layout
- \begin_layout Plain Layout
- To_Address : in String;
- \end_layout
- \begin_layout Plain Layout
- To_Name : in String := "";
- \end_layout
- \begin_layout Plain Layout
- Subject : in String;
- \end_layout
- \begin_layout Plain Layout
- Text_Part : in String;
- \end_layout
- \begin_layout Plain Layout
- HTML_Part : in String;
- \end_layout
- \begin_layout Plain Layout
- SMTP_Server : in String := "localhost";
- \end_layout
- \begin_layout Plain Layout
- SMTP_Port : in Positive := 25;
- \end_layout
- \begin_layout Plain Layout
- Charset : in Character_Set := US_ASCII);
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- As you can see, the only difference between these two is that the first
- one sends plain text emails, while the second one sends
- \emph on
- multipart/alternative
- \emph default
- with both plain text and HTML parts.
- Usage is as simple as:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- declare
- \end_layout
- \begin_layout Plain Layout
- use Yolk.Email;
- \end_layout
- \begin_layout Plain Layout
- \end_layout
- \begin_layout Plain Layout
- Email : Structure;
- \end_layout
- \begin_layout Plain Layout
- begin
- \end_layout
- \begin_layout Plain Layout
- Composer.Send (ES => Email,
- \end_layout
- \begin_layout Plain Layout
- From_Address => "alice@domain.tld",
- \end_layout
- \begin_layout Plain Layout
- From_Name => "Alice",
- \end_layout
- \begin_layout Plain Layout
- To_Address => "bob@domain.tld",
- \end_layout
- \begin_layout Plain Layout
- To_Name => "Bob",
- \end_layout
- \begin_layout Plain Layout
- Subject => "Is this thing on?",
- \end_layout
- \begin_layout Plain Layout
- Text_Part => "Hey you!",
- \end_layout
- \begin_layout Plain Layout
- Charset => ISO_8859_1);
- \end_layout
- \begin_layout Plain Layout
-
- \end_layout
- \begin_layout Plain Layout
- if Composer.Is_Send (Email) then
- \end_layout
- \begin_layout Plain Layout
- -- Success!
- \end_layout
- \begin_layout Plain Layout
- else
- \end_layout
- \begin_layout Plain Layout
- -- Failure!
- \end_layout
- \begin_layout Plain Layout
- end if;
- \end_layout
- \begin_layout Plain Layout
- end;
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- It is possible, and allowed, to call some of the various other procedures
- prior to calling one of the convenience procedures.
- If for example you want to add a custom header, it can be done like this:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- declare
- \end_layout
- \begin_layout Plain Layout
- use Yolk.Email;
- \end_layout
- \begin_layout Plain Layout
- \end_layout
- \begin_layout Plain Layout
- Email : Structure;
- \end_layout
- \begin_layout Plain Layout
- begin
- \end_layout
- \begin_layout Plain Layout
- Composer.Add_Custom_Header (ES => Email,
- \end_layout
- \begin_layout Plain Layout
- Name => "User-Agent",
- \end_layout
- \begin_layout Plain Layout
- Value => "My User Agent");
- \end_layout
- \begin_layout Plain Layout
- \end_layout
- \begin_layout Plain Layout
- Composer.Send (ES => Email,
- \end_layout
- \begin_layout Plain Layout
- From_Address => "alice@domain.tld",
- \end_layout
- \begin_layout Plain Layout
- From_Name => "Alice",
- \end_layout
- \begin_layout Plain Layout
- To_Address => "bob@domain.tld",
- \end_layout
- \begin_layout Plain Layout
- To_Name => "Bob",
- \end_layout
- \begin_layout Plain Layout
- Subject => "Is this thing on?",
- \end_layout
- \begin_layout Plain Layout
- Text_Part => "Hey you!",
- \end_layout
- \begin_layout Plain Layout
- Charset => ISO_8859_1);
- \end_layout
- \begin_layout Plain Layout
-
- \end_layout
- \begin_layout Plain Layout
- if Composer.Is_Send (Email) then
- \end_layout
- \begin_layout Plain Layout
- -- Success!
- \end_layout
- \begin_layout Plain Layout
- else
- \end_layout
- \begin_layout Plain Layout
- -- Failure!
- \end_layout
- \begin_layout Plain Layout
- end if;
- \end_layout
- \begin_layout Plain Layout
- end;
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- And with that, the header
- \emph on
- User-Agent:
- \emph default
- is now added to the email:
- \end_layout
- \begin_layout LyX-Code
- User-Agent: My User Agent
- \end_layout
- \begin_layout Standard
- It hardly gets any easier than that.
- Lets move on and see how the above is accomplished the hard way.
- \end_layout
- \begin_layout Subsection
- Building and sending email, the hard way
- \end_layout
- \begin_layout Standard
- It is possible to build an email from the ground up, which obviously allows
- for a more fine grained control over what is added.
- It is also a bit more complicated, but not much.
- Lets try and mimick the easy examples, the
- \begin_inset Quotes eld
- \end_inset
- hard
- \begin_inset Quotes erd
- \end_inset
- way:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- declare
- \end_layout
- \begin_layout Plain Layout
- use Yolk.Email;
- \end_layout
- \begin_layout Plain Layout
- \end_layout
- \begin_layout Plain Layout
- Email : Structure;
- \end_layout
- \begin_layout Plain Layout
- begin
- \end_layout
- \begin_layout Plain Layout
- Composer.Add_Custom_Header (ES => Email,
- \end_layout
- \begin_layout Plain Layout
- Name => "User-Agent",
- \end_layout
- \begin_layout Plain Layout
- Value => "My User Agent");
- \end_layout
- \begin_layout Plain Layout
- \end_layout
- \begin_layout Plain Layout
- Composer.Add_From (ES => Email,
- \end_layout
- \begin_layout Plain Layout
- Address => "alice@domain.tld",
- \end_layout
- \begin_layout Plain Layout
- Name => "Alice",
- \end_layout
- \begin_layout Plain Layout
- Charset => ISO_8859_1);
- \end_layout
- \begin_layout Plain Layout
- \end_layout
- \begin_layout Plain Layout
- Composer.Add_Recipient (ES => Email,
- \end_layout
- \begin_layout Plain Layout
- Address => "bob@domain.tld",
- \end_layout
- \begin_layout Plain Layout
- Name => "Bob");
- \end_layout
- \begin_layout Plain Layout
-
- \end_layout
- \begin_layout Plain Layout
- Composer.Set_Subject (ES => Email,
- \end_layout
- \begin_layout Plain Layout
- Subject => "Is this thing on?");
- \end_layout
- \begin_layout Plain Layout
- \end_layout
- \begin_layout Plain Layout
- Composer.Set_Text_Part (ES => Email,
- \end_layout
- \begin_layout Plain Layout
- Part => "Hey you!");
- \end_layout
- \begin_layout Plain Layout
- \end_layout
- \begin_layout Plain Layout
- Composer.Add_SMTP_Server (ES => Email,
- \end_layout
- \begin_layout Plain Layout
- Host => "localhost");
- \end_layout
- \begin_layout Plain Layout
-
- \end_layout
- \begin_layout Plain Layout
- Composer.Send (ES => Email);
- \end_layout
- \begin_layout Plain Layout
-
- \end_layout
- \begin_layout Plain Layout
- if Composer.Is_Send (Email) then
- \end_layout
- \begin_layout Plain Layout
- -- Success!
- \end_layout
- \begin_layout Plain Layout
- else
- \end_layout
- \begin_layout Plain Layout
- -- Failure!
- \end_layout
- \begin_layout Plain Layout
- end if;
- \end_layout
- \begin_layout Plain Layout
- end;
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- Harder yes, but really not all that much more difficult.
- \end_layout
- \begin_layout Section
- Yolk.Handlers
- \end_layout
- \begin_layout Standard
- Most web applications will need to handle static content, such as PNG, HTML
- and CSS files.
-
- \emph on
- Yolk.Handlers
- \emph default
- helps you accomplish that, so you don't have to build your own handlers
- for these kinds of files.
- \end_layout
- \begin_layout Standard
- The following filetypes are supported by
- \emph on
- Yolk.Handlers
- \emph default
- :
- \end_layout
- \begin_layout Itemize
- CSS
- \end_layout
- \begin_layout Itemize
- GIF
- \end_layout
- \begin_layout Itemize
- HTML
- \end_layout
- \begin_layout Itemize
- ICO
- \end_layout
- \begin_layout Itemize
- JPG
- \end_layout
- \begin_layout Itemize
- JS
- \end_layout
- \begin_layout Itemize
- PNG
- \end_layout
- \begin_layout Itemize
- SVG
- \end_layout
- \begin_layout Itemize
- XML
- \end_layout
- \begin_layout Itemize
- XSL
- \end_layout
- \begin_layout Standard
- The filetypes that are textual, are compressed according to the
- \emph on
- Yolk.Configuration
- \emph default
- parameter
- \emph on
- Compress_Static_Content
- \emph default
- which defaults to
- \emph on
- False
- \emph default
- .
- The regular expressions for identifying these filetypes are also defined
- in
- \emph on
- Yolk.Configuration
- \emph default
- by the
- \emph on
- Handler_*
- \emph default
- parameters.
- These regular expressions are registered by the
- \emph on
- AWS.Services.Dispatchers.URI.Register_Regexp
- \emph default
- procedure.
- \end_layout
- \begin_layout Standard
- There's only one procedure in the
- \emph on
- Yolk.Handlers
- \emph default
- package:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- procedure Set (RH : out AWS.Services.Dispatchers.URI.Handler);
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- You can see an example on how this is used in the demo file
- \emph on
- my_handlers.adb
- \emph default
- .
- There's really very little reason not to use this package for handling
- of static content, but it is of course not mandatory.
- \end_layout
- \begin_layout Standard
- This package makes use of the
- \emph on
- Yolk.Static_Content
- \emph default
- package for the actual delivery of the content to the user.
- \end_layout
- \begin_layout Section
- Yolk.Log
- \end_layout
- \begin_layout Standard
- This package serves two purposes:
- \end_layout
- \begin_layout Enumerate
- It contains the two callback procedures used to write AWS logging data (access
- and error) to syslogd.
- \end_layout
- \begin_layout Enumerate
- It creates the SQL, SQL_Cache, SQL_Error, SQL_Select, Alert, Critical, Debug,
- Emergency, Error, Info, Notice and Warning trace handles, and activates
- them according to the values defined in the configuration file.
- \end_layout
- \begin_layout Standard
- Out of the box, a Yolk application requires a running syslogd daemon, as
- all log data is sent to syslogd.
- If for some reason you don't want to use syslogd, you're going to have
- to hack the
- \emph on
- Yolk.Log
- \emph default
- package, or remove it entirely.
- \end_layout
- \begin_layout Standard
- The two procedures named
- \emph on
- AWS_*
- \emph default
- are used by the AWS HTTP(S) server.
- These should not be used for anything else - or rather: If you use them
- for anything else, the
- \emph on
- Message
- \emph default
- given is going to be written to syslogd with either the AWS access log
- label or AWS error log label.
- There's absolutely no harm in this, except it might be a bit confusing
- when reading the log data.
- \end_layout
- \begin_layout Standard
- The
- \emph on
- Trace
- \emph default
- procedure is the one that you will be using in your application.
- You can send log data to the trace handles defined in
- \emph on
- Yolk.Log.Trace_Handles
- \emph default
- .
- All log data is then sent to the syslogd daemon using the facilities set
- in the configuration file for the given trace handle.
- \end_layout
- \begin_layout Standard
- Using
- \emph on
- Trace
- \emph default
- is about as easy as it gets:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- Yolk.Log.Trace (Handle => Error,
- \end_layout
- \begin_layout Plain Layout
- Message => "Secret sauce to Error!");
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- If you haven't activated a trace handle, then calling
- \emph on
- Trace
- \emph default
- for that handle does nothing, ie.
- you don't have to remove all your
- \emph on
- Trace
- \emph default
- calls from the code if you don't use them.
- \end_layout
- \begin_layout Standard
- Note that on many systems the Emergency messages are written to console,
- so be cautious about using this specific level, unless you've made certain
- that you can get to the messages.
- \end_layout
- \begin_layout Section
- Yolk.Not_Found
- \end_layout
- \begin_layout Standard
- The job of this package is to return a HTTP 404 status code and an accompanying
- simple
- \emph on
- not found
- \emph default
- HTML page.
- It's sole function
- \emph on
- Generate
- \emph default
- is about as simple as they come:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- function Generate
- \end_layout
- \begin_layout Plain Layout
- (Request : in AWS.Status.Data)
- \end_layout
- \begin_layout Plain Layout
- return AWS.Response.Data;
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- It relies on the template file
- \emph on
- demo/exe/templates/system/404.tmpl
- \emph default
- to generate the generic 404 HTML page, so if you want to use
- \emph on
- Yolk.Not_Found
- \emph default
- in your own application, then remember to bring along this file.
- Where the
- \emph on
- 404.tmpl
- \emph default
- is placed is defined in the configuration parameter
- \emph on
- System_Templates_Path
- \emph default
- .
- \end_layout
- \begin_layout Standard
- Also worth noting is that the
- \emph on
- Yolk.Not_Found.Generate
- \emph default
- function is used as the default callback in the demo application.
- This means that all requested resources that doesn't match a registered
- dispatcher, is served by
- \emph on
- Yolk.Not_Found.Generate
- \emph default
- ie.
- a 404 is returned.
- See the
- \emph on
- demo/src/my_handlers.adb
- \emph default
- file for more information.
- \end_layout
- \begin_layout Section
- Yolk.Process_Control
- \end_layout
- \begin_layout Standard
- With
- \emph on
- Yolk.Process_Control
- \emph default
- you get the ability to control your application using the SIGINT, SIGPWR
- and SIGTERM signals.
- If you give your Yolk application the
- \emph on
- --pid-file
- \emph default
- commandline argument when starting it,
- \emph on
- Yolk.Process_Control
- \emph default
- will create a PID file on the given location, if it is allowed to do so.
- This PID file will also be deleted when the application terminates.
- Note that the
- \emph on
- extras/rc.yolk
- \emph default
- script handles all this transparently.
- \end_layout
- \begin_layout Subsection
- Exceptions
- \end_layout
- \begin_layout Standard
- These are:
- \end_layout
- \begin_layout Itemize
- \emph on
- Cannot_Create_PID_File
- \emph default
- .
- Is raised if the
- \emph on
- PID_File
- \emph default
- cannot be created, eg.
- if the application lacks permissions to write to the directory where the
-
- \emph on
- PID_File
- \emph default
- is located.
- \end_layout
- \begin_layout Itemize
- \emph on
- Cannot_Delete_PID_File
- \emph default
- .
- Is raised if the
- \emph on
- PID_file
- \emph default
- cannot be deleted, eg.
- if the application lacks permissions to write to the directory where the
-
- \emph on
- PID_File
- \emph default
- is located, or to the
- \emph on
- PID_File
- \emph default
- itself.
- \end_layout
- \begin_layout Itemize
- \emph on
- PID_File_Exists
- \emph default
- .
- Is raised when the
- \emph on
- PID_File
- \emph default
- already exists, ie.
- the application is already running or it was shutdown incorrectly.
- \end_layout
- \begin_layout Subsection
- Using Yolk.Process_Control
- \end_layout
- \begin_layout Standard
- When you use the
- \emph on
- Yolk.Process_Control
- \emph default
- package the
- \emph on
- Unreserve_All_Interrupts
- \emph default
- pragma is used.
- This means that depending on the compiler used one or more interrupt signals
- may be affected.
- In the case of the GNAT compiler, this is specifically mentioned in the
- source of the
- \emph on
- Ada.Interrupts.Names
- \emph default
- package:
- \end_layout
- \begin_layout Quote
- -- The pragma Unreserve_All_Interrupts affects the following signal(s):
- \end_layout
- \begin_layout Quote
- -- SIGINT: made available for Ada handler
- \end_layout
- \begin_layout Standard
- Since neither SIGPWR or SIGTERM are reserved by the compiler, the
- \emph on
- Yolk.Process_Control
- \emph default
- package is able to assume control of these signals.
- You can read more about the
- \begin_inset CommandInset href
- LatexCommand href
- name "pragma Unreserve_All_Interrupts here"
- target "http://gcc.gnu.org/onlinedocs/gnat_rm/Pragma-Unreserve_005fAll_005fInterrupts.html"
- \end_inset
- .
- If you compile Yolk with a different compiler than GNAT, then please check
- if one of the affected signals are reserved.
- \end_layout
- \begin_layout Standard
- There are two procedures in the
- \emph on
- Yolk.Process_Control
- \emph default
- package:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- procedure Stop;
- \end_layout
- \begin_layout Plain Layout
- \end_layout
- \begin_layout Plain Layout
- procedure Wait;
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- When you call the
- \emph on
- Wait
- \emph default
- procedure, you basically hang there until
- \end_layout
- \begin_layout Enumerate
- The
- \emph on
- Stop
- \emph default
- procedure is called
- \end_layout
- \begin_layout Enumerate
- The application receives a SIGINT, SIGPWR or SIGTERM signal
- \end_layout
- \begin_layout Standard
- This is quite handy for applications, that need some sort of loop to keep
- them from terminating.
- You can see an example on how this can be done in the
- \emph on
- demo/src/yolk_demo.adb
- \emph default
- file.
- \end_layout
- \begin_layout Standard
- When
- \emph on
- Wait
- \emph default
- is called, subsequent calls to
- \emph on
- Wait
- \emph default
- are ignored, unless a call to
- \emph on
- Stop
- \emph default
- has been made or the application has received one of the SIGINT, SIGPWR
- or SIGTERM signals.
- So it's perfectly valid to do:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- Wait;
- \end_layout
- \begin_layout Plain Layout
- -- Stop called from somewhere in the app
- \end_layout
- \begin_layout Plain Layout
- -- Do something...
- \end_layout
- \begin_layout Plain Layout
- Wait;
- \end_layout
- \begin_layout Plain Layout
- -- The app receives a SIGINT signal
- \end_layout
- \begin_layout Plain Layout
- -- Do something...
- \end_layout
- \begin_layout Plain Layout
- Wait;
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- Whether or not this is actually useful I don't know, but it is possible.
- \end_layout
- \begin_layout Section
- Yolk.Process_Owner
- \end_layout
- \begin_layout Standard
- When it is necessary to change the owner of a process, the
- \emph on
- Yolk.Process_Owner
- \emph default
- package is the solution.
- Obviously this can also be done when starting the application, using various
- shell tricks, but I find it it much cleaner to just let the application
- handle it by itself.
- \end_layout
- \begin_layout Subsection
- Exceptions
- \end_layout
- \begin_layout Standard
- There's only one:
- \end_layout
- \begin_layout Enumerate
- \emph on
- Username_Does_Not_Exist
- \emph default
- .
- This is raised if the given username doesn't exist on the system.
- \end_layout
- \begin_layout Subsection
- Using Yolk.Process_Owner
- \end_layout
- \begin_layout Standard
- There's only a single procedure in this package and its specification looks
- like this:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- procedure Set_User
- \end_layout
- \begin_layout Plain Layout
- (Username : in String);
- \end_layout
- \begin_layout Plain Layout
- -- Set the process owner to Username.
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- Please note that when changing the user ID of the application with
- \emph on
- Set_User
- \emph default
- , the group ID is changed to the first group the given user is a member
- of.
- \end_layout
- \begin_layout Standard
- Usage is as simple as expected:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- declare
- \end_layout
- \begin_layout Plain Layout
- begin
- \end_layout
- \begin_layout Plain Layout
- Set_User (Username => "billybob");
- \end_layout
- \begin_layout Plain Layout
- exception
- \end_layout
- \begin_layout Plain Layout
- when Username_Does_Not_Exist =>
- \end_layout
- \begin_layout Plain Layout
- -- User is missing.
- Do something!
- \end_layout
- \begin_layout Plain Layout
- end;
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- In the file
- \emph on
- demo/src/yolk_demo.adb
- \emph default
- you'll find that
- \emph on
- Yolk.Process_Owner.Set_User
- \emph default
- is used in conjunction with the
- \emph on
- Yolk.Configuration.Yolk_User
- \emph default
- parameter.
- \end_layout
- \begin_layout Section
- Yolk.Server
- \end_layout
- \begin_layout Standard
- This is a convenience package to handle creating, starting and stopping
- an AWS HTTP server.
- The biggest drawback to this package is that it can only create and manage
-
- \emph on
- one
- \emph default
- AWS server.
- \end_layout
- \begin_layout Standard
- Note a potential manual operation when using the
- \emph on
- Yolk.Server
- \emph default
- package : Setting the
- \emph on
- Cache-Control
- \emph default
- header.
- This can become necessary if you
- \end_layout
- \begin_layout Enumerate
- use
- \emph on
- Yolk.Server
- \emph default
- to create and start your AWS server AND
- \end_layout
- \begin_layout Enumerate
- use the
- \emph on
- Yolk.Handlers
- \emph default
- package to register dispatchers for static content AND
- \end_layout
- \begin_layout Enumerate
- have the
- \emph on
- Compress_Static_Content
- \emph default
- configuration parameter set to
- \emph on
- True
- \emph default
- AND
- \end_layout
- \begin_layout Enumerate
- aren't content with the default
- \emph on
- Cache-Control
- \emph default
- header
- \end_layout
- \begin_layout Standard
- In that case you can use the
- \emph on
- Yolk.Static_Content.Set_Cache_Options
- \emph default
- procedure to work your own magic on the
- \emph on
- Cache-Control
- \emph default
- header sent to clients requesting static content.
- See the Yolk.Static_Content chapter for more information.
- \end_layout
- \begin_layout Subsection
- Yolk.Server.Create
- \end_layout
- \begin_layout Standard
- Creating a server is done by calling the
- \emph on
- Create
- \emph default
- function.
- This function accepts one parameter that should be fairly self-explanatory.
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- type HTTP is tagged limited private;
- \end_layout
- \begin_layout Plain Layout
- \end_layout
- \begin_layout Plain Layout
- function Create
- \end_layout
- \begin_layout Plain Layout
- (Unexpected : in AWS.Exceptions.Unexpected_Exception_Handler)
- \end_layout
- \begin_layout Plain Layout
- return HTTP;
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Subsection
- Yolk.Server.Start
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- procedure Start
- \end_layout
- \begin_layout Plain Layout
- (WS : in out HTTP;
- \end_layout
- \begin_layout Plain Layout
- Dispatchers : in AWS.Dispatchers.Handler'Class);
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- This does as expected: Starts the server with
- \emph on
- Dispatchers.
- \end_layout
- \begin_layout Standard
- When calling
- \emph on
- Start
- \emph default
- several things happen:
- \end_layout
- \begin_layout Enumerate
- If the configuration parameter
- \emph on
- Load_MIME_Types_File
- \emph default
- is
- \emph on
- True
- \emph default
- then the MIME types file given in
- \emph on
- MIME_Types_File
- \emph default
- is loaded into AWS.
-
- \end_layout
- \begin_layout Enumerate
- If the configuration parameter
- \emph on
- Start_WebSocket_Servers
- \emph default
- is
- \emph on
- True
- \emph default
- then the AWS WebSocket servers are started.
- \end_layout
- \begin_layout Enumerate
- \emph on
- Yolk.Static_Content.Static_Content_Cache_Setup
- \emph default
- is called with its default parameters if the configuration parameter
- \emph on
- Compress_Static_Content
- \emph default
- is
- \emph on
- True
- \emph default
- .
- \end_layout
- \begin_layout Enumerate
- If session support is turned on for the server and the
- \emph on
- Session_Data_File
- \emph default
- exists, then the session data is loaded from this file.
- \end_layout
- \begin_layout Enumerate
- The
- \emph on
- Yolk.Log.AWS_Access_Log_Writer
- \emph default
- procedure is registered to handle all AWS access log data if the configuration
- parameter
- \emph on
- AWS_Access_Log_Activate
- \emph default
- is
- \emph on
- True
- \emph default
- .
- \end_layout
- \begin_layout Enumerate
- The
- \emph on
- Yolk.Log.AWS_Error_Log_Writer
- \emph default
- procedure is registered to handle all AWS error log data if the configuration
- parameter
- \emph on
- AWS_Error_Log_Activate
- \emph default
- is
- \emph on
- True
- \emph default
- .
- \end_layout
- \begin_layout Subsection
- Yolk.Server.Stop
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- procedure Stop
- \end_layout
- \begin_layout Plain Layout
- (WS : in out HTTP);
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- This does as expected: Stops everything that was started when the
- \emph on
- Yolk.Server.Start
- \emph default
- call was made.
- Note that if sessions support is turned on for the server, then the
- \emph on
- Dispatchers
- \emph default
- are switched for a plain
- \emph on
- Not Found
- \emph default
- dispatcher when
- \emph on
- Stop
- \emph default
- is called.
- This is done to prevent session tampering while the server is shutting
- down.
- \end_layout
- \begin_layout Section
- Yolk.Static_Content
- \end_layout
- \begin_layout Standard
- Most web applications have a lot of static content, ie.
- stuff that rarely changes.
- Things like PNG's, HTML, CSS and Javascript.
- These are content types that are common for most websites, so a application
- is going to have to handle these in some way.
- This is where
- \emph on
- Yolk.Static_Content
- \emph default
- comes in.
- Two kinds of files are handled by
- \emph on
- Yolk.Static_Content
- \emph default
- :
- \end_layout
- \begin_layout Itemize
- Compressable (XML, HTML, CSS, JS and so on)
- \end_layout
- \begin_layout Itemize
- Non-compressable (PNG, JPG, GIF, ICO and so on)
- \end_layout
- \begin_layout Standard
- It is up to you, the user, to decide whether a specific kind of file is
- compressable or not - the package does not make any such assumptions.
- The difference between the two, is that compressable files are compressed
- prior to delivery, if the clients HTTP request includes a
- \emph on
- Accept-Encoding: gzip
- \emph default
- header.
- Non-compressable files are simply returned as is.
- For both kinds, a generic 404 is returned if the requested file doesn't
- exist.
- \end_layout
- \begin_layout Standard
- \emph on
- Yolk.Static_Content
- \emph default
- is affected by five configuration settings:
- \end_layout
- \begin_layout Itemize
- Compress_Static_Content
- \end_layout
- \begin_layout Itemize
- Compress_Static_Content_Minimum_File_Size
- \end_layout
- \begin_layout Itemize
- Compressed_Static_Content_Cache
- \end_layout
- \begin_layout Itemize
- Compressed_Static_Content_Max_Age
- \end_layout
- \begin_layout Itemize
- WWW_Root
- \end_layout
- \begin_layout Standard
- You should carefully read the
- \emph on
- demo/exe/configuration/config.ini
- \emph default
- file for information on what exactly these do.
- \end_layout
- \begin_layout Subsection
- Yolk.Static_Content.Static_Content_Cache_Setup
- \end_layout
- \begin_layout Standard
- The configuration parameter
- \emph on
- Compressed_Static_Content_Cache
- \emph default
- defines where the compressed version of the static content is saved.
- When your application is started, this directory may or may not exist,
- and it may or may not contain various compressed files.
- To make sure that the directory exists and is empty, you should call the
-
- \emph on
- Static_Content_Cache_Setup
- \emph default
- procedure:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- procedure Static_Content_Cache_Setup
- \end_layout
- \begin_layout Plain Layout
- (No_Cache : in Boolean := False;
- \end_layout
- \begin_layout Plain Layout
- No_Store : in Boolean := False;
- \end_layout
- \begin_layout Plain Layout
- No_Transform : in Boolean := False;
- \end_layout
- \begin_layout Plain Layout
- Max_Age : in AWS.Messages.Delta_Seconds := 86400;
- \end_layout
- \begin_layout Plain Layout
- S_Max_Age : in AWS.Messages.Delta_Seconds :=
- \end_layout
- \begin_layout Plain Layout
- AWS.Messages.Unset;
- \end_layout
- \begin_layout Plain Layout
- Public : in Boolean := False;
- \end_layout
- \begin_layout Plain Layout
- Must_Revalidate : in Boolean := True;
- \end_layout
- \begin_layout Plain Layout
- Proxy_Revalidate : in Boolean := False);
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- This procedure creates the
- \emph on
- Compressed_Static_Content_Cache
- \emph default
- directory if it doesn't already exists and if it exists, it deletes everything
- in it.
- So basically you're left with an empty directory after a call to this procedure.
-
- \end_layout
- \begin_layout Standard
- The parameters defines the content of the
- \emph on
- Cache-Control
- \emph default
- header sent to the user agent when a request for static content is made.
- The default parameters are fairly sane, and will result in a cache header
- looking like this:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- Cache-Control: max-age=86400, must-revalidate
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- Read the
- \begin_inset CommandInset href
- LatexCommand href
- name "HTTP/1.1 Cache-Control header definition"
- target "http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9"
- \end_inset
- for more information on what the various settings do.
- \end_layout
- \begin_layout Standard
- If you use
- \emph on
- Yolk.Server
- \emph default
- to create and start your AWS server, then this called is made automatically
- with it's default parameters.
-
- \end_layout
- \begin_layout Standard
- If you don't use
- \emph on
- Yolk.Server
- \emph default
- and you use the
- \emph on
- Yolk.Static_Content
- \emph default
- package to serve static content, then you must call this procedure before
- starting the AWS server.
- Calling it repeatedly will simply wipe out the compressed cache directory
- and reset the
- \emph on
- Control_Cache
- \emph default
- header according to the given parameters.
- \end_layout
- \begin_layout Subsection
- Yolk.Static_Content.Compressable
- \end_layout
- \begin_layout Standard
- If your application contains a bunch of compressable files of significant
- size, you can save a lot of bandwidth by using the
- \emph on
- Compressable
- \emph default
- function to serve them:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- function Compressable
- \end_layout
- \begin_layout Plain Layout
- (Request : in AWS.Status.Data)
- \end_layout
- \begin_layout Plain Layout
- return AWS.Response.Data;
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- A natural place to call this function would be where you define your content
- handlers, as seen in this, slightly altered, excerpt from the
- \emph on
- Yolk.Handlers
- \emph default
- package:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- declare
- \end_layout
- \begin_layout Plain Layout
- package SC renames Yolk.Static_Content;
- \end_layout
- \begin_layout Plain Layout
- Resource_Handlers : AWS.Services.Dispatchers.URI.Handler;
- \end_layout
- \begin_layout Plain Layout
- begin
- \end_layout
- \begin_layout Plain Layout
- AWS.Services.Dispatchers.URI.Register_Regexp
- \end_layout
- \begin_layout Plain Layout
- (Dispatcher => Resource_Handlers,
- \end_layout
- \begin_layout Plain Layout
- URI => "
- \backslash
- .css$",
- \end_layout
- \begin_layout Plain Layout
- Action => Create (Callback => SC.Compressable'Access));
- \end_layout
- \begin_layout Plain Layout
- \end_layout
- \begin_layout Plain Layout
- AWS.Services.Dispatchers.URI.Register_Regexp
- \end_layout
- \begin_layout Plain Layout
- (Dispatcher => Resource_Handlers,
- \end_layout
- \begin_layout Plain Layout
- URI => "
- \backslash
- .html$",
- \end_layout
- \begin_layout Plain Layout
- Action => Create (Callback => SC.Compressable'Access));
- \end_layout
- \begin_layout Plain Layout
- end;
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- Here you can see that we've defined some content handlers for CSS and HTML
- files based on a few simple regular expressions, and whenever a resource
- is requested that matches one of these, the corresponding
- \emph on
- Action
- \emph default
- callback is called, which in this example is the
- \emph on
- Compressable
- \emph default
- function.
- The following steps are then taken:
- \end_layout
- \begin_layout Enumerate
- Does the requested resource exist and is it an ordinary file?
- \end_layout
- \begin_deeper
- \begin_layout Enumerate
- If no, then return a 404 message
- \end_layout
- \begin_layout Enumerate
- if yes, then proceed to 2
- \end_layout
- \end_deeper
- \begin_layout Enumerate
- Does the client support compressed content?
- \end_layout
- \begin_deeper
- \begin_layout Enumerate
- If no, then return the requested resource un-compressed
- \end_layout
- \begin_layout Enumerate
- if yes, then proceed to 3
- \end_layout
- \end_deeper
- \begin_layout Enumerate
- Is there a compressed version of the resource available on disk?
- \end_layout
- \begin_deeper
- \begin_layout Enumerate
- if no, then make one, cache it for future use, and return it
- \end_layout
- \begin_layout Enumerate
- If yes, then proceed to 4
- \end_layout
- \end_deeper
- \begin_layout Enumerate
- Is the age of the compressed file <= Compressed_Max_Age?
- \end_layout
- \begin_deeper
- \begin_layout Enumerate
- If no, then delete the current file, build a new one, cache it and return
- it
- \end_layout
- \begin_layout Enumerate
- If yes, then return it
- \end_layout
- \end_deeper
- \begin_layout Standard
- And that's really all there is to it.
- Note that
- \emph on
- Compressable
- \emph default
- always looks for requested content in the
- \emph on
- WWW_Root
- \emph default
- directory, so if the user requests the file
- \emph on
- /css/index.css
- \emph default
- , then the path is going to be:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- WWW_Root & "/css/index.ss";
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- Using the default configuration value for
- \emph on
- WWW_Root
- \emph default
- , we'll end up with the path:
- \end_layout
- \begin_layout LyX-Code
- static_content/css/index.css
- \end_layout
- \begin_layout Standard
- The compressed version of
- \emph on
- index.css
- \emph default
- is saved as:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- Compressed_Static_Content_Cache & "/css/index.css" & ".gz";
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- Using the default configuration value for
- \emph on
- Compressed_Static_Content_Cache
- \emph default
- , we'll end up with the path:
- \end_layout
- \begin_layout LyX-Code
- static_content/compressed_cache/css/index.css.gz
- \end_layout
- \begin_layout Standard
- In these two cases the paths are relative to the executable, but you can
- of course also define
- \emph on
- WWW_Root
- \emph default
- and
- \emph on
- Compressed_Static_Content_Cache
- \emph default
- as absolute paths in the configuration file.
- \end_layout
- \begin_layout Subsection
- Yolk.Static_Content.Non_Compressable
- \end_layout
- \begin_layout Standard
- A lot of static content really doesn't benefit from any further compression.
- This is the case for PNG files, JPEG files and a whole lot of other kinds
- of files.
- Static content that has already been compressed, should be handled by the
-
- \emph on
- Non_Compressable
- \emph default
- function:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- function Non_Compressable
- \end_layout
- \begin_layout Plain Layout
- (Request : in AWS.Status.Data)
- \end_layout
- \begin_layout Plain Layout
- return AWS.Response.Data;
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- A call to
- \emph on
- Non_Compressable
- \emph default
- is much simpler compared to a call to it's sibling function
- \emph on
- Compressable
- \emph default
- :
- \end_layout
- \begin_layout Enumerate
- Does the requested resource exist and is it an ordinary file?
- \end_layout
- \begin_deeper
- \begin_layout Enumerate
- If no, then return a 404 message
- \end_layout
- \begin_layout Enumerate
- if yes, then return the file
- \end_layout
- \end_deeper
- \begin_layout Standard
- And that's it.
- Either the resource is there, or it isn't.
- If the requested resource is
- \emph on
- /images/foo.png
- \emph default
- , then the
- \emph on
- Non_Compressable
- \emph default
- function searches for the resource in:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- WWW_Root & "/images/foo.png";
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- Using the default configuration value for
- \emph on
- WWW_Root
- \emph default
- , we'll end up with the path:
- \end_layout
- \begin_layout LyX-Code
- static_content/images/foo.png
- \end_layout
- \begin_layout Standard
- Just as with
- \emph on
- Compressable
- \emph default
- a natural place to use
- \emph on
- Non_Compressable
- \emph default
- is where you define you content handlers, but it can obviously be used
- wherever your application handles requests for static content.
- \end_layout
- \begin_layout Subsection
- Yolk.Static.Set_Cache_Options
- \end_layout
- \begin_layout Standard
- You can alter the
- \emph on
- Cache-Control
- \emph default
- header sent to clients requesting static content with a call to
- \emph on
- Set_Cache_Options
- \emph default
- \SpecialChar \@.
- This is especially handy if you use the
- \emph on
- Yolk.Server
- \emph default
- package to create and start your server, since the initial call to
- \emph on
- Static_Content_Cache_Setup
- \emph default
- is hidden you're forced to live with the default values given in the
- \emph on
- Static_Content_Cache_Setup
- \emph default
- call, resulting in a
- \emph on
- Cache-Control
- \emph default
- header looking like this:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- Cache-Control: max-age=86400, must-revalidate
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- If this is not what you want, you can use
- \emph on
- Set_Cache_Options
- \emph default
- to change it:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- procedure Set_Cache_Options
- \end_layout
- \begin_layout Plain Layout
- (No_Cache : in Boolean := False;
- \end_layout
- \begin_layout Plain Layout
- No_Store : in Boolean := False;
- \end_layout
- \begin_layout Plain Layout
- No_Transform : in Boolean := False;
- \end_layout
- \begin_layout Plain Layout
- Max_Age : in AWS.Messages.Delta_Seconds := 86400;
- \end_layout
- \begin_layout Plain Layout
- S_Max_Age : in AWS.Messages.Delta_Seconds :=
- \end_layout
- \begin_layout Plain Layout
- AWS.Messages.Unset;
- \end_layout
- \begin_layout Plain Layout
- Public : in Boolean := False;
- \end_layout
- \begin_layout Plain Layout
- Must_Revalidate : in Boolean := True;
- \end_layout
- \begin_layout Plain Layout
- Proxy_Revalidate : in Boolean := False);
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- This MUST be called immediately after having called
- \emph on
- Yolk.Server.Start
- \emph default
- , since the call to
- \emph on
- Static_Content_Cache_Setup
- \emph default
- in
- \emph on
- Start
- \emph default
- will overwrite the cache options.
- \end_layout
- \begin_layout Section
- Yolk.Syndication
- \end_layout
- \begin_layout Standard
- The Atom Syndication format (
- \begin_inset CommandInset href
- LatexCommand href
- name "RFC4287"
- target "http://tools.ietf.org/html/rfc4287"
- \end_inset
- ) is an XML-based document format that describes lists of related information
- known as "feeds".
- Atom documents are used by many web applications as a means of publishing
- information to users.
- It's not a complicated format, but it does require a bit of work to construct
- a proper Atom feed by hand, and since I try my best to avoid work, I made
- the
- \emph on
- Yolk.Syndication
- \emph default
- package.
- This package makes it
- \begin_inset Quotes eld
- \end_inset
- easy
- \begin_inset Quotes erd
- \end_inset
- to put together an Atom feed document, and have it delivered as a string
- or an XML/Ada DOM object.
- \end_layout
- \begin_layout Standard
- \emph on
- Yolk.Syndication
- \emph default
- helps you construct the Atom XML - it does not check that the resulting
- XML is valid Atom XML, ie.
- that the Atom rules have been followed, so if the Atom specification says
- that
- \end_layout
- \begin_layout Quote
- atom:feed elements MUST contain exactly one atom:id element.
- \end_layout
- \begin_layout Standard
- then it is your job to make sure that your Atom feed has exactly one such
- element.
- So before venturing into the realm of Atom, it's probably a good idea to
- read
- \begin_inset CommandInset href
- LatexCommand href
- name "RFC4287"
- target "http://tools.ietf.org/html/rfc4287"
- \end_inset
- for a good understanding of the requirements for this document format.
- A basic example of how to build an Atom feed can be found in the Yolk demo
- application.
- \end_layout
- \begin_layout Standard
- There are two packages in the
- \emph on
- Yolk.Syndication
- \emph default
- hierarchy:
- \end_layout
- \begin_layout Itemize
- \emph on
- Yolk.Syndication
- \emph default
- - Here the necessary types and exceptions are defined.
- \end_layout
- \begin_layout Itemize
- \emph on
- Yolk.Syndication.Writer
- \emph default
- - Here the functions and procedures for actually creating an Atom feed
- are defined.
- \end_layout
- \begin_layout Standard
- When time permits, I'll add a
- \emph on
- Yolk.Syndication.Reader
- \emph default
- package for extraction of data from an Atom feed.
- \end_layout
- \begin_layout Subsection
- Exceptions
- \end_layout
- \begin_layout Standard
- There's one exception in this package:
- \end_layout
- \begin_layout Itemize
- \emph on
- Not_Valid_XML
- \emph default
- .
- Is raised when some Xhtml content is not valid XML.
- This exception can be raised by all procedures that takes Xhtml as content.
- \end_layout
- \begin_layout Subsection
- The Yolk.Syndication types
- \end_layout
- \begin_layout Standard
- There are 5 important types in this package:
- \end_layout
- \begin_layout Itemize
- \emph on
- Text_Kinds
- \end_layout
- \begin_layout Itemize
- \emph on
- Relation_Kinds
- \end_layout
- \begin_layout Itemize
- \emph on
- Atom_Entry
- \end_layout
- \begin_layout Itemize
- \emph on
- Atom_Entry_Source
- \end_layout
- \begin_layout Itemize
- \emph on
- Atom_Feed
- \end_layout
- \begin_layout Standard
- A few of the procedures in
- \emph on
- Yolk.Syndication.Writer
- \emph default
- has parameters of the
- \emph on
- Text_Kinds
- \emph default
- type.
- This identifies the kind of data that is being added, with possible values
- being
- \end_layout
- \begin_layout Itemize
- \emph on
- Text
- \emph default
-
- \end_layout
- \begin_layout Itemize
- \emph on
- Html
- \end_layout
- \begin_layout Itemize
- \emph on
- Xhtml
- \end_layout
- \begin_layout Standard
- Hopefully it's obvious what each of these refers to.
- Procedures that have parameters of the
- \emph on
- Text_Kinds
- \emph default
- type always add data to the feed that can be interpreted as one of these
- three kinds of text.
- \end_layout
- \begin_layout Standard
- The
- \emph on
- Relation_Kinds
- \emph default
- type is used in correlation with links that are added to the feed.
- It identifies how the link relates to the current feed/entry.
- There are 5 possible relations:
- \end_layout
- \begin_layout Itemize
- \emph on
- Alternate
- \emph default
- : Signifies that the link points to an alternate version of the resource
- described by the containing element.
- \end_layout
- \begin_layout Itemize
- \emph on
- Related
- \emph default
- : Signifies that the link points to a resource that is related to, but not
- the same as, the resource described by the containing element.
- \end_layout
- \begin_layout Itemize
- \emph on
- Self
- \emph default
- : Signifies that the link points to a resource that is equivalent to the
- resource described by the containing element.
- All feeds should have one link with a
- \emph on
- Self
- \emph default
- relation pointing to itself.
- \end_layout
- \begin_layout Itemize
- \emph on
- Enclosure
- \emph default
- : Signifies that the link points to a resource that is related to, but not
- the same as, the resource described by the containing element.
- It also signifies that the resource potentially is large in size and might
- require special handling.
- If
- \emph on
- Enclosure
- \emph default
- is used, then usually the
- \emph on
- Length
- \emph default
- parameter is set to hint at the size of the resource.
- \end_layout
- \begin_layout Itemize
- \emph on
- Via
- \emph default
- : Signifies that the resource provided by the containing element originates
- in the URI given by the
- \emph on
- Href
- \emph default
- parameter of the link element.
- \end_layout
- \begin_layout Standard
- Finally we have the most important types:
- \end_layout
- \begin_layout Itemize
- \emph on
- Atom_Entry
- \emph default
- : An entry in a feed.
- \end_layout
- \begin_layout Itemize
- \emph on
- Atom_Entry_Source
- \emph default
- : The origin of an entry.
- \end_layout
- \begin_layout Itemize
- \emph on
- Atom_Feed
- \emph default
- : The Atom feed.
- \end_layout
- \begin_layout Standard
- These are core to the functionality of
- \emph on
- Yolk.Syndication
- \emph default
- , and every single procedure and function in the
- \emph on
- Yolk.Syndication.Writer
- \emph default
- package use one or the other.
- These three types are
- \emph on
- private
- \emph default
- , so the only way to declare an object of either one, is by calling the
-
- \emph on
- New_Atom_Feed
- \emph default
- ,
- \emph on
- New_Atom_Entry
- \emph default
- or
- \emph on
- New_Atom_Entry_Source
- \emph default
- functions respectively.
- \end_layout
- \begin_layout Standard
- Note that only
- \emph on
- Atom_Feed
- \emph default
- is thread safe.
- The two entry related types are not.
- \end_layout
- \begin_layout Subsection
- Yolk.Syndication.New_Atom_Feed
- \end_layout
- \begin_layout Standard
- This function initialize an
- \emph on
- Atom_Feed
- \emph default
- type, and its specification looks like this:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- function New_Atom_Feed
- \end_layout
- \begin_layout Plain Layout
- (Base_URI : in String := None;
- \end_layout
- \begin_layout Plain Layout
- Language : in String := None;
- \end_layout
- \begin_layout Plain Layout
- Max_Age : in Duration := 5_616_000.0;
- \end_layout
- \begin_layout Plain Layout
- Max_Entries : in Positive := 100;
- \end_layout
- \begin_layout Plain Layout
- Min_Entries : in Positive := 10)
- \end_layout
- \begin_layout Plain Layout
- return Atom_Feed;
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- The
- \emph on
- Base_URI
- \emph default
- parameter establish a base for resolving relative references in the feed.
- The
- \emph on
- Language
- \emph default
- parameter indicates the natural language used in the feed.
-
- \emph on
- Max_Age
- \emph default
- is a duration that determine when an entry in the feed is old enough to
- be deleted.
-
- \emph on
- Max_Entries
- \emph default
- is the amount of entries kept in the feed.
- If there are more than this amount of entries in the feed, then the oldest
- are deleted until the feed contains
- \emph on
- Max_Entries
- \emph default
- entries again.
-
- \emph on
- Min_Entries
- \emph default
- is the minimum amount of entries that must be present in the feed, before
- we bother deleting entries whose age is >
- \emph on
- Max_Age
- \emph default
- .
- If there are less than
- \emph on
- Min_Entries
- \emph default
- entries in the feed, then we keep even a 100 year old entry.
- \end_layout
- \begin_layout Standard
- What these parameters hints at, is that some automatic maintenance is done
- when using
- \emph on
- Yolk.Syndication
- \emph default
- , and this is indeed true.
- Usually you do not want a feed to grow forever, and instead of having to
- manually clear away old stuff,
- \emph on
- Yolk.Syndication
- \emph default
- handles all this for you, according to the values given when you instantiate
- an
- \emph on
- Atom_Feed
- \emph default
- object using
- \emph on
- New_Atom_Feed
- \emph default
- .
- \end_layout
- \begin_layout Subsection
- Yolk.Syndication.New_Atom_Entry
- \end_layout
- \begin_layout Standard
- This function initialize an
- \emph on
- Atom_Entry
- \emph default
- type, and its specification looks like this:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- function New_Atom_Entry
- \end_layout
- \begin_layout Plain Layout
- (Base_URI : in String := None;
- \end_layout
- \begin_layout Plain Layout
- Language : in String := None)
- \end_layout
- \begin_layout Plain Layout
- return Atom_Entry;
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- As you can see, it's a lot simpler than the
- \emph on
- New_Atom_Feed
- \emph default
- function.
- This is of course because all the automatic maintenance related parameters
- have already been set by they
- \emph on
- New_Atom_Feed
- \emph default
- function.
- All that is left is to define the
- \emph on
- Base_URI
- \emph default
- and the natural
- \emph on
- Language
- \emph default
- used by the entry.
- \end_layout
- \begin_layout Subsection
- Yolk.Syndication.New_Atom_Entry_Source
- \end_layout
- \begin_layout Standard
- This function initialize an
- \emph on
- Atom_Entry_Source
- \emph default
- type, and its specification looks like this:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- function New_Atom_Entry_Source
- \end_layout
- \begin_layout Plain Layout
- (Base_URI : in String := None;
- \end_layout
- \begin_layout Plain Layout
- Language : in String := None)
- \end_layout
- \begin_layout Plain Layout
- return Atom_Entry_Source;
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- As you can see, this is very similar to the
- \emph on
- New_Atom_Entry
- \emph default
- function, since its job is to return an
- \emph on
- Atom_Entry_Source
- \emph default
- object, which is basically just an object that describes the origins of
- a feed entry.
- \end_layout
- \begin_layout Subsection
- Yolk.Syndication.Writer
- \end_layout
- \begin_layout Standard
- In this package we find all the tools necessary to build the Atom XML.
- There are far too many subprograms in
- \emph on
- Yolk.Syndication.Writer
- \emph default
- to list here, so instead I'll refer you to the source code.
- All the subprograms in this package work on one of the
- \emph on
- Atom_Feed
- \emph default
- ,
- \emph on
- Atom_Entry
- \emph default
- or
- \emph on
- Atom_Entry_Source
- \emph default
- types, for example if you want to set a title on your feed, you'll use
- the
- \emph on
- Set_Title
- \emph default
- procedure:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- procedure Set_Title
- \end_layout
- \begin_layout Plain Layout
- (Feed : in out Atom_Feed;
- \end_layout
- \begin_layout Plain Layout
- Title : in String;
- \end_layout
- \begin_layout Plain Layout
- Base_URI : in String := None;
- \end_layout
- \begin_layout Plain Layout
- Language : in String := None;
- \end_layout
- \begin_layout Plain Layout
- Title_Kind : in Text_Kinds := Text);
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- Or if the title is for an entry, then:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- procedure Set_Title
- \end_layout
- \begin_layout Plain Layout
- (Entr : in out Atom_Entry;
- \end_layout
- \begin_layout Plain Layout
- Title : in String;
- \end_layout
- \begin_layout Plain Layout
- Base_URI : in String := None;
- \end_layout
- \begin_layout Plain Layout
- Language : in String := None;
- \end_layout
- \begin_layout Plain Layout
- Title_Kind : in Text_Kinds := Text);
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- Or we could add an author to the feed/entry/entry source:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- procedure Add_Author
- \end_layout
- \begin_layout Plain Layout
- (Feed : in out Atom_Feed;
- \end_layout
- \begin_layout Plain Layout
- Name : in String;
- \end_layout
- \begin_layout Plain Layout
- Base_URI : in String := None;
- \end_layout
- \begin_layout Plain Layout
- Email : in String := None;
- \end_layout
- \begin_layout Plain Layout
- Language : in String := None;
- \end_layout
- \begin_layout Plain Layout
- URI : in String := None);
- \end_layout
- \begin_layout Plain Layout
- \end_layout
- \begin_layout Plain Layout
- procedure Add_Author
- \end_layout
- \begin_layout Plain Layout
- (Entr : in out Atom_Entry;
- \end_layout
- \begin_layout Plain Layout
- Name : in String;
- \end_layout
- \begin_layout Plain Layout
- Base_URI : in String := None;
- \end_layout
- \begin_layout Plain Layout
- Email : in String := None;
- \end_layout
- \begin_layout Plain Layout
- Language : in String := None;
- \end_layout
- \begin_layout Plain Layout
- URI : in String := None);
- \end_layout
- \begin_layout Plain Layout
- \end_layout
- \begin_layout Plain Layout
- procedure Add_Author
- \end_layout
- \begin_layout Plain Layout
- (Entry_Source : in out Atom_Entry_Source;
- \end_layout
- \begin_layout Plain Layout
- Name : in String;
- \end_layout
- \begin_layout Plain Layout
- Base_URI : in String := None;
- \end_layout
- \begin_layout Plain Layout
- Email : in String := None;
- \end_layout
- \begin_layout Plain Layout
- Language : in String := None;
- \end_layout
- \begin_layout Plain Layout
- URI : in String := None);
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- There's actually a hint about the kind of XML element that is being produced
- by these procedures.
- If the name of the procedure starts with
- \emph on
- Set_
- \emph default
- then it hints at an XML element of which there's only ever one.
- So
- \emph on
- Set_Title
- \emph default
- creates a
- \emph on
- <title>Foo</title>
- \emph default
- element, and if called again, overwrites the previous value, whereas if
- the name of procedure starts with
- \emph on
- Add_
- \emph default
- then the Atom specification allows for multiples of these, as can be seen
- with the
- \emph on
- Add_Author
- \emph default
- procedure.
- Calling this one creates an
- \emph on
- <author>
- \emph default
- element, and calling it again simply adds one more author to the feed/entry/ent
- ry source.
- \end_layout
- \begin_layout Standard
- Most of the subprograms in this package deals directly with building the
- Atom XML, but there are a few exceptions, as you will see next.
- \end_layout
- \begin_layout Subsection
- Counting the amount of entries in a feed
- \end_layout
- \begin_layout Standard
- If you need to know how many entries that are currently in a feed, the you
- can use the
- \emph on
- Yolk.Syndication.Writer.Amount_Of_Entries
- \emph default
- function:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- function Amount_Of_Entries
- \end_layout
- \begin_layout Plain Layout
- (Feed : in Atom_Feed)
- \end_layout
- \begin_layout Plain Layout
- return Natural;
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Subsection
- Clearing and deleting entries
- \end_layout
- \begin_layout Standard
- There are two procedures available for clearing and deleting entries, one
- for clearing all entries away, and one for deleting entries based on their
- Id.
- Lets start with the one that clears out everything:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- procedure Clear_Entry_List
- \end_layout
- \begin_layout Plain Layout
- (Feed : in out Atom_Feed);
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- Calling
- \emph on
- Clear_Entry_List
- \emph default
- deletes every single entry that has been added to the
- \emph on
- Feed
- \emph default
- object so far.
- A less destructive procedure is
- \emph on
- Delete_Entry
- \emph default
- :
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- procedure Delete_Entry
- \end_layout
- \begin_layout Plain Layout
- (Feed : in out Atom_Feed;
- \end_layout
- \begin_layout Plain Layout
- Id : in String);
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- Using this one, you can delete all entries whose Id is
- \emph on
- Id
- \emph default
- .
- Note that the match must be exact, so case matters.
- FOO is not the same as foo.
- \end_layout
- \begin_layout Subsection
- Getting the Atom feed
- \end_layout
- \begin_layout Standard
- When you've added titles, authors, categories, entries and content to your
- feed, the next step is turning it into XML.
- This can be done in one of two ways:
- \end_layout
- \begin_layout Enumerate
- As string XML.
- \end_layout
- \begin_layout Enumerate
- As an XML/Ada DOM XML object.
- \end_layout
- \begin_layout Standard
- The string XML is obviously for the final audience, whereas the DOM XML
- is useful if you need to do some further work on the feed before releasing
- it on the world.
- Here they are:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- function Get_XML_DOM
- \end_layout
- \begin_layout Plain Layout
- (Feed : in Atom_Feed)
- \end_layout
- \begin_layout Plain Layout
- return DOM.Core.Document;
- \end_layout
- \begin_layout Plain Layout
- \end_layout
- \begin_layout Plain Layout
- function Get_XML_String
- \end_layout
- \begin_layout Plain Layout
- (Feed : in Atom_Feed;
- \end_layout
- \begin_layout Plain Layout
- Pretty_Print : in Boolean := False)
- \end_layout
- \begin_layout Plain Layout
- return String;
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- Note that if
- \emph on
- Pretty_Print
- \emph default
- is
- \emph on
- True
- \emph default
- then whitespace is going get mangled according to these rules:
- \end_layout
- \begin_layout Quote
- If Pretty_Print is true, then the XML nodes will be indented so that children
- nodes are to the right of their parents.
- It is set to False by default because its use changes the document (addition
- or removal of whitespaces among other things), which in general has no
- effect for automatic tools reading the document.
- All whitespaces are modified outside of elements containing nothing but
- text nodes.
- For text nodes, leading and trailing whitespaces are also deleted.
- \end_layout
- \begin_layout Standard
- \emph on
- Get_XML_String
- \emph default
- relies on the
- \emph on
- Write
- \emph default
- function from XML/Ada to generate its output, and the above quote is taken
- straight from the XML/Ada source comments.
- It's also worth noting that
- \emph on
- Get_XML_String
- \emph default
- and
- \emph on
- Get_XML_DOM
- \emph default
- both are pretty resource-hungry, so it's probably best to cache the results
- for later use, instead of calling them on each and every hit.
- \end_layout
- \begin_layout Section
- Yolk.Utilities
- \end_layout
- \begin_layout Standard
- This package contains various support functionality.
- \end_layout
- \begin_layout Section
- Yolk.Whoops
- \end_layout
- \begin_layout Standard
- This package contains one single procedure:
- \emph on
- Unexpected_Exception_Handler
- \emph default
- .
- I suspect the name gives away exactly what this procedure does.
- It looks like this:
- \end_layout
- \begin_layout Standard
- \begin_inset Box Frameless
- position "t"
- hor_pos "c"
- has_inner_box 1
- inner_pos "t"
- use_parbox 0
- use_makebox 0
- width "100col%"
- special "none"
- height "1in"
- height_special "totalheight"
- status open
- \begin_layout Plain Layout
- \begin_inset listings
- lstparams "basicstyle={\small\sffamily},frame=tblr,language=Ada,showstringspaces=false,tabsize=3,xleftmargin=1em,xrightmargin=1em"
- inline false
- status open
- \begin_layout Plain Layout
- procedure Unexpected_Exception_Handler
- \end_layout
- \begin_layout Plain Layout
- (E : Ada.Exceptions.Exception_Occurrence;
- \end_layout
- \begin_layout Plain Layout
- Log : in out AWS.Log.Object;
- \end_layout
- \begin_layout Plain Layout
- Error : AWS.Exceptions.Data;
- \end_layout
- \begin_layout Plain Layout
- Answer : in out AWS.Response.Data);
- \end_layout
- \end_inset
- \end_layout
- \end_inset
- \end_layout
- \begin_layout Standard
- You can use this procedure to catch any and all exceptions you've failed
- to catch in your application, ie.
- the ones AWS pickup and fail to do anything sensible with.
- When
- \emph on
- Unexpected_Reception_Handler
- \emph default
- catch an exception, two things happen:
- \end_layout
- \begin_layout Enumerate
- The exception is logged to the
- \emph on
- Yolk.Log
- \emph default
- .
- \emph on
- Error
- \emph default
- trace.
- \end_layout
- \begin_layout Enumerate
- A HTTP status code 500 is returned to the user.
- \end_layout
- \begin_layout Standard
- The template used to create the HTTP code 500 error message is
- \emph on
- demo/exe/templates/system/500.tmpl
- \emph default
- .
- You can of course change this to match the look and feel of your application.
- The path to the
- \emph on
- 500.tmpl
- \emph default
- file is set by the configuration setting
- \emph on
- System_Templates_Path
- \emph default
- .
-
- \end_layout
- \begin_layout Standard
- You can see an example on how to use this procedure in the file
- \emph on
- demo/src/yolk_demo.adb
- \emph default
- .
- \end_layout
- \end_body
- \end_document