Review: Sailing to Sarantium, by Guy Gavriel KaySeries: Sarantine Mosaic #1 Publisher: HarperPrism Copyright: 1998 Printing: January 2000 ISBN: 0-06-105990-0 Format: Mass market Pages: 533
Crispin is a well-respected mosaicist, a Rhodian, heir to a long tradition of artistic accomplishment. Rhodias is largely in ruins, and the kings that fight over its land are far removed the emperors of Rhodias at its height, but there's still demand for skilled craftsmanship. Crispin has a partner, assistants, and the opportunity to do at least adequate work. It's not a bad life, or at least wasn't before plague took his wife and daughters while he watched, helpless. Now, he's closed off, angry, and consumed by fatalism and futility.
His partner, Martinian, could never say why, when the imperious and obnoxious courier came from the far-off and half-legendary of Sarantium to summon him to assist with the rebuilding of the Sanctuary of Jad, he pretended not to be himself and pointed the courier at Crispin instead. Nor was Crispin entirely sure why he played along, although the courier was so arrogant and officious that he invited such treatment. He had no intention of going in Martinian's place and name until his friends intervened, united in their conviction that he needed something to focus on and a reason to live.
But nothing about Sarantium is simple. Even before Crispin leaves, the local queen, precariously balancing between warring factions, reveals her own reason to send Crispin to the capital of the far-off empire: using him as a desperate messenger to propose an alliance through marriage. And when he finally arrives, after unexpected perils on the road, he tumbles immediately into the deep complexities of the Sarantine court and its remarkable rulers.
Most of Guy Gavriel Kay's work is historical fiction with the serial numbers partly filed off and some magic added. The degree to which the serial numbers are removed varies by work; here, the history is obvious. Sarantium is Byzantium, fallen Rhodias is Rome, and the emperor Valerius and his former dancer empress Alixana are clearly Justinian and Theodora. Knowing that will provide a lot of context, but can also be distracting, since the temptation to scramble for Wikipedia and line things up with real history is strong. I read this book the first time without knowing the history and this second time knowing it. I think I enjoyed it a bit more on its own terms, instead of as a reflection and reinterpretation. Either way, though, it's one of Kay's best novels, which is saying quite a bit.
Sailing to Sarantium has two very different parts: Crispin's journey to Sarantium, and then what happens when he arrives. The first is a fairly linear travel narrative mixed with old religion, magic, and an experience in the woods that's a little disconnected from the rest of the story. The second is the fast-entangling politics and factionalism of the city itself, which wastes no time pulling Crispin into meetings with the most influential people at court.
In my memory, I liked the Sarantium narrative the best, and found the travel story less significant. Re-reading, I'm not sure I agree with my earlier self. Kay does write some of the best conversations in fiction; if you want to see careful verbal maneuvering or gut reactions with wide-ranging consequences, I can't think of any author who shows both the words and the nuances as well as Kay. He makes the court maneuvering feel truly epic. Watching Crispin's blunt competence cut through the Sarantine court, and seeing him stay focused on his life work despite all those distractions, is a truly rewarding experience. But that second part of the book also has some structural problems, and a few characterization problems.
The structural problem is that Kay wants to tell the same story from multiple angles, viewpoints, and timelines to show the reader every implication of the hornet's nest that Crispin kicks over, since quite a lot happens in the course of one day and night. This mostly works, but it is so laden with flashbacks, foreshadowing, and rewinds that I started losing track of the time relationship between the scenes. Kay is a very skilled author, so he avoids confusing the reader entirely, but I think he still tried too complex of a temporal structure here.
The characterization problem is that I previously wasn't paying as close of attention to Kay's portrayal of women and of male sexual reactions to women. It didn't bother me before; this time, it started getting on my nerves. Yes, this is historical fiction (although limitations on roles for women in history is rather overstated in fiction), and to give Kay credit it does feature a very strong female character in Alixana. But the male protector and female seducer dynamic is very strong, and all the women in this book seem to get shoehorned into it. And perhaps I'm missing some weakness that other men have, but I have never had the sort of overwhelming, thought-destroying reaction to the presence of a seductive woman as Kay's men seem to routinely have in this book. To give Crispin credit, he maneuvers his way through those conversations without doing anything stupid. (Kay's characters very rarely do stupid things, which is refreshing.) But the effort required started undermining my suspension of disbelief. Even making allowances for a culture that might consider a woman with her hair down the equivalent of an entirely nude woman, I simply don't believe that a man who had been married with two daughters, had a long career, and had the life experience Crispin had would have that much difficulty with an aggressively seductive woman that he already doesn't trust.
As a result, as much as I love Kay's political conversational fencing, I enjoyed the travel portion of the book more on this re-read. Crispin is a type of character Kay writes extremely well: an honest, honorable man trying to navigate unfamiliar waters without a lot of context, but with a firm sense of internal morality, a lot of natural intelligence, and a true passion for something. At one point in this book, another character decides to walk away from his current job and follow Crispin wherever he goes. Kay makes you believe that and want to do it yourself. It's a very rewarding experience as a reader to watch a character you can trust find careful, courageous, and tricky solutions to complicated problems.
But I think the best part of this book is Kay's ability to put Crispin's art, the creation of mosaics, on the page in a way that lets the reader viscerally appreciate it. Crispin is passionate about mosaics, about how to make them and how to think about them, and the passion is contagious and forms the heart and soul of this novel. Kay manages to make mosaics overshadow some of the most dramatic politics in history, which says quite a lot. There is almost nothing I love more than reading about talented, passionate people doing things they are extremely good at. I know nothing about mosaic that I haven't read in this book and its sequel, so I have no basis from which to judge the accuracy of Kay's portrayal, but he made me feel like I could appreciate some of the nuance, skill, and design constraints of the art form. It's a wonderful reading experience.
Sailing to Sarantium is best thought of half of a long book that was divided for publication reasons, so don't expect much of an ending here. It can only be read in combination with Lord of Emperors, which you'll want to have on hand when you finish this book so that you can continue the story.
Followed by Lord of Emperors.
Rating: 9 out of 10
Here is my monthly update covering what I have been doing in the free software world (previous month):
- Fixed a number of instances in the Django web development framework where methods had mutable defaults arguments such as lists or dictionaries. (#7253)
- Made a large number of improvements to travis.debian.net, my hosted service for projects that host their Debian packaging on GitHub to use the Travis CI continuous integration platform to test builds on every update:
- Worked with Evgeni Golov to run autopkgtest and autodep9 tests after builds. (#23, #24 & #25)
- Ensured that all remote branches are created locally so that packages that specify options such as pristine_tar=True in debian/gbp.conf work as expected. (commit)
- Fixed an issue where checking out other branches did not reliably not work due to Travis cloning the repository with --depth=50. (#21)
- Updated the documentation after prompting from Valerie Young. (db7238 & 470d24)
- Improved my Chrome extension for the FastMail web interface to collapse whitespace when appending to the subject. (#9)
- Submitted a pull request for the Handbrake video transcoder to make the build reproducible. (#320)
- Updated the configuration for my OpenWRT-based router (a device I use as a range extender and to save tedious reconfiguration of all my wifi devices in new locales) to enter a "fallback" mode if it cannot connect to the client network. This works around a longstanding "wontfix" upstream issue. (diff)
- Updated django-agpl, my reusable Django application to assist in releasing projects under the GNU Affero General Public License:
- Filed in issue in Mailvelope (a browser extension for OpenPGP encryption) to support composing/viewing messages in a fixed-width font. (#422)
- Blogged about how to write your first Lintian check as well as on the progress bar I added to Diffoscope.
Whilst anyone can inspect the source code of free software for malicious flaws, most Linux distributions provide binary (or "compiled") packages to end users.
The motivation behind the Reproducible Builds effort is to allow verification that no flaws have been introduced — either maliciously and accidentally — during this compilation process by promising identical binary packages are always generated from a given source.
I made the following improvements to our tools:
diffoscope is our "diff on steroids" that will not only recursively unpack archives but will transform binary formats into human-readable forms in order to compare them.
- Added a global Progress object to track the status of the comparison process allowing for graphical and machine-readable status indicators. I also blogged about this feature in more detail.
- Moved the global Config object to a more Pythonic "singleton" pattern and ensured that constraints are checked on every change.
- Display the "disordered" behaviour we intend to show on startup. (#837689)
- Support relative paths in command-line parameters (previously only absolute paths were permitted).
strip-nondeterminism is our tool to remove specific information from a completed build.
- Fix an issue where temporary files were being left on the filesystem and add a test to avoid similar issues in future. (#836670)
- Print an error if the file to normalise does not exist. (#800159)
- Testsuite improvements:
- Set the timezone in tests to avoid a FTBFS and add a File::StripNondeterminism::init method to the API to to set tzset everywhere. (#837382)
- "Smoke test" the strip-nondeterminism(1) and dh_strip_nondeterminism(1) scripts to prevent syntax regressions.
- Add a testcase for .jar file ordering and normalisation.
- Check the stripping process before comparing file attributes to make it less confusing on failure.
- Move to a lookup table for descriptions of stat(1) indices and use that for nicer failure messages.
- Don't uselessly test whether the inode number has changed.
- Run perlcritic across the codebase and adopt some of its prescriptions including explicitly using oct(..) for integers with leading zeroes, avoiding mixing high and low-precedence booleans, ensuring subroutines end with a return statement, etc.
I attended the Debian Bug Squashing Party (BSP) in Salzburg, Austria where 70+ "release-critical" bugs were fixed.
I attended NixOS user group in London, England.
Niels Thykier granted me commit access to the Lintian Git repository and I added myself to the debian/copyright there.
- rtl-sdr: Correct invocation of rm_conffile
- dh-haskell: Experimental push on scalar is now forbidden
- fortunes-es: Correct reference to $msg_installing_link
- webkit2pdf: FTBFS with dash as /bin/sh
- tj3: Cannot remove 'data/tjp.vim': No such file or directory
- greylistd: Fails to install in testing
- witty: Drop the build dependency on hardening-wrapper
- ruby-em-hiredis: Gem::LoadError: Could not find hiredis
- highlight.js: File `iftex.sty' not found
- transmission-remote-gtk: Option release requires an argument
This month I have been paid to work 12.75 hours on Debian Long Term Support (LTS). In that time I did the following:
- "Frontdesk" duties, triaging CVEs, etc.
- Issued DLA 608-1 for mailman fixing a CSRF vulnerability.
- Issued DLA 611-1 for jsch correcting a path traversal vulnerability.
- Issued DLA 620-1 for libphp-adodb patching a SQL injection vulnerability.
- Issued DLA 631-1 for unadf correcting a buffer underflow issue.
- Issued DLA 634-1 for dropbear fixing a buffer overflow when parsing ASN.1 keys.
- Issued DLA 635-1 for dwarfutils working around an out-of-bounds read issue.
- Issued DLA 638-1 for the SELinux policycoreutils, patching a sandbox escape issue.
- Enhanced Brian May's find-work --unassigned switch to take an optional "except this user" argument.
- Marked matrixssl and inspircd as being unsupported in the current LTS version.
- python-django 1:1.10.1-1 — New upstream release and ensure that django-admin startproject foo creates files with the correct shebang under Python 3.
- 19.6.0-5 — Don't call chown(2) if it would be a no-op to avoid failure under snap.
- 19.6.0-6 — Remove now-obsolete conffiles and logrotate scripts; they should have been removed in 19.6.0-3.
- 3.2.3-2 — Call ulimit -n 65536 by default from SysVinit scripts to normalise the behaviour with systemd. I also bumped the Debian package epoch as the "2:" prefix made it look like we are shipping version 2.x. I additionaly backported this upload to Debian Jessie.
- 3.2.4-1 — New upstream release, add missing -ldl for dladdr(3) & add missing dependency on lsb-base.
- python-redis (2.10.5-2) — Bump python-hiredis to Suggests to sync with Ubuntu and move to a machine-readable debian/copyright. I also backported this upload to Debian Jessie.
- adminer (4.2.5-3) — Move mysql-server dependencies to default-mysql-server. I also backported this upload to Debian Jessie.
- gpsmanshp (1.2.3-5) on behalf of the QA team:
- Move to "minimal" debhelper style, making the build reproducible. (#777446 & #792991)
- Reorder linker command options to build with --as-needed (#729726) and add hardening flags.
- Move to machine-readable copyright file, add missing #DEBHELPER# tokens to postinst and prerm scripts, tidy descriptions & other debian/control fields and other smaller changes.
I sponsored the upload of 5 packages from other developers:
- stressapptest (1.0.6-3) — Make the build reproducible. (#831587)
- zeroinstall-injector (2.12-1) — Fix FTBFS due to failing tests. (#837226)
- libisofs, libburn & libisoburn (1.4.6-1) — New upstream releases.
I also NMU'd:
- cfingerd (1.4.3-3.2) — Fix a FTBFS due to lack of "." in Perl's @INC. (#837267)
- dot-forward (0.71-2.1) — Make the build reproducible. (#776760)
- 8 packages to remove dependencies on hardening-wrapper and hardening-includes: switchsh, pwauth, grap, libmsn, libevocosm, passwordmaker-cli, srtp & netatalk.
- 12 packages that were using now-unsupported debhelper levels: freetable, alsamixergui, linklint, openjade, python-cddb, dh-kpatches, dsh, jfsuils, lpr, myspell & libxml-dumper-perl.
I filed 37 FTBFS bugs against csoundqt, cups-filters, dymo-cups-drivers, easytag, erlang-p1-oauth2, erlang-p1-sqlite3, erlang-p1-xmlrpc, erlang-redis-client, fso-datad, gnome-python-desktop, gnote, gstreamermm-1.0, gtkglextmm, gupnp-dlna, haskell-hmatrix-gsl, jdeb, kryo-serializers, libcmrt, libfso-glib, libmonitoring-livestatus-perl, librasterlite2, network-manager, print-manager, psychtoolbox-3, python-3to2, python-tidylib, recutils, slang2, snd, sugar, tj3, transmission-remote-gtk, vino, webkit2pdf, xml-core, xml-core & xml-core.
As a Debian FTP assistant I ACCEPTed 147 packages: alljoyn-services-1604, android-platform-external-doclava, android-platform-system-tools-aidl, aufs, bcolz, binwalk, bmusb, bruteforce-salted-openssl, cappuccino, captagent, chrome-gnome-shell, ciphersaber, cmark, colorfultabs, cppformat, dnsrecon, dogtag-pki, dxtool, e2guardian, flask-compress, fonts-mononoki, fwknop-gui, gajim-httpupload, glbinding, glewmx, gnome-2048, golang-github-googleapis-proto-client-go, google-android-installers, gsl, haskell-hmatrix-gsl, haskell-relational-query, haskell-relational-schemas, haskell-secret-sharing, hindsight, i8c, ip4r, java-string-similarity, khal, khronos-opencl-headers, liblivemedia, libshell-config-generate-perl, libshell-guess-perl, libstaroffice, libxml2, libzonemaster-perl, linux, linux-grsec-base, linux-signed, lua-sandbox, lua-torch-trepl, mbrola-br2, mbrola-br4, mbrola-de1, mbrola-de2, mbrola-de3, mbrola-ir1, mbrola-lt1, mbrola-lt2, mbrola-mx1, mimeo, mimerender, mongo-tools, mozilla-gnome-keyring, munin, node-grunt-cli, node-js-yaml, nova, open-build-service, openzwave, orafce, osmalchemy, pgespresso, pgextwlist, pgfincore, pgmemcache, pgpool2, pgsql-asn1oid, postbooks-schema, postgis, postgresql-debversion, postgresql-multicorn, postgresql-mysql-fdw, postgresql-unit, powerline-taskwarrior, prefix, pycares, pydl, pynliner, pytango, pytest-cookies, python-adal, python-applicationinsights, python-async-timeout, python-azure, python-azure-storage, python-blosc, python-can, python-canmatrix, python-chartkick, python-confluent-kafka, python-jellyfish, python-k8sclient, python-msrestazure, python-nss, python-pytest-benchmark, python-tenacity, python-tmdbsimple, python-typing, python-unidiff, python-xstatic-angular-schema-form, python-xstatic-tv4, quilt, r-bioc-phyloseq, r-cran-filehash, r-cran-png, r-cran-testit, r-cran-tikzdevice, rainbow-mode, repmgr, restart-emacs, restbed, ruby-azure-sdk, ruby-babel-source, ruby-babel-transpiler, ruby-diaspora-prosody-config, ruby-haikunator, ruby-license-finder, ruby-ms-rest, ruby-ms-rest-azure, ruby-rails-assets-autosize, ruby-rails-assets-blueimp-gallery, ruby-rails-assets-bootstrap, ruby-rails-assets-bootstrap-markdown, ruby-rails-assets-emojione, ruby-sprockets-es6, ruby-timeliness, rustc, skytools3, slony1-2, snmp-mibs-downloader, syslog-ng, test-kitchen, uctodata, usbguard, vagrant-azure, vagrant-mutate & vim.
At the end of August 2012, I announced my Early Retirement from HP. Two years later, my friend and former boss Martin Fink successfully recruited me to return to what later became Hewlett Packard Enterprise, as an HPE Fellow working on open source strategy in his Office of the CTO.
I'm proud of what I was was able to accomplish in the 25 months since then, but recent efforts to "simplify" HPE actually made things complicated for me. Between the announcement in late June that Martin intended to retire himself, and the two major spin-merger announcements involving Enterprise Services and Software... well...
The bottom line is that today, 30 September 2016, is my last day at HPE.
My plan is to "return to retirement" and work on some fun projects with my wife now that we are "empty nesters". I do intend to remain involved in the Free Software and open hardware worlds, but whether that might eventually involve further employment is something I'm going to try and avoid thinking about for a while...
There is a rocket launch scheduled nearby this weekend, after all!