Upgrade to varnish v4 - varnish

We've upgraded varnish v3 to v4 and I currently working on converting my vcl.
In the v3 version we've used inline C to set and read headers with following functions:
VRT_GetHdr(sp, HDR_REQ, header);
VRT_SetHdr(sp, HDR_REQ, header, value , vrt_magic_string_end);
However in version 4 those functions are are slighty changed.
After some searching we've found that's we need to use a kind of a structure to define a header.
VCL_HEADER hdrdef;
hdrdef->where = HDR_REQ;
hdrdef->what = "\005Test:";
When using this we get a compiler fail with message that it cannot assign to a read only object.
Do somebody know how we can utilize/fill this structure?
Thanks in advance!
Kristof

This should do the trick:
C{
static const struct gethdr_s VGC_HDR_REQ_hdrdef = { HDR_REQ, "\005Test:" };
}C
C{
VRT_SetHdr(ctx, &VGC_HDR_REQ_hdrdef, value, vrt_magic_string_end);
}C
See: https://github.com/varnish/Varnish-Cache/blob/master/bin/varnishtest/tests/r01406.vtc

Related

How to create a Uuid with static lifetime?

I want to have a static Uuid in my Rust program but I am unable to figure out how to do it.
I tried this but it does not work
fn type_id() -> &'static uuid::Uuid {
let tmp = "9cb4cf49-5c3d-4647-83b0-8f3515da7be1".as_bytes();
let tmp = uuid::Uuid::from_slice(tmp).unwrap();
&tmp
}
error: cannot return reference to local variable `tmp`
returns a reference to data owned by the current function (rustc E0515)
Assuming you're using the uuid crate, several of the "constructor" functions are const. So you can just call them "normally" to initialise your static (which is a const context).
Sadly the playground doesn't have uuid but I figure something along the lines of:
static TYPE_ID: Uuid = Uuid::from_u128(0x9cb4cf49_5c3d_4647_83b0_8f3515da7be1);
or using the hex_literal crate if you prefer something more string-looking:
static TYPE_ID: Uuid = Uuid::from_bytes(hex!("9cb4cf49 5c3d 4647 83b0 8f3515da7be1"));
Thanks #PitaJ. Using once_cell:Lazy works. I am still curious to know if there is a simpler way of doing this so I won't mark the answer as accepted yet.
static TYPE_ID: Lazy<uuid::Uuid> = Lazy::new(|| {
let tmp = "9cb4cf49-5c3d-4647-83b0-8f3515da7be1";
let tmp = uuid::Uuid::from_str(tmp).unwrap();
tmp
});

Unable to initialize static set of strings inside templatized class in CLang, works fine in GCC

I'm using Boost config_file_iterator to parse a parameters file for different modules in the standard Boost way:
[Module 1 name]
M1_Key1=value1
[Module 2 name]
M2_Key1=value2
For that, Boost has the nice feature to accept a std::set containing all the valid keys, to throw an exception in case a non-valid one is passed.
boost::program_options::detail::config_file_iterator cfgIt(configStream, ALLOWED_PARAMS);
In my code, I've a set of modules, each one with its own set of parameters, In each one of the module header I have (as non-member variables):
module1.h:
static const std::string MODULE1_NAME = "Module 1 name";
static const std::string MODULE1_KEY1 = "M1_Key1";
module2.h:
static const std::string MODULE2_NAME = "Module 2 name";
static const std::string MODULE2_KEY1 = "M2_Key1";
In the header file for the parameters parser:
class ParametersParser
{
static const std::set<std::string> ALLOWED_PARAMS;
}
Finally in the source file of that parameter parser groups all the allowed values for the config iterator from the different modules:
#include "module1.h"
#include "module2.h"
const std::set<std::string> ParametersParser::ALLOWED_PARAMS =
{{
MODULE1_NAME + std::string(".") + MODULE1_KEY1,
MODULE2_NAME + std::string(".") + MODULE2_KEY1
}};
since Boost expects that as the allowed parameters set, a set of string of the way "Module X Name.MX_KeyY", and that worked fine.
However, because of other reasons, I've templatized the class that parses the file, so now my set of strings is declared also in the same header file, as:
#include "module1.h"
#include "module2.h"
/* Class definition */
template <class T>
class ParametersParser
{
static const std::set<std::string> ALLOWED_PARAMS;
};
/* Static member initialization */
template <class T>
const std::set<std::string> ParametersParser<T>::ALLOWED_PARAMS =
{{
MODULE1_NAME + std::string(".") + MODULE1_KEY1,
MODULE2_NAME + std::string(".") + MODULE2_KEY1
}};
And here is where the problem arises: This compiles in both gcc 4.8.5 (CentOS 7.5 vanilla) and AppleClang 9.1.0.9020039 (MacOSX 10.3), but in MacOSX, the resulting set only contains a ".". It's like the static strings defined in the modules headers (MODULE1_NAME, MODULE1_KEY1, etc) are empty!!! In gcc/CentOS, it works fine. Unfortunately, I couldn't compile on gcc for MacOSX (It complains about unresolved dependencies with Boost), while CLang on CentOS (Apple LLVM version 9.1.0 (clang-902.0.39.2)) works fine too.
Do you have any clues what am I doing wrong? Is it something about using strings as static variables? I also tried declaring the set using the new initializer list syntax, const std::set<std::string> ParametersParser<T>::ALLOWED_PARAMS{{...}}, but didn't work either.
Thanks a lot for your help.

What is the correct monotouch binding for this?

It seems most of the examples regarding binding an Objective-C library to c# show methods and properties, but what do you do with instance variables that are declared?
Here's an example of the .h file I'm trying to create a binding for:
#interface NdefRecord : NSObject
{
#public
uint8_t Flags;
NDEF_TNF_Type Tnf;
uint8_t TypeLength;
uint8_t *Type;
uint8_t IdLength;
uint8_t *Id;
uint32_t PayloadLength;
uint8_t *PayloadData;
}
/**
Initialize this record.
- Optional: Since member fields are public, you can also set them directly.
*/
- (id) init:(NDEF_TNF_Type)tnf type:(NSData*)type Id:(NSData*)IdBytes payload:(NSData*)payload;
/**
Parse an NDEF Record from raw bytes.
*/
- (BOOL) parse:(UInt8*)data;
/**
Returns this entire NDEF Record as a byte array.
*/
- (uint32_t) toByteArray:(UInt8*)buffer;
...
#end
In my binding project, things like the parse: method are easy enough to bind, but things like TypeLength and *Type were missed by Objective Sharpie, and nothing I seem to hand create works properly.
In an iOS XCode project, those variables are accessed with syntax like so:
record->TypeLength instead of [record TypeLength] which leads me to believe a simple binding like:
[Export ("TypeLength")]
Byte TypeLength { get; set; }
isn't going to work.
I'm completely stuck on a solution here, so any guidance is much appreciated!
The binding tool does not support accessing internal fields of a class, which is what you are trying to do here.
The only thing you can bind with an [Export] are actual properties and methods.
You need to alter that library to expose properties to those internals.

customized error reporting in v4

Another question on migrating code from v3 to v4:
For v3, I had a customized error reporting, using code like this (in the grammar file):
#members {
public void displayRecognitionError(String[] tokenNames,
RecognitionException e) {
String hdr = getErrorHeader(e);
String msg = getErrorMessage(e, tokenNames);
System.out.println("ERR:"+hdr+":"+msg);
errCount += 1;
}
}
In v4, when compiling the generated java files, I am getting the error:
MyParser.java:163: cannot find symbol
symbol : method getErrorMessage(org.antlr.v4.runtime.RecognitionException,java.lang.String[])
location: class MyParser
String msg = getErrorMessage(e, tokenNames);
^
Is this function replaced by some other function in v4? (I saw some questions and answers on ANTLRErrorListener, but I could not get how to use it for my situation.)
The displayRecognitionError method was removed in ANTLR 4, so even if you correct the body of that method it will not do anything. You need to remove the method from your grammar entirely, and implement ANTLRErrorListener instead. The documentation includes a list of classes that implement the interface, so you can reference those and/or extend one of them to produce the desired functionality.
Once you have an instance of an ANTLRErrorListener, you can use the following code to attach it to a Parser instance.
// remove the default error listener
parser.removeErrorListeners();
// add your custom error listener
parser.addErrorListener(listener);

inserting "this" into an STL map from the constructor

VERSION 1
class Doh {
private:
static std::map<const std::string, const Doh*> someMap;
std::string stringValue_;
public:
Doh(std::string str) : stringValue_(str) {
Doh::someMap.insert(
std::make_pair<const std::string,const Doh*>
(this->stringValue_,this)
);
}
}
The above was ok with MSVC 2010 but with MSVC 2008 it fails – and I guess it is because the object is not constructed yet when it is inserted in the map (I got a memory access violation).
So, I tried a delayed insertion, which worked:
VERSION 2
Doh(std::string str) : stringValue_(str) {
boost::thread(&Doh::insertIntoTheStaticMap,this);
}
void insertIntoTheStaticMap() {
boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
Doh::someMap.insert(
std::make_pair<const std::string,const Doh*>
(this->stringValue_,this)
);
}
But as you might be able to guess, my intention is to have the static Doh::someMap as a common lookup dictionary.
VERSION 1 didn’t need any thread-safety because I would create all Doh instances in the same thread – in initialization blocks - which would be called by dynamic initializers before I enter main().
But with VERSION 2, the naïve sleep() is neither graceful nor reliable (not to mention, I might need to lock the map before insertion).
What would be a nice KISS approach?
Only potential issue I see is the initialization of the static member, if there are multiple source files. Try guarding it with a function.
class Doh {
private:
static std::map< std::string, Doh * > &get_map() {
static std::map< std::string, Doh * > someMap;
return someMap; // initialize upon first use
}
std::string stringValue_;
public:
Doh(std::string str) : stringValue_(str) {
get_map().insert(
std::make_pair
(this->stringValue_,this)
);
}
};
In neither version is there any sign of init for stringvalue_ - what does the debugger show you about this key when you hit the map insert in version 1 of the code? How is this field set up, and what is its type?
Running this in the debugger for VS2008 should allow you to narrow down the point of failure into the <map> source, I would have thought.

Resources