Skip to content

Instantly share code, notes, and snippets.

@richardartoul
Created March 30, 2018 21:09
Show Gist options
  • Save richardartoul/0dd8527560269677f84ed6ad414bb77e to your computer and use it in GitHub Desktop.
Save richardartoul/0dd8527560269677f84ed6ad414bb77e to your computer and use it in GitHub Desktop.
M3DB Msgpack forwards/backwards compatibility schema.go
// Copyright (c) 2016 Uber Technologies, Inc
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE
// Instructions for adding a new field to an existing object in a backwards
// and forwards compatible way:
// 1. Do not change the objects type
// 2. Do not change the objects version
// 3. Modify the encoder to encode the new fields
// 4. Increase the constant below for the current (not minimum!) number
// of fields per that object
// 5. Modify the decoder to selectively decode the new fields based on
// the actual number of fields that are encoded in the file - See the
// decodeIndexInfo function for an example
package msgpack
const (
// Incrementing any of these values is a backwards-compatible change
// I.E the new binary will still be able to read old files (as long
// as the minimum number of fields for a given object is not also
// increased, see the comment below), but it is not a forwards-compatible
// change I.E old binaries will not be able to read the new files and just
// skip over any unrecognized fields (which they will do if this value is
// not incremented when adding new fields)
indexInfoVersion = 1
indexEntryVersion = 1
indexSummaryVersion = 1
logInfoVersion = 1
logEntryVersion = 1
logMetadataVersion = 1
)
type objectType int
// nolint: deadcode, varcheck, unused
const (
// Adding any new object types is a backwards-compatibe change I.E
// the new binary will still be able to read old files, but it is
// not a forwards-compatible change I.E old binaries will not be
// able to read the new files.
unknownType objectType = iota
rootObjectType
indexInfoType
indexSummariesInfoType
indexBloomFilterInfoType
indexEntryType
indexSummaryType
logInfoType
logEntryType
logMetadataType
// Total number of object types
numObjectTypes = iota
)
const (
// min number of fields specifies the minimum number of fields
// that an object such that the encoder won't reject it. This value
// should be equal to the number of fields in objects that were encoded
// previosly that we still want new binaries to be able to read without
// complaint. I.E if previous versions of M3DB wrote 4 fields for an object,
// and an even earlier version only wrote 3 fields, than the minimum number
// should be 3 if we intend to continue reading files that were written by
// the version that only encoded 3 fields.
minNumRootObjectFields = 2
minNumIndexInfoFields = 6
minNumIndexSummariesInfoFields = 1
minNumIndexBloomFilterInfoFields = 2
minNumIndexEntryFields = 5
minNumIndexSummaryFields = 3
minNumLogInfoFields = 3
minNumLogEntryFields = 7
minNumLogMetadataFields = 3
// curr number of fields specifies the number of fields that the current
// version of the M3DB will encode. This is used to ensure that the
// correct number of fields is encoded into the files. These values need
// to be incremened whenever we add new fields to an object.
currNumRootObjectFields = 2
currNumIndexInfoFields = 8
currNumIndexSummariesInfoFields = 1
currNumIndexBloomFilterInfoFields = 2
currNumIndexEntryFields = 5
currNumIndexSummaryFields = 3
currNumLogInfoFields = 3
currNumLogEntryFields = 7
currNumLogMetadataFields = 3
)
var minNumObjectFields []int
var currNumObjectFields []int
func numFieldsForType(objType objectType) (min, curr int) {
return minNumObjectFields[int(objType)-1], currNumObjectFields[int(objType)-1]
}
func setMinNumObjectFieldsForType(objType objectType, numFields int) {
minNumObjectFields[int(objType)-1] = numFields
}
func setCurrNumObjectFieldsForType(objType objectType, numFields int) {
currNumObjectFields[int(objType)-1] = numFields
}
func init() {
minNumObjectFields = make([]int, int(numObjectTypes))
currNumObjectFields = make([]int, int(numObjectTypes))
setMinNumObjectFieldsForType(rootObjectType, minNumRootObjectFields)
setMinNumObjectFieldsForType(indexInfoType, minNumIndexInfoFields)
setMinNumObjectFieldsForType(indexSummariesInfoType, minNumIndexSummariesInfoFields)
setMinNumObjectFieldsForType(indexBloomFilterInfoType, minNumIndexBloomFilterInfoFields)
setMinNumObjectFieldsForType(indexEntryType, minNumIndexEntryFields)
setMinNumObjectFieldsForType(indexSummaryType, minNumIndexSummaryFields)
setMinNumObjectFieldsForType(logInfoType, minNumLogInfoFields)
setMinNumObjectFieldsForType(logEntryType, minNumLogEntryFields)
setMinNumObjectFieldsForType(logMetadataType, minNumLogMetadataFields)
setCurrNumObjectFieldsForType(rootObjectType, currNumRootObjectFields)
setCurrNumObjectFieldsForType(indexInfoType, currNumIndexInfoFields)
setCurrNumObjectFieldsForType(indexSummariesInfoType, currNumIndexSummariesInfoFields)
setCurrNumObjectFieldsForType(indexBloomFilterInfoType, currNumIndexBloomFilterInfoFields)
setCurrNumObjectFieldsForType(indexEntryType, currNumIndexEntryFields)
setCurrNumObjectFieldsForType(indexSummaryType, currNumIndexSummaryFields)
setCurrNumObjectFieldsForType(logInfoType, currNumLogInfoFields)
setCurrNumObjectFieldsForType(logEntryType, currNumLogEntryFields)
setCurrNumObjectFieldsForType(logMetadataType, currNumLogMetadataFields)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment