This article summarizes some best practices to consider when taking your project to open source either on GitHub or some other public source code repository.
This article summarizes some best practices to consider when taking your project to open source either on GitHub or some other public source code repository.
Rocket Lab secretly launched a disco ball satellite on its latest test flight – The Verge
I’m quite conflicted about this — I think I like it:
Shaped a bit like a disco ball, the Humanity Star is a 3-foot-wide carbon fiber sphere, made up of 65 panels that reflect the Sun’s light. The satellite is supposed to spin in space, too, so it’s constantly bouncing sunlight. In fact, the probe is so bright that people can see it with the naked eye. The Humanity Star’s orbit also takes it all over Earth, so the satellite will be visible from every location on the planet at different times. Rocket Lab has set up a website that gives real-time updates about the Humanity Star’s location. People can find out when the satellite will be closest to them, and then go outside to look for it. The goal of the project is to create “a shared experience for all of humanity,” according to Rocket Lab.
(tags: rocket-lab disco-balls satellites humanity-star orbit space)
oh my.
(tags: 3d-printing art history british-museum models cool)
‘DolphinAttack: Inaudible Voice Commands’ [pdf]
‘Speech recognition (SR) systems such as Siri or Google Now have become an increasingly popular human-computer interaction method, and have turned various systems into voice controllable systems(VCS). Prior work on attacking VCS shows that the hidden voice commands that are incomprehensible to people can control the systems. Hidden voice commands, though hidden, are nonetheless audible. In this work, we design a completely inaudible attack, DolphinAttack, that modulates voice commands on ultrasonic carriers (e.g., f > 20 kHz) to achieve inaudibility. By leveraging the nonlinearity of the microphone circuits, the modulated low frequency audio commands can be successfully demodulated, recovered, and more importantly interpreted by the speech recognition systems. We validate DolphinAttack on popular speech recognition systems, including Siri, Google Now, Samsung S Voice, Huawei HiVoice, Cortana and Alexa. By injecting a sequence of inaudible voice commands, we show a few proof-of-concept attacks, which include activating Siri to initiate a FaceTime call on iPhone, activating Google Now to switch the phone to the airplane mode, and even manipulating the navigation system in an Audi automobile. We propose hardware and software defense solutions. We validate that it is feasible to detect DolphinAttack by classifying the audios using supported vector machine (SVM), and suggest to re-design voice controllable systems to be resilient to inaudible voice command attacks.’ via Zeynep (https://twitter.com/zeynep/status/956520320504123392)
(tags: alexa siri attacks security exploits google-now speech-recognition speech audio acm papers cortana)
Targeted Audio Adversarial Examples
This is phenomenal:
We have constructed targeted audio adversarial examples on speech-to-text transcription neural networks: given an arbitrary waveform, we can make a small perturbation that when added to the original waveform causes it to transcribe as any phrase we choose. In prior work, we constructed hidden voice commands, audio that sounded like noise but transcribed to any phrases chosen by an adversary. With our new attack, we are able to improve this and make an arbitrary waveform transcribe as any target phrase.The audio examples on this page are impressive — a little bit of background noise, such as you might hear on a telephone call with high compression, hard to perceive if you aren’t listening out for it. Paper here: https://arxiv.org/abs/1801.01944 (Via Parker Higgins, https://twitter.com/xor )
(tags: papers audio adversarial-classification neural-networks speech-to-text speech recognition voice attacks exploits via:xor)
We have spent an highly pleasant time together at the Alfresco DevCon 2018 and here are some thoughts about my experience and my contributions at this huge event.
UPDATE LOG: As Richard Esplin kindly mentioned in the comment, I have updated the section about the future of Share with the correct message. Sorry for this and thanks to Richard for reading my article and for proposing this correction. I have also added something about the recent involvement of the community in the ADF roadmap.
The day before the beginning of this event, me and Luis enjoyed a very good dinner at LX Factory together with other fabulous Alfresco Community Stars. We have tasted different kind of starters and I have personally tried a huge and tasty Portuguese Burger with different spices and a nice beer served in a very long glaaaaaaaaas, check out the photo below:
Nathan McMinn, Axel Faust, Luis Cabaceira, PJ, Jeff Potts and Boriss Mejias. Thanks Nathan for this epic shot!
We have signed as TAI Solutions a partnership agreement with ECMCoreAveri and we have started to collaborate together for creating and delivering worldwide training courses around the Alfresco Digital Business Platform.
During the first day I contributed as an International Certified Alfresco Instructor for delivering the course about all the basics of the Alfresco Platform development.
We held a class with 50 attendees on all the Alfresco fundamentals covering Alfresco Content Services and Alfresco Process Services. Finally at the end of the day Ole Hejlskov (Developer Evangelist at Alfresco) described the ADF approach.
I have personally edited the material with related labs and I held the session in the classroom about the following topics:
The course was held by me, Shoeb Sarguroh and Oliver Laabs but in the room there were also other people for supporting attendees for any need:
This training day has gone very well even if we had some issues with the WIFI network, we resolved using my clean Maven repository built from scratch for this course and then we copied it into some USB keys. This allowed every attendee to correctly use the Alfresco SDK and then to complete all the required labs.
I would like to thank all the involved people in the training room, my colleague Shoeb and Oliver but also Sabine, Kevin and Darryl helped a lot during labs.
Delivering training courses with so many different language speaking people, it is every time challenging, not only for us as instructors but also for attendees!
Thank you to all the attendees for kindly listening this huge amount of informations that are rained on you :)
ECMCoreAveri International Instructors Team: me, Sabine, Shoeb, Oliver and Cristina. Thanks to Cristina for this great shot :)
During the last day, and before my session, Alfresco together with the Order of the Bee gave an Alfresco VIP Award to 20 community members around the world. For each one they have shared the main reason and the goal achieved in terms of contribution for the nomination.
I received this unexpected Alfresco VIP Award for all my contributions in different Open Source projects and communities and for improving interoperability among these ecosystems.
This is so awesome and I would like to thank Alfresco and all the members inside the Board of the Order of the Bee for this important recognition of my work around communities!
Thank you so much to Alfresco and the Order of The Bee! Very appreciated ^__^
The Alfresco VIP Award received from Alfresco and the Order of the Bee. Thank you so much!!! :)
During the last day I held the session with my friend Luis Cabaceira about content migration using Apache ManifoldCF.
We had the honor to be introduced on the stage by Nathan McMinn (Senior Director of Premiere Services at Alfresco) and we received a lot of interesting feedbacks about our presentation from partners and customers and if you need more informations about it, please feel free to contact me.
I would like to also thank Nathan for having mentioned us in his retrospective shared in the community forums.
We can summarize our presentation on the following topics:
Me and Luis during our session introducing content migration with Apache ManifoldCF
At the end of our presentation Nathan said: <<You guys are some kind of Starsky and Hutch for content migration!!!>> and then I had to create the following meme for commemorating this cool moment :)
As you probably know I'm a videogamer and you can imagine how much I was enthusiastic when I saw John Newton mentioning Destiny 2 as a very good example of design of a potential and real user interface.
The benefit of the interaction between a Guardian in Destiny and his own Ghost (this is the name of his intelligent mini drone) allows him to be focused on the action, leaving to the Ghost any further suggestion for the next step to accomplish during his mission.
Bungie has integrated the Ghost with Amazon Alexa and this means that you practically could have a real Ghost near you, while you are playing the game. You can talk to your Ghost to interact with the game in real time and changing your equipment with a voice command.
We should spend some words on Bungie that has done a very good job also in terms of designing the public API around the game. This good approach allowed developers to implement different applications using part of the entire game repository around the user assets.
Considering the overall conference, I have to confess that there were an impressive amount of interesting sessions that it was impossible to follow at the same time. I'm looking forward to take a look at these presentations and videos when they will be published on the DevCon website.
It's clear that the future of Alfresco platform is even more related to DevOps approaches with a brand new vision for UX. We have to consider that Alfresco is investing and bringing the previous effort from Share to new standard frameworks to improve the adoption.
Having a huge crowd of developers that can easily create apps on top of Alfresco using skills that now we found in the market can be very effective and I agree with this approach. I would have only wanted more community involvement before pulling ADF out of the cylinder.
Anyway I'm very happy to see that now we have an active discussion with the community about the future of ADF. The discussion started from a simple tweet by Jeff for passing to Bindu and then Mario. If you take a look at what the community is doing it is simply awesome! Great job to everyone from Alfresco guys to community members :)
Alfresco Share is not actually deprecated but considering that is a ready to use application for achieving some generic and common collaboration functionalities, they consider this good enough for making easier an initial adoption of the platform.
I personally think that every time in Content Services and ECM area, it is hard to find a customer / use case that can fit with a generic user interface. Typically it makes sense to work on specific requirements aligned with functionalities across roles and the entire enterprise organization.
What we can expect from this new point of view is trying to bring different UX experiences built with a community approach but vertically specific for each industry or set of needed capabilities.
The new Application Developer Framework (ADF) is starting to be the supported and suggested way for implementing your own front-end apps. And here we see that all the previous energy invested in Share now is all focused on ADF that will be also supported by Alfresco itself.
Finally I want just to say that it was so fun to exchange opinions and considerations about the market and all the different aspects around Alfresco with all of you during the break, lunch and dinner.
Thank you all for having spent great moments together! See you at the next Alfresco DevCon!
I'll update this post as soon as possible with new photos and all the material related to our session with the presentation and the demo videos when it will be published from Alfresco.
Stay tuned ;)
Nathan McMinn, Axel Faust, Luis Cabaceira, PJ, Jeff Potts and Boriss Mejias. Thanks a lot to Nathan McMinn for this epic shot!
Me, Sabine, Shoeb, Oliver and Cristina. Thanks to Cristina for this great shot :)
Thanks a lot to Nathan McMinn for this epic shot!
Thanks to sprouvez for this great shot!
This meme was created after our presentation for a comment made by Nathan: <<You guys are some kind of Starsky and Hutch for content migration!!! >>
Remote Code Execution on the Smiths Medical Medfusion 4000 Infusion Pump
‘Between March and June of 2017 I spent around 400 hours of personal time analyzing the Smiths Medical Medfusion 4000 infusion pump for security vulnerabilities. The devices analyzed had software versions 1.1.2 and 1.5.0. The flaws discovered (the most critical of which was a DHCP buffer overflow in the MQX operating system used) were disclosed in a coordinated fashion and are detailed by ICS-CERT in ICSMA-250-02A and CERT in VU#590639. The goal of this exercise was to help protect patients that rely on therapy provided by the pump, to raise awareness of the risk present in unpatched versions of the device, and, finally, to contribute to the corpus of embedded/IoT security research.’
(tags: medical infusion-pumps security iot safety exploits embedded-systems reversing)
Writeup of one of the classic tape loaders used on the ZX Spectrum, both for fast loading and piracy protection
(tags: piracy reverse-engineering history zx-spectrum tape loaders gremlin)
The 29 Stages Of A Twitterstorm In 2018
’14. Then suddenly there are Nazis everywhere.’
(tags: twitter twitterstorms funny 2018 nazis alt-right memes)
![]() |
| Camel in Action Website |
| Camel 2.5.0 | Camel 2.20.1 |
|---|---|
| >80 components | >280 components |
| 482,779 LOC | 1307016 LOC |
| 23 named contributors | 497 named contributors |
"To the Apache Camel community - may this book be a helpful companion on your journeys with Camel"
OK, sports fans, here we go!
A Look Inside Salesforce Tower
Get an inside look through the eyes of an employee working in the building!
Last month our 2010 27″ iMac stopped working. There was no drama, just a black screen where previously had been the High Sierra backdrop. A quick bit of investigation showed that it wasn’t as simple as a dead machine. The fans still blew and when turned off and on it made all the expected noises. There was just no picture. Plugging in an external monitor soon showed that the machine was usable and still functioning normally. After 7 years of service it seemed as if the LCD panel had finally failed.
The law of murphy stalks all such events and this time was no different. We’re in the midst of building a house so buying a replacement iMac wasn’t really an option. Looking at the pricing and specifications the offerings, none seemed like value for money – even if we had the money and wanted to splash out. However, as the machine was my wifes day to day workhorse, we would soon miss the abilities it offered. A solution was needed.
When I built my desktop computer 15 months ago I chose standard, well supported components. Given the travel my work entails it often sits idle, so a possible low cost solution would have been for my wife to use my machine. Her MacBook Air is very old and frankly not very pleasant to use for anything beyond mail and surfing the web while my laptop is more than capable. Of course, my desktop runs Windows and she is happier with the world of Apple. But maybe…
Hackintosh is a term I’ve seen a lot, but when I last looked it was very complex and involved a lot of jumping through hoops and using very specific components. Looking again in 2017 revealed how far things had evolved. A lot of reviews and blogs talked about success dual booting a single, home built machine with OSX and Windows. They all mentioned the tonymacx86 website which has a lot of information, tutorials and downloads to help.
Using a monitor I found a suitable USB memory stick, registered with tonymacx86, downloaded the files and shortly afterwards had the USB stick ready for a try. I’ll be honest, I didn’t expect much when I plugged it and powered up my desktop. The black screen with the Apple logo was a surprise. The progress bar slowly filling in was an even bigger surprise but when I was asked to choose an installation language I was glad to be sitting. Perhaps this could work?
Needing somewhere to install OSX on my desktop I found an older disk and after moving some wiring around had it installed and ready to receive OSX. Powering up again and going through the installtion instructions from the tonymacx86 website proved to be childs play and it didn’t take long for the install to commence. The reboots took me a little by surprise, but the process ran without any issues and soon I was filling in usernames and viewing the High Sierra backdrop.
Was everything perfect? No. That would have been too much to expect but I was sitting wondering what I was missing as up to this point it had been too simple.
Continuing with the tonymacx86 installation instructions I ran the MultiBeast app. This presented the first questions that caused me to pause. What drivers did I actually need? Looking at the OSX Preferences app it was clear no network or sound card had been recognised, so drivers would be needed for those. Ticking the boxes that seemed applicable and installing the Clover bootloader all went as expected and I rebooted – to a black screen.
This was, ironically, the same situation as the existing iMac – a responsive computer with a black screen. The fact it had worked previously meant it wasn’t a total roadblock and after some research I copied the USB stick EFI folder over the same folder on the installed bootloader. Rebooting rewarded me with a login screen and working network! The sound card had been recognised and was listed but as my sound is via the HDMI cable I still wasn’t hearing anything. Having a 4K monitor on my desktop has been great, but when running OSX it wasn’t great as the font size was far too small. Without a way to change the display font using the machine was mildly frustrating despite the change from the i3 2010 processor to the i7 2016 processor being very evident.
I tried a few things but wasn’t able to get the sound working via HDMI after trying a large number of different approaches outlined by people. The community seems to be gaining cohesion and the tools are certaiinly improving but I still found myself looking at version incompatibilities, outdated and incomplete instructions that were often filled with abbreviations that meant nothing to me. Clover is an interesting tool but isn’t as user friendly as many claim it to be.
We discovered a fix for the black screen on the iMac during this process. It was a bug related to the iMac goiong to sleep. Armed with this knowledge we were able to restore it to full working order, removing the need for me to continue. While I haven’t taken this any further when the iMac does eventually cease to be usable I will seriously consider building a Hackintosh. A quick costing with suitable components showed that it would save around £1000 over a comparable iMac, resulting in a machine that could be expanded and upgraded.
For the last few years my favorite web site had become The Awl.
And now, no more.
Bummer.
I hope all those EXTREMELY talented writers and editors find good new locations elsewhere.
One of the challenges of running large scale distributed systems is being able to pinpoint problems. It’s all too common to blame a random component (usually a database) whenever there’s a hiccup even when there’s no evidence to support the claim. We’ve already discussed the importance of monitoring tools, graphing and alerting metrics, and using distributed tracing systems like ZipKin to correctly identify the source of a problem in a complex system.
Once you’ve narrowed down the problem to a single system, what do you do? To figure this out, it’s going to depend on the nature of the problem, of course. Some issues are temporary, like a dead disk. Some are related to a human-introduced change, like a deployment or a wrong configuration setting. These have relatively straightforward solutions. Replace the disk, or rollback the deployment.
What about problems that are outside the scope of a simple change? One external factor that we haven’t mentioned so far is growth. Scale can be a difficult problem to understand because reproducing the issue is often nuanced and complex. These challenges are sometimes measured in throughput, (requests per second), size (terabytes), or latency (5ms p99). For instance, if a database server is able to serve every request out of memory, it may get excellent throughput. As the size of the dataset increases, random lookups are more and more likely to go to disk, decreasing throughput. Time Window Compaction Strategy is a great example of a solution to a scale problem that’s hard to understand unless the numbers are there. The pain of compaction isn’t felt until you’re dealing with a large enough volume of data to cause performance problems.
During the times of failure we all too often find ourselves thinking of the machine and its processes as a black box. Billions of instructions executing every second without the ability to peer inside and understand its mysteries.
Fortunately, we’re not completely blind as to what a machine is doing. For years we’ve had tools like debuggers and profilers available to us. Oracle’s JDK offers us Java Flight Recorder, which we can use to analyze running processes locally or in production:

Profiling with flight recorder is straightforward, but interpreting the results takes a little bit of work. Expanding the list of nested tables and looking for obvious issues is a bit more mental work than I’m interested in. It would be a lot easier if we could visualize the information. It requires a commercial license to use in production, and only works with the Oracle JDK.
That brings us back to the subject of this post: a way of generating useful visual information called a flame graph. A flame graph let’s us quickly identify the performance bottlenecks in a system. They were invented by Brendan Gregg. This is also part one of a very long series of performance tuning posts, we will be referring back to it as we dive deeper into the internals of Cassandra.
The approach we’ll examine in this post is utilizing the Swiss Java Knife, usually referred to as SJK, to capture the data from the JVM and generate the flame graphs. SJK is a fantastic collection of tools. Aside from generating flame graphs, we can inspect garbage collection statistics, watch threads, and do a variety of other diagnostic tasks. It works on Mac, Linux, and both the Oracle JDK and the OpenJDK.
I’ve downloaded the JAR, put it in my $HOME/bin and set up a shell function to call it easily:
sjk () {
java -jar ~/bin/sjk-plus-0.8.jar "$@"
}
On my laptop I’m running a workload with cassandra-stress. I’ve prepopulated the database, and started the stress workload with the following command:
cassandra-stress read n=1000000
For the first step of our analysis, we need to capture the stack frames of our running Java application using the stcap feature of SJK. To do this, we need to pass in the process id and the file to which we will dump the data. The dumps are written in a binary format that we’ll be able to query later:
sjk stcap -p 92541 -i 10ms -o dump.std
Then we can analyze the data. If all we have is a terminal, we can print out a histogram of the analysis. This can be pretty useful on it’s own if there’s an obvious issue. In this case, we can see that a lot of time is spent in sun.misc.Unsafe.park, meaning threads are just waiting around, parked:
$ sjk ssa -f dump.std --histo
Trc (%) Frm N Term (%) Frame
372447 96% 372447 0 0% java.lang.Thread.run(Thread.java:745)
309251 80% 309251 309251 80% sun.misc.Unsafe.park(Native Method)
259376 67% 259376 0 0% java.util.concurrent.locks.LockSupport.park(LockSupport.java:304)
254388 66% 254388 0 0% org.apache.cassandra.concurrent.SEPWorker.run(SEPWorker.java:87)
55709 14% 55709 0 0% java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
52374 13% 52374 0 0% org.apache.cassandra.concurrent.NamedThreadFactory$$Lambda$6/1758056825.run(Unknown Source)
52374 13% 52374 0 0% org.apache.cassandra.concurrent.NamedThreadFactory.lambda$threadLocalDeallocator$0(NamedThreadFactory.java:81)
44892 11% 44892 0 0% io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:138)
44887 11% 44887 0 0% java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
42398 11% 42398 0 0% io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:409)
42398 11% 42398 0 0% io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858)
42398 11% 42398 0 0% io.netty.channel.nio.NioEventLoop.select(NioEventLoop.java:753)
42398 11% 42398 0 0% sun.nio.ch.KQueueArrayWrapper.poll(KQueueArrayWrapper.java:198)
42398 11% 42398 0 0% sun.nio.ch.KQueueSelectorImpl.doSelect(KQueueSelectorImpl.java:117)
42398 11% 42398 42398 11% sun.nio.ch.KQueueArrayWrapper.kevent0(Native Method)
42398 11% 42398 0 0% sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
42398 11% 42398 0 0% sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
Now that we have our stcap dump, we can generate a flame graph with the following command:
sjk ssa --flame -f dump.std > flame-sjk.svg
When you open the SVG in a browser, you should end up with an image which looks something like this:

If you open the flame graph on your machine you can mouse over the different sections to see the method call and percentage of time it’s taking. The wider the bar, the more frequent it’s present in the stacks. It’s very easy to glance at the graph to understand where the time is spent in our program.
This is not the only technique for generating flame graphs. Brendan Gregg has a long list of links and references I recommend reading at the bottom of his FlameGraph page. I intend to write a utility to export the SJK format to the format that Brendan uses on his blog as it’s a little nicer to look, has a better mouseover, supports drill down, and has a search. They also support differential flame graphs, which are nice if you’re doing performance comparisons across different builds.
I hope you’ve enjoyed this post on visualizing Cassandra’s performance using FlameGraphs. We’ve used this tool several times with the teams we’ve worked with to tune Cassandra’s configurations and optimize performance. In the next post in this series we’ll be examining how to tune garbage collection parameters to maximize throughput while keeping latency to a minimum.
sys-firmware/intel-microcode package. It's now easier than ever to update microcode automatically early on boot. This is a valuable alternative to shipping microcode within the BIOS. I mean honestly, who regularly checks for BIOS updates? Much easier by doing that through an ebuild.initramfs now builds a cpio archive at /boot/intel-uc.img ready to be used by grub. In /boot/grub/grub.cfg:menuentry 'Gentoo Linux 4.14' {
root=hd0,1
linux /boot/linux-4.14.12 root=LABEL=ROOT ro rootfstype=ext4 net.ifnames=0
initrd /boot/intel-uc.img /boot/initrd.img
}
Note how the microcode intitramfs is simply prepended to the boot initramfs (initrd). A kernel that has microcode laoding support enabled will find it there, upload the microcode into the cpu and then discard the initramfs blob, and continue booting with the initrd.img. The first line in your dmesg output will show:
microcode: microcode updated early to revision 0x80, date = 2018-01-04
Andy Weir had the debut novel sensation that, surely, every novelist dreams of: The Martian was a world-wide best-seller, stayed on the best-seller lists for almost two years, and was then adapted to become one of the top ten movies of 2015.
You can only imagine what a life-changing experience this must have been for a guy who spent 15 years writing novels while working full time.
Anyway, Weir is now back with his second novel: Artemis.
In various creative fields, people talk about the "sophomore slump", and it surely can't have been easy for Weir to figure out how he wanted to write his next book. I'm sure he was also feeling pressure from both his readers and his publisher to hurry up and deliver another book.
So he did.
Artemis is certainly not the book that The Martian was.
However, both as a standalone effort and as a companion piece, it is quite interesting.
And, as you should probably grow to expect from Weir, it's a rollicking roller-coaster adventure ride of a book.
But while The Martian was a book about humans who were in space, and wanted to get back to Earth, Artemis is a book about people who were on Earth, and have decided that they want to live in space.
Weir is very interested in the notion of what it would mean for humans to be living somewhere other than on Earth, which is indeed a fascinating thing to think about, and Artemis is of most interest when you look at it from that viewpoint.
Artemis, as it turns out, spends most of its time spinning tales of completely ordinary experiences that have much more to do with being human beings, than with being in outer space. Rather than being just a sterile laboratory occupied by scientists, as so many "outer space" books are, Weir's outer space civilization is full of everything that makes us human. There are bars, casinos, and night clubs; there are prostitutes, drug dealers, and smugglers; there are petty rivalries, dirty laundry, and double-dealing.
But, most of all, there are complex systems, and, as was true with The Martian, it is when dealing with interesting complex systems that Weir's book is at its most interesting (even if great literature it ain't):
He wiggled his hand. "That wasn't just you. There were a lot of engineering failures. Like: Why aren't there detectors in the air pipeline for complex toxins? Why did Sanchez store methane, oxygen, and chlorine in a room with an oven? Why doesn't Life Support have its own separate air partition to make sure they'll stay awake if the rest of the city has a problem? Why is Life Support centralized instead of having a separate zone for each bubble? These are the questions people are asking.
Moreover, as Weir observes, these aren't actually engineering questions at their root; they are questions about how we organize our societies, a question which is just as important and relevant in outer space as it is here on Earth:
"The next big step is taxes.""Taxes?" I snorted. "People come here because they don't want to pay taxes."
"They already pay taxes -- as rent to KSC. We need to change over to a property-ownership and tax model so the city's wealth is directly tied to the economy. But that's not for a while."
She took off her glasses. "It's all part of the life-cycle of an economy. First it's lawless capitalism until that starts to impede growth. Next comes regulation, law enforcement, and taxes. After that: public benefits and entitlements. Then, finally, overexpenditure and collapse."
"Wait. Collapse?"
"Yes, collapse. An economy is a living thing. It's born full of vitality and dies once it's rigid and worn out. Then, through necessity, people break into smaller economic groups and the cycle begins anew, but with more economies. Baby economies, like Artemis is right now."
Although Artemis ultimately fails as a work of literature, it is promising as a hint of what Weir is interested in, and where he might go.
Humans in space is a fascinating concept, and thinking about it realistically, rather than in some fantastic sterile implausible laboratory fashion, is how we're going to get to a point where we're actually ready to have humans in space. Building space ships and sending people out in them is just an engineering problem, and we'll solve that, probably pretty soon. But economics, politics, crime, government? These are actually HARD problems.
Writing about them, thinking about them, sharing those ideas, is one way to make it real, and for that, if for nothing else, I enjoyed reading Artemis and will look forward to Weir's next work.
A short lesson, this time; perhaps our education is nearing completion and we are moving on to become graduate students?
Clearlake Capital Acquires Perforce Software
Clearlake Capital Group, L.P. (together with its affiliates, “Clearlake”) today announced that it has acquired Perforce Software (“Perforce” or the “Company”), developer of the industry’s most flexible, scalable and secure version control and collaboration platform, from growth equity investor Summit Partners. The Company will continue to be led by Janet Dryer, CEO, and Mark Ties, COO, who will both join the Board of Directors alongside Clearlake. Financial terms were not disclosed.

What impact on latency should you expect from applying the kernel patches for the Meltdown security vulnerability?
TL;DR expect a latency increase of at least 20% for both reads and writes.
The Meltdown vulnerability, formally CVE-2017-5754, allows rogue processes to access kernel memory. Simple demonstrations have already appeared online on how to expose passwords and ssh private keys from memory. The consequences of this, in particular on shared hosts (ie cloud) are considered “catastrophic” by security analysts. Initially discovered in early 2017, the vulnerability was planned to be publicly announced on the 9th January 2018. However, due to the attention generated by the frequency of Linux kernel ‘page-table isolation’ (KPTI) patches committed late in 2017 the news broke early on 3rd January 2018.
Without updated hardware, the Linux kernel patches impact CPU usage. While userspace programs are not directly affected, anything that triggers a lot of interrupts to the CPU, such as a database’s use of IO and network, will suffer. Early reports are showing evidence of CPU usage taking a hit between 5% and 70%. Because of the potential CPU performance hit and lack of evidence available, The Last Pickle used a little time to see what impacts we could record for ourselves.
The hardware used for testing was a Lenovo X1 Carbon (gen 5) laptop. This machine runs an Intel Core i7-5600U CPU with 8Gb RAM. Running on it is Ubuntu 17.10 Artful. The unpatched kernel was version 4.13.0-21, and the patched kernel version 4.13.0-25. A physical machine was used to avoid the performance variances encountered in the different cloud environments.
The Ubuntu kernel was patched according to instructions here and the ppa:canonical-kernel-team/pti repository.
A simple schema, but typical of many Cassandra usages, was used on top of Cassandra-3.11.1 via a 3 node ccm cluster. The stress execution ran with 32 threads. Running stress, three nodes, and a large number threads on one piece of hardware was intentional so to increase thread/context switching and kernel overhead.
The stress run was limited to 5k requests per second so to avoid saturation, which occurred around 7k/s. The ratio of writes to reads was 1:1, with reads being split between whole partitions and single rows. The table used TWCS and was tuned down to 10 minute windows, so to ensure compactions ran during an otherwise short stress run. The stress ran for an hour against both the unpatched and patched kernels.
ccm stress user profile=stress.yaml ops\(insert=2,by_partition=1,by_row=1\) duration=1h -rate threads=32 throttle=5000/s -graph file=meltdown.html title=Meltdown revision=cassandra-3.11.1-unpatched
The following graphs show that over every percentile a 20%+ latency increase occurs. Sometimes the increase is up around 50%.




The full stress results are available here.

Jim Jagielski—My 2017-2018 IntrospectionsAs the old year falls away and the new year boots up, it is traditional for people to write "old year retrospectives" as well as "new year predictions." Heck, I originally envisioned this entry as a duet of 2 separate blogs. But as much as I tried, it was just too difficult to keep them distinct and self-contained. There was simply too much overlap and as much as I expect "new things" in 2018, I think 2018 will mostly be a solidification of events and issues ramped up from 2017.
So with all that in mind, I present my 2017-2018 Introspections... in no particular order:
Continue reading "My 2017-2018 Introspections"
This blog post of mine was initially published by Computerworld UK in 2010.
As open source comes of age and becomes mainstream, more and more job postings include “open source skills” in their requirements.
But do you really want to hire someone who spends their time exchanging flames with members of their own community in public forums? Someone who greets newcomers with “I have forwarded your question to /dev/null, thanks” and other RTFM answers?
Luckily, open source communities are not just about being rude and unwelcoming to strangers. Most of them are not like that at all, and the skills you learn in an open source community can make a big difference in a corporate environment as well.
One very important skill that you learn or improve in an open source community is to express yourself clearly in written form. The mailing lists or forums that we use are very limited compared to in-person communications, and extra care is required to get your message through. Being concise and complete, disagreeing respectfully, avoiding personal attacks and coping with what you perceive as personal attacks are all extremely useful skills on the job. Useful skills for your whole life actually.
Once you master asynchronous written discussions as a way to build group consensus, doing the same in a face to face meeting can be much easier. But the basic skills are the same, so what you learn in an open source community definitely helps.
Travel improves the mind, and although being active in open source can help one travel more, even without traveling you’ll be exposed to people from different cultures, different opinions, people who communicate in their second or third language, and that helps “improve your mind” by making you more tolerant and understanding of people who think differently.
Not to mention people who perceive what you say in a different way than you expected – this happens all the time in our communities, due in part to the weak communications channels that we have to use. So you learn to be extra careful with jokes and sneaky comments, which might work when combined with the right body language, but can cause big misunderstandings on our mailing lists. Like when you travel to places with a different culture.
Resilience to criticism and self-confidence is also something that you’ll often develop in an open source community. Even if not rude, criticism in public can hurt your ego at first. After a while you just get used to it, take care of fixing your actual mistakes if any, and start ignoring unwarranted negative comments. You learn to avoid feeding the troll, as we say. Once your work starts to produce useful results that are visible to the whole community, you don’t really care if someone thinks you’re not doing a good job.
The technical benefits or working in open source communities are also extremely valuable. Being exposed to the work and way of thinking of many extremely bright developers, and quite a few geniuses, definitely helps you raise the bar on what you consider good software. I remember how my listening skills improved when I attended a full-time music school for one year in my youth: just listening to great teachers and fellow students play made me unconsciously raise the bar on what I consider good music.
Open source communities, by exposing you to good and clever software, can have the same effect. And being exposed to people who are much better than you at certain things (which is bound to happen for anybody in an open source project) also helps make you more humble and realistic about your strengths and weaknesses. Like in soccer, the team is most efficient when all players are very clear about their own and other players’ strengths and weaknesses.
You’ll know to whom you should pass or not pass the ball in a given situation.
To summarise, actively participating in a balanced open source community will make you a better communicator, a more resilient and self-confident person, improve your technical skills and make you humbler and more realistic about your strengths and weaknesses.
This blog post of mine was initially published by Computerworld UK in 2010.
I’m amazed at how many so-called “enterprise software systems” do not embrace the Web model in 2010, making them way much harder and much less fun to use than they should be.
I have recently started making parallels between this and music teachers, and the analogy seems to work. Don’t ask where the parallel comes from…weird connections in my brain I guess.
Say you want to learn to play the guitar. Someone recommended Joe, who’s teaching in his downtown studio.
You get there almost on time. Traffic. You find Joe’s studio and here he is, dressed in a neat and simple casual outfit. Smiling at you.
Joe: Hey welcome! So you wanna learn to play?
You: Yes. I brought my guitar, got it from my uncle. It’s a bit worn out as you can see.
Joe: I see…well, you might want to get a better one if you continue past the first few lessons, but for now that will do! Do you have something that you would like to play to get started?
You: “Smoke on the water”, of course. The opening line.
Joe: Let’s try that then, I’ll show you! Just plug your guitar in this amplifier, and let me setup some nice effects so you get a cool sound.
Joe plays the first few bars a few times, shows you how that works and you give it a try. Ten minutes later you start sounding half-decent and you’re having loads of fun playing together with Joe.
Joe: Okay, you’re doing good! I’ll show you my rough course plan so you know what’s up next. I’m quite flexible when it comes to the curriculum – as long as you’re having fun and progressing we’ll be fine.
It’s easy to imagine the bad teacher version of this story:
Bad software is like that bad teacher:
The Web model is the way to go, of course.
This is 2010, and this is the Web. Don’t let any useless software stand between you and the information and services that you need.
A few weeks ago, I had the pleasure of hitting two excellent conferences in one week: SpringOne and The Rich Web Experience. The primary reason I like both conferences so much is that there are so many familiar faces.
I had a gas hanging out with folks from Pivotal after I arrived on Monday night. On Tuesday, I thoroughly enjoyed the opening keynote. Seeing the unveiling of Spring Boot 2.0's most impressive feature was spectacular too!
Started as a dare, ended as a feature in @springboot 2.0! Animated Banners ?? #SpringOne pic.twitter.com/PqSDSWHMze
— Brian Clozel (@bclozel) December 5, 2017
I walked to the Okta office for some swag that afternoon, then proceeded to the Atomist happy hour. I talked with Rod Johnson about how Atomist might be able to help update our example apps and the Okta Developer blog. Since keeping our posts and examples up-to-date is a maintenance burden, I think Atomist could be a huge help.
After happy hour, a bunch of us joined Heroku for a delicious dinner and fun conversations.
Great night with @heroku friends @mraible @speakjava @starbuxman @afitnerd @Lspacewalker pic.twitter.com/JUVz0Ak2sH
— Joe Kutner (@codefinger) December 6, 2017
On Wednesday, I delivered my talk on Bootiful Development with Spring Boot and React. You can find my slides on Speaker Deck.
It was recorded and published to YouTube as well.
After my talk ended, I only had 70 minutes before my flight took off for Florida and the Rich Web Experience. Luckily, there was hardly any traffic and I found myself boarding with 23 minutes to spare.
At the Rich Web Experience, I had two back-to-back talks on Thursday morning. The first was on OAuth and is modeled off my What the Heck is OAuth blog post. I was surprised to have a packed room and appreciated the enthusiastic audience. You can find my slides on Speaker Deck or view them below.
I had an extra half-hour (compared to SpringOne) to deliver my Bootiful React talk, but I still managed to run out of time. The good news is it was largely because of audience interaction and questions. I feel like presentations are a lot more enjoyable when conversations happen during them. I published my slides afterward. The major difference between this deck and the one at SpringOne is I included Kent Dodds' free React courses on egghead.io.
I took a nice stroll along the Clearwater beaches that afternoon. I felt like a huge weight had been lifted off my shoulders since I was done speaking for the year.
On Friday, I flew back to Denver and spent the afternoon polishing all the READMEs in our developer example apps. We recently discovered that a lot of folks were trying our examples without reading our blog posts. As a developer, I know it's nice to clone a project, configure it, and run it. This should be much easier now. For example, if you look at the README for the okta-spring-boot-2-angular-5-example, you should be able to modify and run without reading its associated blog post.
The next day, I helped organize a Devoxx4Kids Denver on building Fruit Ninja with Scratch. Melissa McKay was the class instructor and the kids had a blast. The workshop was hosted at Thrive Ballpark and they published a blog post about how Devoxx4Kids is Teaching Kids to Thrive.
#Devoxx4Kids Denver in full swing with @melissajmckay at @ThriveWorkplace. Fruit Ninja with @scratch! pic.twitter.com/ZqruHtVk0u
— Matt Raible (@mraible) December 9, 2017
The following week, I traveled to San Francisco to meet with my team and do some team building activities. I thouroughly enjoyed the stroll to work on Tuesday morning, and bowling that afternoon.
I feel very fortunate to have such a beautiful walk to the @okta SF office. #lifeatokta #embarcadero pic.twitter.com/NBaUmHtiFy
— Matt Raible (@mraible) December 12, 2017
I flew back Wednesday and made it just in time for the Denver JUG Holiday party. We had a pretty good turnout, announced some awards, voted on Venkat's talk in January, and gave out a few prizes. You can read more about the festivities on the Denver JUG blog.
When I drove home that night, I felt like George Bailey rushing home at the end of It's a Wonderful Life! The joy of being home without travel on the horizon is a wonderful feeling.
At the end of that week, I was able to find time to work on the Ionic Module for JHipster and release it.
It's a great feeling to be home for the holidays. It was Trish's birthday weekend last weekend, so we watched her compete in a couple horse shows with Tucker. They sure do look good together, don't they?
Happy Birthday to my lovely wife, @TrishPhoto! She started the day at 5am so she could do one of her favorite things - competing with Tucker. ???? pic.twitter.com/XvLd81VRcz
— Matt Raible (@mraible) December 17, 2017
I'm done traveling for the year and I don't have any overnight travel scheduled until mid-February. My TripIt stats show I traveled quite a bit this year, and I'm looking forward to speaking at more JUGs and less conferences next year.
I spent 141 days on the road, but I'm grateful for getting to attend so many cool conferences in many exotic locations.
If you want to tinker with some code over the break, you can checkout my blog post on how to use Spring Security 5.0 with OIDC or my buddy Nate's Spread Serverless Holiday Cheer with Lambda and API Gateway.
Happy Holidays everyone! 😊
You've seen web sites with stock prices or retweet counts that update in real time. However, such sites are more the exception rather than the norm. WebSockets make it easy, and are widely supported, but not used as much as they could be.
Examples provided for WebSockets typically don't focus on the "pubsub" use case; instead they tend to focus on echo servers and the occasional chat server. These are OK as far as they go.
This post provides three mini-demos that implement the same design pattern in JavaScript on both the client and server.
For the impatient who want to see running code,
git clone https://github.com/rubys/websocket-demo.git cd websocket-demos npm install node server.js
After running this, visit http://localhost:8080/ in a browser, and you should see something like this:
The primary responsibility of the server is to maintain a list of active websocket connections. The code below will maintain three such sets, one for each of the demos provided.
// attach to web server var wsServer = new websocket.server({httpServer: httpServer}); // three sets of connections var connections = { text: new Set(), html: new Set(), json: new Set() }; // when a request comes in for one of these streams, add the websocket to the // appropriate set, and upon receipt of close events, remove the websocket // from that set. wsServer.on('request', (request) => { var url = request.httpRequest.url.slice(1); if (!connections[url]) { // reject request if not for one of the pre-identified paths request.reject(); console.log((new Date()) + ' ' + url + ' connection rejected.'); return; }; // accept request and add to the connection set based on the request url var connection = request.accept('ws-demo', request.origin); console.log((new Date()) + ' ' + url + ' connection accepted.'); connections[url].add(connection); // whenever the connection closes, remove connection from the relevant set connection.on('close', (reasonCode, description) => { console.log((new Date()) + ' ' + url + ' connection disconnected.'); connections[url].delete(connection) }) });
The code is fairly straightforward. Three sets are defined; and when a request comes in it is either accepted or rejected based on the path part of the URL of the request. If accepted, the connection is added to the appropriate set. When a connection is closed, the connection is removed from the set.
EZPZ!
The client's responsibitlity is to open the socket, and to keep it open.
function subscribe(path, callback) { var ws = null; var base = window.top.location.href function openchannel() { if (ws) return; var url = new URL(path, base.replace('http', 'ws')); ws = new WebSocket(url.href, 'ws-demo'); ws.onopen = (event) => { console.log(path + ' web socket opened!'); }; ws.onmessage = (event) => { callback(event.data); }; ws.onerror = (event) => { console.log(path + ' web socket error:'); console.log(event); ws = null; }; ws.onclose = (event) => { console.log(path + ' web socket closed'); ws = null; } } // open (and keep open) the channel openchannel(); setInterval(() => openchannel(), 2000); }
A subscribe method is defined that accepts a path and a callback. The path is used to construct the URL to open. The callback is called whenever a message is received. Errors and closures cause the ws variable to be set to null. Every two seconds, the ws variable is checked, and an attempt is made to reestablish the socket connection when this value is null.
Now it is time to put the sets of server connections, and client subscribe function to use.
Starting with the client:
var textarea = document.querySelector('textarea'); // initially populate the textarea with the contents of data.txt from the // server fetch("/data.txt").then((response) => { response.text().then((body) => { textarea.value = body }) }); // whenever the textarea changes, send the new value to the server textarea.addEventListener('input', (event) => { fetch("/data.txt", {method: 'POST', body: textarea.value}); }); // whenever data is received, update textarea with the value subscribe('text', (data) => { textarea.value = data });
The value of the textarea is fetched from the server on page load. Changes made to the textarea are posted to the server as they occur. Updates received from the server are loaded into the textarea. Nothing to it!
Now, onto the server:
// Return the current contents of data.txt app.get('/data.txt', (request, response) => { response.sendFile(dirname + '/data.txt'); }); // Update contents of data.txt app.post('/data.txt', (request, response) => { var fd = fs.openSync(dirname + '/data.txt', 'w'); request.on('data', (data) => fs.writeSync(fd, data)); request.on('end', () => { fs.closeSync(fd); response.sendFile(dirname + '/data.txt'); }) }) // watch for file system changes. when data.txt changes, send new raw // contents to all /text connections. fs.watch(dirname, {}, (event, filename) => { if (filename == 'data.txt') { fs.readFile(filename, 'utf8', (err, data) => { if (data && !err) { for (connection of connections.text) { connection.sendUTF(data) }; } }) } })
Requests to get data.txt cause the contents of the file to be returned. Post requests cause the contents to be updated. It is the last block of code that we are most interested in here: the file system is watched for changes, and whenever data.txt is updated, it is read and the results are sent to each text connection. Pretty straightforward!
If you visit http://localhost:8080/textarea in multiple browser windows, you will see a textarea in each. Updating any one window will update all. What you have is the beginning of a collaborative editing application, though there would really need to be more logic put in place to properly serialize concurrent updates.
The first example has the server sending plain text content. This next example deals with HTML. The marked package is used to convert text to HTML on the server.
This client is simpler in that it doesn't have to deal with sending updates to the server:
// initially populate the textarea with the converted markdown obtained // from the server fetch("/data.html").then((response) => { response.text().then((body) => { document.body.innerHTML = body }) }); // whenever data is received, update body with the data subscribe('html', (data) => { document.body.innerHTML = data });
The primary difference between this example and the previous one is that the content is placed into document.body.innerHTML instead of textarea.value.
Like the client, the server portion of this demo consists of two blocks of code:
app.get('/data.html', (request, response) => { fs.readFile('data.txt', 'utf8', (error, data) => { if (error) { response.status(404).end(); } else { marked(data, (error, content) => { if (error) { console.log(error); response.status(500).send(error); } else { response.send(content); } }) } }) }); // watch for file system changes. when data.txt changes, send converted // markdown output to all /html connections. fs.watch(dirname, {}, (event, filename) => { if (filename == 'data.txt') { fs.readFile(filename, 'utf8', (err, data) => { if (data && !err) { marked(data, (err, content) => { if (!err) { for (connection of connections.html) { connection.sendUTF(content); } } }) } }) } })
The salient difference between this example and the previous example is call to the marked function to perform the conversion.
If you visit http://localhost:8080/markdown, you will see the text converted to markdown. You can also visit http://localhost:8080/ to see both of these demos side by side, in separate frames. Updates make in the window on the left will be reflected on the right.
No changes were required to the first demo to make this happen as both demos watch for file system changes. In fact, you can edit data.txt on the server with your favorite text area and whenever you save your changes all clients will be updated.
In this final example, the server will be sending down a recursive directory listing, complete with file names, sizes, and last modified dates. On the client, Vue.js will be used to present the data. We start with a template:
<tbody>
<tr v-for="file in filelist">
<td>{{ file.name }}</td>
<td>{{ file.size }}</td>
<td>{{ file.mtime }}</td>
</tr>
</tbody>And add a bit of code:
var app = new Vue({el: 'tbody', data: {filelist: []}}); fetch('filelist.json').then((response) => { response.json().then((json) => { app.filelist = json }); }); subscribe('json', (data) => { app.filelist = JSON.parse(data) });
The first line associates some data (initially an empty array) with an HTML element (in this case tbody). The remaining code should look very familiar by now. Because of the way Vue.js works, all that is required to update the display is to update the data.
The server side should also seem pretty familiar:
app.get('/dir.json', (request, response) => { response.json(stats(dirname)); }); fs.watch(dirname, {recursive: true}, (event, filename) => { var data = JSON.stringify(stats(dirname)); for (connection of connections.json) { connection.sendUTF(data) } })
Not shown is the code that extracts the information from the filesystem, the rest is the same basic pattern that has been used for each of these demos.
If you visit http://localhost:8080/filelist, you will see a table showing each of the files on the server. This list will be updated whenever you create, delete, or update any file. The server will push a new (and complete) set of data, and Vue.js will determine what needs to be changed in the browser window. All this generally takes place in a fraction of a second.
Vue.js is only one such framework that can be used in this way. Angular, Ember.js, and React are additional frameworks that are worth exploring.
By focusing on file system modified events, these demos have tried to demonstrate server initiated updates.
With comparatively little code, web sites can be prepared to receive and apply unsolicited updates from the server. The granularity of the updates can be as little as a single string, can be a HTML fragment, or can be arbitrary data encoded in JSON.
Reserving web sockets for server initiated broadcast operations can keep your code small and understandable. Traditional HTTP GET and POST requests can be used for all client initiated retrieval and update operations.
This makes the division of labor between the client and server straightforward: the server is responsible for providing state -- both on demand and as the state changes. The client is responsible for updating the view to match the state.
It’s been a long time since I’ve blogged any good rant about matters in the news here. It’s not that I don’t sometimes have things I could say, nor even that my words would be superfluous because the Chattering Classes in the mainstream media are already saying them. Rather it’s a lack of round tuits, and perhaps because I might sometimes post a rant elsewhere instead (for example, El Reg on predominantly techie matters).
So how better to try and restart than by blogging a positive story. One of those rare occasions where out government appears possibly to be doing the Right Thing about one of today’s most serious problems. I can’t find it on the BBC website (where I looked after hearing it on the radio), but Google finds it at the FT.
The story is rather different between the BBC and the FT, but the gist of it is that Michael Gove and/or the Department of the Environment (of which he is minister in charge) is at last considering proposals to clean up our air, by restricting or banning domestic wood and coal fires. These fires have become a huge problem in recent years. I believe they have standards about keeping their own house unpolluted, but for anyone who happens to live downwind[1] of such fires, it can fill the house with smoke for extended periods: many hours a day, many months a year. We’re talking levels of smoke comparable to not one or two but a great many smokers in the house, and this is seriously nasty smoke that hasn’t gone through the considerable cleanup that’s been forced onto the tobacco industry in recent decades.
In summary, for people affected by this, it’s an order of magnitude worse than regular exposure to passive smoking, or to those diesel emissions that have created such a fuss in recent times.
Governments have occasionally been known to do the right thing on pollution. In the 1950s we had clean air legislation to clear up a reportedly-serious smog problem. In my lifetime we’ve rid ourselves of most of the blight of tobacco smoke (including legislation that has been very successful despite my reservations at the time). Let’s hope we can see the spirit of that 1950s legislation revived and give us back our air!
[1] The prevailing wind here is approximately west-south-west, and a very common winter weather pattern includes mild damp weather and very light westerly winds. So the greatest killer is to be between east and northeast of a woodburner.
Finally the next Alfresco DevCon is arriving in January and I'm very proud to have the opportunity to contribute on this event as a trainer and a speaker. I'm pretty sure that also passing some good time with other Alfresco friends in Lisbon will be nice :)
If you don't know nothing about Alfresco but you want to put your fingers on it, you can join the training sessions that will be held during the first day of the conference.
This can be a good way for any newbies to become familiar with all the approaches and best practices needed for developing your content and business platform on top of Alfresco.
We will cover both the Content Services and the Process Services platform so this is a fantastic occasion for learning the basics from people that works on it from a decade.
The final session will be held by Ole Hejlskov (Developer Evangelist at Alfresco) and he will share with us how to create your own application using ADF. Practically this is the most intensive and the most comprehensive training day that Alfresco has ever made!!!
I'll work in partnership with the ECMCoreAveri Team together with my old friends Shoeb Sarguroh and Oliver Laabs, we are Certified Alfresco Instructors helping the Alfresco Training Team for delivering the introduction intensive course. We will support all the attendees on installing, configuring and developing labs during all the day.
We hope that this intensive training day will be useful for all of you that want to start a project using Alfresco.
After some years spent on contributing on Apache ManifoldCF inside the PMC we have started a new, and potentially overwhelming, swerve on the project: content migration.
ManifoldCF is a repository crawler that had as a primary goal manage the indexing process using scheduled jobs. After a discussion in the community, we realized that we could use it also for content migration and not only for searching purpose.
Then we started to implement some Output Connectors dedicated to this new scenario. The first connector that I have implemented is the CMIS Output Connector that allow you to migrate contents from any ManifoldCF supported repos to any CMIS-compliant repo. Notice that the core framework will manage for you also the incremental injection considering also the removed contents.
I'm very happy to have started this new adventure and during this journey, I met one of the persons that allowed me to understand better the Alfresco platform and that gave me a lot in terms of knowledge and experience: Luis Cabaceira (Solutions Architect at Alfresco).
I learnt a lot reading his white papers about sizing and performance tuning and now working strictly with him it is a huge and priceless thing for me, really, thank you man ;)
Luis started to contribute on ManifoldCF implementing an Alfresco BFSI Output Connector for making easier any migration to Alfresco. He is also became a Committer inside the project and I'm sure that he will bring a lot of value and contributions taking care of some of the current Alfresco connectors and giving a huge help on the content migration area.
We hope that our session will bring value and ideas to all of you and we really hope to receive any kind of feedback on our current work and if you want to contribute, feel free to contact me and please subscribe the ManifoldCF mailing lists.
This will help us for making a huge release of ManifoldCF that will be tagged as Content Migration Enabler scheduled on the next 2.10 version (around Q2 2018).
See you at the conference for sharing awesome experiences or only just to say hello :)
Below you will find the abstract of our presentation:
Content migration using Apache ManifoldCF Output Connectors
In our days, enterprise digital content is scattered on several independent systems and subsystems, which perform services such as user authentication, document storage, and provide search capabilities. Centralising enterprise data into a single repository is a growing necessity for organisations. Our talk proposes an approach that could be the "silver bullet" that will open a clear path for Enterprise digital content centralisation . In its genesis , Apache ManifoldCF is a crawler that allows you to manage content indexes in your search engines, this was the main goal of the product. We've realised that we could leverage ManifoldCF to also migrate content, and not only indexes, making it a very good migration tool. This talk will focus on 2 new output connectors for Apache ManifoldCF that are being developed by us.
This is just the first slide of our presentation, stay tuned and come to see me and Luis speaking about content migration using Apache ManifoldCF
![]() |
| Figure 17.9 - Before with the glitch in the dashed line in the bottom not being 100% horizontal line |
![]() |
| Figure 17.9 - After with the dashed lined in the bottom fixed |
I originally published this article on SD Times, republishing it to keep it around for posterity…
If you’re looking at embracing open source today, you might be a bit late to the game. Using open-source software is mainstream now, and being involved in open-source projects is nothing to write home about either. Everybody does it, we know how it works, its value is proven.
But what’s next? Sharing source code openly is a given in open-source projects, but in the end it’s only about sharing lines of text. The real long-term power of successful open-source projects lies in how their communities operate, and that’s where open development comes in.
Shared communications channels. Meritocracy. Commit early, commit often. Back your work by issues in a shared tracker. Archive all discussions, decisions and issues about your project, and make that searchable. All simple principles that, when combined, make a huge difference to the efficiency of our corporate projects.
But, of course, the chaotic meritocracies of open-source projects won’t work for corporate teams, right? Such teams require a chain of command with strictly defined roles. Corporate meritocracy? You must be kidding.
I’m not kidding, actually: Open development works very well in corporate settings, and from my experience in both very small and fairly large organizations, much better than old-fashioned top-to-bottom chains of command and information segregation principles. Empower your engineers, trust them, make everything transparent so that mistakes can be caught early, and make sure the project’s flow of information is continuous and archived. Big rewards are just around the corner—if you dive in, that is.
What’s open development?
Open development starts by using shared digital channels to communicate between project members, as opposed to one-to-one e-mails and meetings. If your team’s e-mail clients are their knowledge base, that will go away with them when they leave, and it’s impossible for new project members to acquire that knowledge easily.
A centralized channel, like a mailing list, allows team members to be aware of everything that’s going on. A busy mailing list requires discipline, but the rewards are huge in terms of spreading knowledge around, avoiding duplicate work and providing a way for newcomers to get a feel for the project by reviewing the discussion archives. At the Apache Software Foundation, we even declare that “If it didn’t happen on the dev list, it didn’t happen,” which is a way of saying that whatever is worth saying must be made available to all team members. No more discrepancies in what information team members get; it’s all in there.
The next step is sharing all your code openly, all the time, with all stakeholders. Not just in a static way, but as a continuous flow of commits that can tell you how fast your software is evolving and where it’s going, in real time.
Software developers will sometimes tell you that they cannot show their code because it’s not finished. But code is never finished, and it’s not always beautiful, so who cares? Sharing code early and continuously brings huge benefits in terms of peer reviews, learning from others, and creating a sense of belonging among team members. It’s not “my” code anymore, it’s “our” code. I’m happy when someone sees a way to improve it and just does it, sometimes without even asking for permission, because the fix is obvious. One less bug, quality goes up, and “shared neurons in the air” as we sometimes say: all big benefits to a team’s efficiency and cohesion.
Openly sharing the descriptions and resolutions of issues is equally important and helps optimize usage of a team’s skills, especially in a crisis. As in a well-managed open-source project, every code change is backed by an issue in the tracker, so you end up with one Web page per issue, which tells the full history of why the change was made, how, when, and by whom. Invaluable information when you need to revisit the issue later, maybe much later when whoever wrote that code is gone.
Corporate projects too often skip this step because their developers are co-located and can just ask their colleague next door directly. By doing that, they lose an easy opportunity to create a living knowledgebase of their projects, without much effort from the developers. It’s not much work to write a few lines of explanation in an issue tracker when an issue is resolved, and, with good integration, rich links will be created between the issue tracker and the corresponding source code, creating a web of valuable information.
The dreaded “When can we ship?” question is also much easier to answer based on a dynamic list of specific issues and corresponding metadata than by asking around the office, or worse, having boring status meetings.
The last critical tool in our open development setup is in self-service archives of all that information. Archived mailing lists, resolved issues that stay around in the tracker, source-code control history, and log messages, once made searchable, make project knowledge available in self-service to all team members. Here as well, forget about access control and leave everything open. You want your engineers to be curious when they need to, and to find at least basic information about everything that’s going on by themselves, without having to bother their colleagues with meetings or tons of questions. Given sufficient self-service information, adding more competent people to a project does increase productivity, as people can largely get up to speed on their own.
While all this openness may seem chaotic and noisy to the corporate managers of yesterday, that’s how open-source projects work. The simple fact that loose groups of software developers with no common boss consistently produce some of the best software around should open your eyes. This works.
After seeing a lot of questions surrounding incremental repair on the mailing list and after observing several outages caused by it, we figured it would be good to write down our advices in a blog post.
Repair in Apache Cassandra is a maintenance operation that restores data consistency throughout a cluster.
It is advised to run repair operations at leasts every gc_grace_seconds to ensure that tombstones will get replicated consistently to avoid zombie records if you perform DELETE statements on your tables.
Repair also facilitates recovery from outages that last longer than the hint window, or in case hints were dropped. For those operators already familiar with the repair concepts, there were a few back-to-basics moments when the behavior of repair changed significantly in the release of Apache Cassandra 2.2. The introduction of incremental repair as the default along with the generalization of anti-compaction created a whole new set of challenges.
To perform repairs without comparing all data between all replicas, Apache Cassandra uses merkle trees to compare trees of hashed values instead.

During a repair, each replica will build a merkle tree, using what is called a “validation compaction”. It is basically a compaction without the write phase, the output being a tree of hashes.

Merkle trees will then be compared between replicas to identify mismatching leaves, each leaf containing several partitions. No difference check is made on a per partition basis : if one partition in a leaf is not in sync, then all partitions in the leaf are considered as not being in sync. When more data is sent over than is required it’s typically called overstreaming. Gigabytes of data can be streamed, even for one bit of difference. To mitigate overstreaming, people started performing subrange repairs by specifying the start/end tokens to repair by smaller chunks, which results in having less partitions per leaf.
With clusters growing in size and density, performing repairs within gc_grace_seconds started to get more and more challenging, with repairs sometimes lasting for tens of days.
Some clever folks leveraged the immutable nature of SSTables and introduced incremental repair in Apache Cassandra 2.1.
The plan with incremental repair was that once some data had been repaired, it would be marked as such and never needed to be repaired anymore.
Since SSTables can contain tokens from multiple token ranges, and repair is performed by token range, it was necessary to be able to separate repaired data from unrepaired data. That process is called anticompaction.

Once a repair session ends, each repaired SSTable will be split into 2 SSTables : one that contains the data that was repaired in the session (ie : data that belonged to the repaired token range) and another one with the remaining unrepaired data. The newly created SSTable containing repaired data will be marked as such by setting its repairedAt timestamp to the time of the repair session.
When performing validation compaction during the next incremental repair, Cassandra will skip the SSTables with a repairedAt timestamp higher than 0, and thus only compare data that is unrepaired.

Incremental repair was actually promising enough that it was promoted as the default repair mode in C* 2.2, and anticompaction was since then also performed during full repairs.
To say the least, this was a bit of a premature move from the community as incremental repair has a few very annoying drawbacks and caveats that would make us consider it an experimental feature instead.
The most nasty one is filed in the Apache Cassandra JIRA as CASSANDRA-9143 with a fix ready for the unplanned 4.0 release. Between validation compaction and anticompaction, an SSTable that is involved in a repair can be compacted away as part of the standard compaction process on one node and not on the others. Such an SSTable will not get marked as repaired on that specific node while the rest of the cluster will consider the data it contained as repaired.
Thus, on the next incremental repair run, all the partitions contained by that SSTable will be seen as inconsistent and it can generate a fairly large amount of overstreaming.
This is a particularly nasty bug when incremental repair is used in conjunction with Level Compaction Strategy (LCS). LCS is a very intensive strategy where SSTables get compacted way more often than with STCS and TWCS.
LCS creates fixed sized SSTables, which can easily lead to have thousands of SSTables for a single table. The way streaming occurs in Apache Cassandra during repair makes that overstreaming of LCS tables could create tens of thousands of small SSTables in L0 which can ultimately bring nodes down and affect the whole cluster. This is particularly true when the nodes use a large number of vnodes.
We have seen happening on several customers clusters, and it requires then a lot of operational expertise to bring back the cluster to a sane state.
In addition to the bugs related to incorrectly marked sstables, there is significant overhead of anti-compaction. It was kind of a big surprise for users upgrading from 2.0/2.1 to 2.2 when trying to run repair. If there is already a lot of data on disk, the first incremental repair can take a lot of time (if not forever) and create a similar situation as above with a lot of SSTables being created due to anticompaction. Keep in mind that anticompaction will rewrite all SSTables on disk to separate repaired and unrepaired data.
While it’s not necessary anymore to “prepare” the migration to incremental repair, we would strongly advise against running it on a cluster with a lot of unrepaired data, without first marking SSTables as repaired. This would require to run a full repair first to make sure data is actually repaired, but now even full repair performs anticompaction, so… you see the problem.
A safety measure has been set in place to prevent SSTables going through anticompaction to be compacted, for valid reasons. The problem is that it will also prevent that SSTable from going through validation compaction which will lead repair sessions to fail if an SSTable is being anticompacted. Given that anticompaction also occurs with full repairs, this creates the following limitation : you cannot run repair on more than one node at a time without risking to have failed sessions due to concurrency on SSTables. This is true for incremental repair but also full repair, and it changes a lot of the habit you had to run repair in previous versions.
The only way to perform repair without anticompaction in “modern” versions of Apache Cassandra is subrange repair, which fully skips anticompaction. To perform a subrange repair correctly, you have three options :
Regardless, it is extremely important to note that repaired and unrepaired SSTables can never be compacted together. If you stop performing incremental repairs once you started, you could end up with outdated data not being cleaned up on disk due to the presence of the same partition in both states. So if you want to continue using incremental repair, make sure it runs very regularly, and if you want to move back to full subrange repairs you will need to mark all SSTables as unrepaired using sstablerepairedset.
Note that due to subrange repair not performing anti-compaction, is not possible to perform subrange repair in incremental mode.
Here’s our advice at the time of writing this blog post, based on our experience with customers : perform full subrange repair exclusively for now and do not ever run incremental repair. Just pretend that feature does not exist for now.
While the idea behind incremental repair is brilliant, the implementation still has flaws that can cause severe damage to a production cluster, especially when using LCS and DTCS. The improvements and fixes planned for 4.0 will need to be thoroughly tested to prove they fixed incremental repair and allow it to be safely used as a daily routine.
We are confident that future releases will make incremental repair better, allowing the operation to be safe and blazing fast compared to full repairs.
equery b $(find /usr/lib/ /lib/ -name *.a) | awk '{ print $1; }' | sort | uniq
Typically this yields packages like elfutils, libbsd, nss, iproute2, keyutils, texinfo, flex, db, numactl.Service Workers enable a web application to be responsive even if the network isn't. Frameworks like AngularJS, React and Vue.js enable web applications to efficiently update and render web pages as data changes.
The Apache Software Foundation's Whimsy board agenda application uses both in combination to achieve a responsive user experience - both in terms of quick responses to user requests and quick updates based on changes made on the server.
From a performance perspective, the two cases easiest to optimize for are (1) the server fully up and running accessed across a fast network with all possible items cached, and (2) the application fully offline as once you make offline possible at all, it will be fast.
The harder cases ones where the server has received a significant update and needs to get that information to users, and even harder is when the server has no instances running and needs to spin up a new instance to process a request. While it is possible to do blue/green deployment for applications that are "always on", this isn't practical or appropriate for applications which only used in periodic bursts. The board agenda tool is one such application.
This article describes how a goal of sub-second response time is achieved in such an environment. There are plenty of articles on the web that show snippets or sanitized approaches, this one focuses on real world usage.
Service Workers are JavaScript files that can intercept and provide responses to navigation and resource requests. Service Workers are supported today by Chrome and FireFox, and are under development in Microsoft Edge and WebKit/Safari.
Service Workers are part of a larger effort dubbed "Progressive Web Apps" that aim to make web applications reliable and fast, no matter what the state of the network may happen to be. The word "progressive" in this name is there to indicate that these applications will work with any browser to the best of that browser's ability.
The signature or premier feature of Service Workers is offline applications. Such web applications are loaded normally the first time, and cached. When offline, requests are served by the cache, and any input made by users can be stored in local storage or in an index db.
serviceworke.rs and The Offline Cookbook provide a number of recipes that can be used.
This information is for background purposes only. Feel free to skim or skip.
The ASF Board meets monthly, and minutes are published publicly on the web. A typical meeting has over one hundred agenda items, though the board agenda tool assists in resolving most off them offline, leaving a manageable 9 officer reports, around 20 PMC reports that may or may not require action, and a handful of special orders.
While the full agenda is several thousand lines long, this file size is only a quarter of a megabyte or the size of a small image. The server side of this application parses the agenda and presents it to the client in JSON format, and the result is roughly the same size as the original.
To optimize the response of the first page access, the server is structured to do server side rendering of the page that is requested, and the resulting response starts with links to stylesheets, then contains the rendered HTML, and finally any scripts and data needed. This allows the browser to incrementally render the page as it is received. This set of scripts includes a script that can render any page (or component) that the board agenda tool can produce, and the data includes all the information necessary to do so. The current implementation is based on Vue.js.
Once loaded, traversals between pages is immeasurably quick. By that I mean that you can go to the first page and lean on the right arrow button and pages will smoothly scroll through the pages by at roughly the rate at which you can see the faces in a deck of cards shuffled upside down.
The pages generally contain buttons and hidden forms; which buttons appear often depends on the user who requests the page. For example, only Directors will see approve and unapprove buttons; and individual directors will only see one of these two buttons based on whether or not they have already approved the report.
A WebSocket between the server and client is made mostly so the server can push changes to each client; changes that then cause re-rendering and updated displays. Requests from the client to the server generally are done via XMLHttpRequest as it wasn't until very recently that Safari supported fetch. IE still doesn't, but Edge does.
Total (uncompressed) size of the application script is another quarter of a megabyte, and dependencies include Vue.js and Bootstrap, the latter being the biggest requiring over a half a megabyte of minimized CSS.
All scripts and stylesheets are served with a Cache-Control: immutable header as well as an expiration date a year from when the request was made. This is made possible by the expedient of utilizing a cache busting query string that contains the last modified date. Etag and 304 responses are also supported.
Offline support was added recently. Updates made when offline are stored in an IndexDB and sent as a batch when the user returns online. Having all of the code and data to render any page made this support very straightforward.
As mentioned at the top of this article, offline operations are virtually instantaneous. Generally, immeasurably so. As described above, this also applies to transitions between pages.
This leaves the initial visit, and returning visits, the latter includes opening the application in new tabs.
Best case response times for these cases is about a second. This may be due to the way that server side rendering is done or perhaps due to the fact that each page is customized to the individual. Improving on this is not a current priority, though the solution described later in this article addresses this.
Worst case response times are when there are no active server processes and all caches (both server side and client side) are either empty or stale. It is hard to get precise numbers for this, but it is on the order of eight to ten seconds. Somewhere around four is the starting of the server. Building the JSON form of the agenda can take another two given all of the validation (involving things like LDAP queries) involved in the process. Regenerating the ES5 JavaScript from sources can take another second or so. Producing the custom rendered HTML is another second. And then there is all of the client side processing.
In all, probably just under ten seconds if the server is otherwise idle. It can be a little more if the server is under moderate to heavy load.
The worst parts of this:
Given that the application can be brought up quickly in an entirely offline mode, one possibility would be to show the last cached status and then request updated information and process that information when received. This approach works well if the only change is to agenda data, but doesn't work so well in production whenever a script change is involved.
This can be solved with a window.location.reload() call, which is described (and somewhat discouraged) as approach #2 in Dan Fabulic's "How to Fix the Refresh Button When Using Service Workers". Note the code below was written before Dan's page was published, but in any case, Dan accurately describes the issue.
Taking some measurements on this produces interesting results. What is needed to determine if a script or stylesheet has changed is a current inventory from the server. This can consistently be provided quickly and is independent of the user requesting the data, so it can be cached. But since the data size is small enough, caching (in the sense of HTTP 304 reponses) isn't all that helpful.
Response time for this request in realistic network conditions when there is an available server process is around 200 milliseconds, and doesn't tend to vary very much.
The good news is that this completely addresses the "reload flash" problem.
Unfortunately, the key words here are "available server process" as that was the original problem to solve.
Fortunately, a combination approach is possible:
Additional exploration lead to the solution where the inventory page mentioned below could be formatted in HTML and, in fact, be the equivalent to a blank agenda page. Such a page would still be less than 2K bytes, and performance would be equivalent to loading a blank page and then navigating to the desired page, in other words, immeasurably fast.
If you look at existing recipes, Network or Cache is pretty close; the problem is that it leaves the user with stale data if the network is slow. It can be improved upon.
Starting with the fetch from the network:
// attempt to fetch bootstrap.html from the network
fetch(request).then(function(response) {
// cache the response if OK, fulfill the response if not timed out
if (response.ok) {
cache.put(request, response.clone());
// preload stylesheets and javascripts
if (/bootstrap\.html$/.test(request.url)) {
response.clone().text().then(function(text) {
var toolate = !timeoutId;
setTimeout(
function() {
preload(cache, request.url, text, toolate)
},
(toolate ? 0 : 3000)
)
})
};
if (timeoutId) {
clearTimeout(timeoutId);
resolve(response)
}
} else {
// bad response: use cache instead
replyFromCache(true)
}
}).catch(function(failure) {
// no response: use cache instead
replyFromCache(true)
})This code needs to be wrapped in a Promise that provides a resolve function, and needs access to a cache as well as a variable named timeoutid and that determines whether or not the response has timed out.
If the response is ok, it and will be cached and a preload method will be called to load resources mentioned in the page. That will either be done immediately if not toolate, or after a short delay the timer expired to allow updates to be processed. Finally, if such a response was received in time, the timer will be cleared, and the promise will be resolved.
If either a bad response or no response was received (typically, this represents a network failure), the cache will be used instead.
Next the logic to reply from the cache:
// common logic to reply from cache
var replyFromCache = function(refetch) {
return cache.match(request).then(function(response) {
clearTimeout(timeoutId);
if (response) {
resolve(response);
timeoutId = null
} else if (refetch) {
fetch(event.request).then(resolve, reject)
}
})
};
// respond from cache if the server isn't fast enough
timeoutId = setTimeout(function() {replyFromCache(false)}, timeout);This code looks for a cache match, and if it finds one, it will resolve the response, and clear the timeoutId enabling the fetch code to detect if it was too late.
If no response is found, the action taken will be determined by the refetch argument. The fetch logic above passes true for this, and the timeout logic passes false. If true, it will retry the original request (which presumably will fail) and return that result to the user. This is handling a never should happen scenario where the cache doesn't contain the bootstrap page.
The above two snippets of code are then wrapped by a function, providing the event, resolve, reject, and cache variables, as well as declaring and initializing the timeoutId variable:
// Return a bootstrap.html page within 0.5 seconds. If the network responds
// in time, go with that response, otherwise respond with a cached version.
function bootstrap(event, request) {
return new Promise(function(resolve, reject) {
var timeoutId = null;
caches.open("board/agenda").then(function(cache) {
...
}
})Next, we need to implement the preload function:
// look for css and js files and in HTML response ensure that each are cached
function preload(cache, base, text, toolate) {
var pattern = /"[-.\w+/]+\.(css|js)\?\d+"/g;
var count = 0;
var changed = false;
while (match = pattern.exec(text)) {
count++;
var path = match[0].split("\"")[1];
var request = new Request(new URL(path, base));
cache.match(request).then(function(response) {
if (response) {
count--
} else {
fetch(request).then(function(response) {
if (response.ok) cacheReplace(cache, request, response);
count--;
if (count == 0 && toolate) {
clients.matchAll().then(function(clients) {
clients.forEach(function(client) {
client.postMessage({type: "reload"})
})
})
}
})
}
})
}
};This code parses the HTML response, looking for .css, and .js files, based on a knowledge as to how this particular server will format the HTML. For each such entry in the HTML, the cache is searched for a match. If one is found, nothing more needs to be done. Otherwise, the resource is fetched and placed in the cache.
Once all requests are processed, and if this involved requesting a response from the network, then a check is made to see if this was a late response, and if so, a reload request is sent to all client windows.
cacheReplace is another application specific function:
// insert or replace a response into the cache. Delete other responses
// with the same path (ignoring the query string).
function cacheReplace(cache, request, response) {
var path = request.url.split("?")[0];
cache.keys().then(function(keys) {
keys.forEach(function(key) {
if (key.url.split("?")[0] == path && key.url != path) {
cache.delete(key).then(function() {})
}
})
});
cache.put(request, response)
};The purpose of this method is as stated: to delete from the cache other responses that differ only in the query string. It also adds the response to the cache.
The remainder is either straightforward or application specific in a way that has no performance relevance. The scripts and stylesheets are served with a cache falling back to network strategy. The initial preloading which normally could be as simple as a call to cache.addAll needs to be aware of query strings and for this application it turns out that a different bootstrap HTML file is needed for each meeting.
Finally, here is the client side logic which handles reload messages from the service worker:
navigator.serviceWorker.register(scope + "sw.js", scope).then(function() {
// watch for reload requests from the service worker
navigator.serviceWorker.addEventListener("message", function(event) {
if (event.data.type == "reload") {
// ignore reload request if any input or textarea element is visible
var inputs = document.querySelectorAll("input, textarea");
if (Math.max.apply(
Math,
Array.prototype.slice.call(inputs).map(function(element) {
return element.offsetWidth
})
) <= 0) window.location.reload()
}
});
}This code watches for type: "reload" messages from the service worker and invokes window.location.reload() only if there are no input or text area elements visible, which is determined using the offsetWidth property of each element. Very few board agenda pages have visible input fields by default; many, however, have bootstrap modal dialog boxes containing forms.
In production when using a browser that supports Service Workers, requests for the bootstrap page now typically range from 100 to 300 milliseconds, with the resulting page fully loaded in 400 to 600 milliseconds. Generally, this includes the time it takes to fetch and render updated data, but in rare cases that may take up to an additional 200 milliseconds.
In development, and in production when there are no server processes available and when accessed using a browser that supports Service Workers, the page initially loads in 700 to 1200 milliseconds. It is not clear to me why this sees a greater range of response times; but in any case, this is still a notable improvement. Often in development, and in rare cases in production, there may be a noticeable refresh that occurs one to five seconds later.
Visitations by browsers that do not support service workers, and for that matter the first time a new user visits the board agenda tool, do not see any performance improvement or degradation with these changes.
Not a bad result from less than 100 lines of code.
# required by sys-apps/portage-2.3.13-r1::gentoo[python_targets_python3_4,-build,python_targets_python2_7,-python_targets_python3_5] # required by virtual/package-manager-0::gentoo # required by @system # required by @world (argument) >=dev-python/pyblake2-0.9.3-r1 python_targets_python3_4That's because python-3.5 as well as python-3.6 and a new version of portage went stable, that in turn causes python USE flag changes and portage can't figure out correctly what to do.
emerge -1av python:3.5 eselect python update emerge -1avD --changed-use @worldThat should let you update world again and depclean will remove python-3.4 for you.
emerge -uavD @world emerge --depclean
We had the pleasure to release our monitoring dashboards designed for Apache Cassandra on Datadog last week. It is a nice occasion to share our thoughts around Cassandra Dashboards design as it is a recurrent question in the community.
We wrote a post about this on the Datadog website here.
For people using Datadog we hope this will give more details on how the dashboards were designed, thus on how to use the dashboards we provided. For others, we hope this information will be useful in the process of building and then using your own dashboards, with the technology of your choice.
Building an efficient, complete, and readable set of dashboards to monitor Apache Cassandra is time consuming and far from being straightforward.
Those who tried it probably noticed it requires a fair amount of time and knowledge with both the monitoring technology in use (Datadog, Grafana, Graphite or InfluxDB, metrics-reporter, etc) and of Apache Cassandra. Creating dashboards is about picking the most relevant metrics, aggregations, units, chart type and then gather them in a way that this huge amount of data actually provides usable information. Dashboards need to be readable, understandable and easy to use for the final operator.
On one hand, creating comprehensive dashboards is a long and complex task. On the other hand, every Apache Cassandra cluster can be monitored roughly the same way. Most production issues can be detected and analyzed using a common set of charts, organized the same way, for all the Apache Cassandra clusters. Each cluster may require additional operator specific dashboards or charts depending on workload and merging of metrics outside of Cassandra, but those would supplement the standard dashboards, not replace them. There are some differences depending on the Apache Cassandra versions in use, but they are relatively minor and not subject to rapid change.
In my monitoring presentation at the 2016 Cassandra Summit I announced that we were working on this project.
In December 2017 it was release for Datadog users. If you want to get started with these dashboards and you are using Datadog, see how to do this documentation on Datadog integration for Cassandra.
The dashboards have been designed to allow the operator to do the following:
The 2 later points above can be seen as the same kind of operations which can be supported by the same set of dashboards.
Empowering the operator
We strongly believe that showing the metrics to the operator can be a nice entry point for learning about Cassandra. Each of the themed dashboards monitor a distinct internal processes of Cassandra. Most of the metrics related to this internal process are then grouped up within a Dashboard. We think it makes it easier for the operator to understand Cassandra’s internal processes.
To make it clearer, let’s consider the example of someone completely new to Cassandra. On first repair, the operator starts an incremental repair without knowing anything about it and latencies increase substantially after a short while. Classic.
The operator would notice a read latency in the ‘Overview Dashboard’, then aim at the ‘Read Path Dashboard’. There the operator would be able to notice that the number of SSTables went from 50 to 800 on each node, or for a table. If the chart is there out of the box, even if not knowing what an SSTable is the operator can understand something changed there and that it relates to the outage somehow. The operator would then search in the right direction, probably solving the issue quickly, and possibly learning in the process.
Here we will be really focusing on charts details and indications on how to use each chart efficiently. While this post is a discussion of dashboards available for DataDog, the metrics can be visualized using any tool, and we believe this would be a good starting point when setting up monitoring for Cassandra.
In the graphs, the values and percentiles chosen are sometime quite arbitrary and often depend on the use case or Cassandra setup. The point is to give a reference, a starting point on what could be ‘normal’ or ‘wrong’ values. The Apache Cassandra monitoring documentation, the mailing list archive, or #cassandra on #freenode (IRC) are good ways to answer questions that might pop while using dashboards.
Some dashboards are voluntary duplicated across dashboards or within a dashboard, but with distinct visualisation or aggregation.
We don’t try to troubleshoot at this stage. We want to detect outages that might impact the service or check that the Cassandra cluster is globally healthy. To accomplish this, this Overview Dashboard aims at both being complete and minimalist.
Complete as we want to be warned anytime “something is happening“ in the Cassandra cluster. Minimalist because we don’t want to miss an important information here because of the flood of non-critical or too low level informations. These charts aim answer the question: “Is Cassandra healthy?”.

The goal here is to divide the information into smaller, more meaningful chunks. When having an issue, it will often only affect one of the subsystems of Cassandra, so the operator can have all the needed information in one place when working on a specific issue, without having irrelevant informations (for this specific issue) hiding more important information.
For this reason these dashboards must maximize the information on a specific theme or internal process of Cassandra and show all the low level information (per table, per host). We are often repeating charts from other dashboards, so we always find the information we need as Cassandra users. This is the contrary to the overview dashboard needs mentioned above that just shows “high level” information.
In this dashboard we are concerned about any element that could impact a high level client read. In fact, we want to know about everything that could affect the read path in Cassandra by just looking at this dashboard.

This dashboard focuses on a comprehensive view of the various metrics which affect write latency and throughput. Long garbage collection pause times will always result in dips in throughput and spikes in latency, so it is featured prominently on this dashboard.

This dashboard is about getting a comprehensive view of the various metrics which impact the asynchronous steps the data goes through after a write, from the flush to the data deletion with all the compaction processes in between. Here we will be willing to be aware of disk space evolution and make sure asynchronous management of SSTables is happening efficiently or as expected.

To conclude, when happy with monitoring dashboards, it is a good idea to add some alerting rules.
It is important to detect all the anomalies as quickly as possible. To bring monitoring to the next level of efficiency, it is good to be warned automatically when something goes wrong.
We believe adding alerts on each of the “Overview Dashboard” metrics will be sufficient to detect most issues and any major outage, or at least be a good starting point. For each metric, the alerting threshold should be high enough not to trigger false alerts to ensure a mitigating action can be taken. Some alerts should use absolute value (Disk space available, CPU, etc), while others will require relative values. Manually tuning some alerts will be required based on configuration and workload, such as alerting on the latencies.
The biggest risk on alerting is probably to be flooded by false alerts as the natural inclination to start ignoring them, which leads to missing valid ones. As a global guideline, any alert should trigger an action, if it does not, this alert is relatively useless and adds noise.
Jim Jagielski—The Path to Apache OpenOffice 4.2.0It is no secret that, for awhile at least, Apache OpenOffice had lost its groove.
Partly it was due to external issues. Mostly that the project and the committers were spending a lot of their time and energies battling and correcting the FUD associated around the project. Nary a week would go by without the common refrain "OpenOffice is Dead. Kill it already!" and constant (clueless) rehashes of the history between OpenOffice and LibreOffice. With all that, it is easy and understandable to see why morale within the AOO community would have been low. Which would then reflect and affect development on the project itself.
So more so than anything, what the project needed was a good ol' shot of adrenaline in the arm and some encouragement to keep the flame alive. Over the last few months this has succeeded beyond our dreams. After an admittedly way-too-long period, we finally released AOO 4.1.4. And we are actively working on not only a 4.1.5 release but also preparing plans for our 4.2.0 release.
And it's there that you can help.
Part of what AOO really wants to be is a simple, easy-to-user, streamlined office suite for the largest population of people possible. This includes supporting old and long deprecated OSs. For example, our goal is to continue to support Apple OSX 10.7 (Lion) with our 4.2.0 release. However, there is one platform which we are simply unsure about what to do, and how to handle it. And what makes it even more interesting is that it's our reference build system for AOO 4.1.x: CentOS5
Starting with AOO 4.2.0, we are defaulting to GIO instead of Gnome VFS. The problem is that CentOS5 doesn't support GIO, which means that if we continue with CentOS5 as our reference build platform for our community builds, then all Linux users who use and depend on those community builds will be "stuck" with Gnome VFS instead of GIO. If instead we start using CentOS6 as our community build server. we leave CentOS5 users in a lurch (NOTE: CentOS5 users would still be able to build AOO 4.2.0 on their own, it's just that the binaries that the AOO project supplies won't work). So we are looking at 3 options:
Which one makes the most sense? Join the conversation and the discussion on the AOO dev mailing list!
(gdb) bt #0 0x00007ffff6a5ef50 in raise () from /lib64/libc.so.6 #1 0x00007ffff6a60bfa in abort () from /lib64/libc.so.6 #2 0x00007ffff7914b32 in pa_xmalloc0 () from /usr/lib64/libpulse.so.0 #3 0x00007ffff7ba1db1 in pa_database_open () from /usr/lib64/pulseaudio/libpulsecore-10.0.so #4 0x00007fffeed60468 in module_card_restore_LTX_pa__init () from /usr/lib64/pulse-10.0/modules/module-card-restore.so #5 0x00007ffff7b5ac98 in pa_module_load () from /usr/lib64/pulseaudio/libpulsecore-10.0.so #6 0x00007ffff7b49751 in ?? () from /usr/lib64/pulseaudio/libpulsecore-10.0.so #7 0x00007ffff7b4fd2c in pa_cli_command_execute_line_stateful () from /usr/lib64/pulseaudio/libpulsecore-10.0.so #8 0x00007ffff7b50551 in pa_cli_command_execute_file_stream () from /usr/lib64/pulseaudio/libpulsecore-10.0.so #9 0x0000000000406e55 in main ()So it is trying to read some database. What database?
open("/home/xoxo/.pulse/91b2f1e2678a89a9c38b83075061a39a-card-database.x86_64-pc-linux-gnu.simple", O_RDONLY|O_CLOEXEC) = 9
So likely this thingy is corrupt. Solved this with:rm -rf .pulseOne of my favorite conferences in the world is Devoxx Belgium. First of all, it tends to have one of the most enthusiastic audiences I've ever seen. Secondly, its organizers are super awesome and challenge you to give great talks. Third, it was the first conference I ever took my Trish to. In 2011, I took her a second time and proposed to her in Paris afterward.
This year, I traveled to Devoxx Belgium for the first time without Trish. It was stressful because I didn't prepare well beforehand. However, it was also gratifying because I was able to make everything work, even it all happened at the last minute. Furthermore, I did the majority of my talks with good friends, which is always a pleasant experience.
The purpose of this blog post is to document my experience this year, so I can look back and say WTF was I
thinking?! 
I left Denver on Monday (November 6) afternoon and flew to Brussels, Belgium. My flight landed in Brussels at 9 am and Josh and my (three hour) talk was at 1:30 pm. I made it in time, but it was one of the first times we didn’t have a lot of time to prepare face-to-face beforehand. I learned that getting t-shirts printed in the US to save $500 is a good idea, but having to take two suitcases to carry them all is a bad idea.
We did our usual talk and I used Okta's new Angular SDK
instead of the Sign-In Widget to showcase authentication. Even
though the crucial step I needed was contained in my notes, I failed. One simple line to add an HttpInterceptor and
I missed it!
I think I followed up well with a tweet that showed how to fix it. But who knows how many people use Twitter. One things for sure, people tweet more at Devoxx Belgium than any other conference I’ve ever been too! In fact, the #Devoxx hashtag got hijacked by some porn sites and their tweets started showing up on the Twitter wall. ??
I tweeted about what I forgot to do after our talk.
Thanks to everyone who attended @starbuxman and my session on Cloud Native PWAs at @Devoxx!
— Matt Raible (@mraible) November 8, 2017
Slides: https://t.co/3uyn4KUbm2
Source code: https://t.co/6deOtoHeeg
FWIW, I figured out why my @okta demo failed. I forgot to add the AuthInterceptor as a provider. Doh! #Devoxx pic.twitter.com/HxdYp6CetZ
Josh and my talk was published on YouTube the very next day, which is awesome.
Tuesday night was the speaker’s reception, so I attended that and turned in around 10 pm. I worked on my next presentation (Angular vs. React) for a few hours after getting back to my hotel.
On Wednesday, I worked all day with my co-speaker (Deepu, co-lead of JHipster) on our Angular vs. React presentation. We worked for eight hours at the conference venue that day and parted ways around 6 pm.
On Wednesday night, I attended a dinner with Ray Tsang (Google Cloud Advocate). We were invited (along with Josh) to a dinner with JDriven. Josh couldn’t make it, but Ray and I attended and had a great time. I got home at 10 pm that night and worked on my next day’s presentation until 3 am.
Thursday, I worked with Deepu for a couple hours to polish and practice our presentation and we delivered it that afternoon. We also advertised the t-shirts we brought.
There were lots of tweets about our talk, but I think this from Daniel Bryant with our recommendations for Angular vs React was one of my favorites.
The results of the web framework smackdown are in...
— Daniel Bryant (@danielbryantuk) November 9, 2017
via @mraible and @deepu105 at #Devoxx pic.twitter.com/MBYfZ2Fli4
Our session went well, even thought it wasn’t super technical, and it was published to YouTube.
I also published our slides on Speaker Deck.
We had the JHipster BOF late that night (during the conference movie) and only had three people show up. With five committers there, we still had a great time, and it was fun to give Julien the Duke’s Choice Award trophy since he started the project.
@java_hipster team rocking @Devoxx @mraible @juliendubois @sendilkumarn #DukesChoiceAward pic.twitter.com/gaNpnJtBYR
— Deepu K Sasidharan (@deepu105) November 9, 2017
Duke might've had a little too much to drink during our BOF. :D
I thought our ratings (~4.2) for the two sessions were “good enough” to call the conference a success. Thanks to the conference organizers for delivering such an awesome experience once again.
I spent the weekend in Bruges and had a lovely time staying at an Airbnb and visiting some local breweries.
On Saturday night, I worked for several hours on the Ionic module for JHipster that I needed for my talk at Devoxx Morocco. That’s where the (self-inflicted) drama began. Here’s the timeline of events that I documented in my presentation after my talk:
I published the slides from "Developing PWAs and Mobile Apps with Ionic, Angular, and JHipster" to Speaker Deck.
I also made a 5 minute video, because I recorded a lot of my development experience along the way.
Phew! It was an exhausting couple of weeks. I learned something I already knew - you should have your presentation finished before you leave for the conference, especially when traveling overseas!
Nevertheless, I had a great time. At Devoxx Belgium, it was announced that Josh and I both won Devoxx Champion awards. This award is given to speakers that attend all the Devoxx conferences in a year. Unfortunately, they never told either of us that we got it, so we missed it in the keynote. Luckily, it was recorded.
At Devoxx Morocco, they notified me five minutes before the keynote that “I should come” and that they had a surprise for me. I was in the midst of my last-minute scramble to get code working and write my presentation, but I went anyway. I’m glad I did because it was a very cool opening keynote and I was honored to receive a Devoxx Champion award.
I made sure to get my picture with Josh, and his girlfriend Tammie, after lunch.
There are two new Okta open source projects as part of my efforts, but they’ll require some polishing before they’re ready for general consumption. I hope to do that before the end of the year, but the end of January is probably more realistic. Below are links to their repos on GitHub:
For more photos from these events, see my album on Flickr. Devoxx Belgium posted their photos to a Devoxx2017 album, as well as albums for each day: day 1, day 2, day 3, day 4, and day 5. Devoxx Morocco posted all of their photos in three separate albums: day 1, day 2, and day 3.
I want to thank the organizers from Devoxx Belgium and Devoxx Morocco for accepting my talks and allow me to fulfill one of my goals for the year: becoming a Devoxx Champion. In 2018, I plan to slow down a bit and speak more in the US, concentrating on Java User Groups.
However, 2017 isn't over! I'll be speaking at SpringOne and The Rich Web Experience next week. We're also planning a Devoxx4Kids Denver meetup in December and a Denver JUG Holiday Party as well.
Last Monday I atended the FOSS Backstage Micro-Summit and enjoyed it at a lot. I haven't been to ApacheCons for quite some time and it was good to see familiar faces and get to know so many new folks.
The slides of my talk are on Speaker Deck but I'm afraid they aren't that useful without the things I actually said.
Update 2017-12-01: video of the talk without the Q&A session that followed it.
react-native run-android
adb shell input keyevent 82
Last Monday I presented on Asynchronous Decision Making at the (excellent) FOSS Backstage Micro Summit in Berlin and there were some questions about me saying that status meetings are a waste of time.
My opinion on status meetings hasn’t changed in a long time and I’m very happy to see Jason Fried loudly confirm it in his status meetings are the scourge post.
Quoting him:
How would you feel if you had to regularly expense $1200 so you could “tell a few teammates something”. Think that would go over well?
If your team shape allows you to run status meetings, you should first reflect on their actual cost. And if you still want to run them after that I suggest:
a) Requiring people to briefly report their status in writing before the meeting, asynchronously
b) Requiring people to read other people’s status before the meeting, asynchronously
c) Choosing a maximum of 3 items to discuss in your meeting,
based on those reports, and timebox those topics during the meeting
d) If you don’t get enough items to deserve interrupting your whole team right now: cancel that meeting! Or maybe limit it to managers to avoid interrupting the Makers.
That’s just the essentials, Jason Fried has more detailed suggestions in a similar spirit, make sure to read his post!
I like the 3P format for brief written status reports:
– Progress: what concrete, measurable progress has been made since last report
– Problems: what’s blocking you from progressing
– Perspectives: what are your plans for the next period
If this post (and Jason’s) help you save tons of money by eliminating useless meetings, feel free to make a donation to a good cause ;-)

![]() |
| Last page of chapter 19 with page count 822 |
Jake was a border collie that came into my life when I met Trish. In fact, I met him on our first date. After dinner, Trish and I wandered back to her place and took her dogs for a walk in Wash Park. She had two: Sagan (the crazy one) and Jake (stoner dog). Jake wasn't a purebred border collie, but he was one of those perfect dogs. He slept a lot, liked to lay in the sunshine, and was always happy to harass Sagan and giggle while doing it when we went on walks.
A few years ago, when I was only working 20 hours per week, I grew to appreciate our dogs more than ever. I'd take them on walks, hikes, and runs almost every afternoon. I learned that living my life like my dogs wanted me to live it was a great thing. Long walks, relaxing in the sun, smiling from ear to ear when a family member comes home.
A few weeks ago, I took both our dogs on a run and Jake was not feeling well. He certainly didn't want to run, and he could barely keep up even when we walked. Trish took him in for some tests, and we discovered his blood cells were under attack. Trish rushed him to CSU's Veterinary Hospital for a blood transfusion. That helped, but we discovered a few days later that his bones were no longer producing red blood cells. Another blood transfusion, a bunch of prescription drugs, and he was back in action. He seemed to be doing great. We drove to Montana last week to visit my parents and brought him with us.
Last Friday, Jake could only walk on three legs. Yesterday, he was down to two. Trish took him in, and his doctor said his liver was failing. Since he was an older dog and lived a great life, we chose not continue keeping him alive. He was put to sleep yesterday afternoon at Aurora Animal Hospital. They allowed him to lay in the grass, in the sunshine, while they carried out the procedure.
I'm happy to have known you, Jake. You were a great dog, and I learned a lot from you. Sleep well, buddy.
Our next concert is the Monteverdi Vespers, on Nov. 26th at the Guildhall, Plymouth. This work, untypical of its own time as well as our own, makes an interesting change from our usual repertoire. Simple individual lines and harmonies rooted firmly in renaissance polyphony, yet with complex (and sometimes fiendish to hold) interweaving textures, and a level of both vocal and orchestral flourishes and ornamentation that makes it arguably the first major work of the Baroque era.
I’m glad to be singing it, and I think it’ll be a good evening out for those in or near Plymouth. Hope to see some of my readers there!