/* A utility for writing the SEGMENTS_GEN file to a Directory. NOTE: this is an internal utility which is kept public so that it's accessible by code from other packages. You should avoid calling this method unless you're absolutely sure what you're doing! */ func writeSegmentsGen(dir store.Directory, generation int64) { if err := func() (err error) { var genOutput store.IndexOutput genOutput, err = dir.CreateOutput(INDEX_FILENAME_SEGMENTS_GEN, store.IO_CONTEXT_READONCE) if err != nil { return err } defer func() { err = mergeError(err, genOutput.Close()) err = mergeError(err, dir.Sync([]string{INDEX_FILENAME_SEGMENTS_GEN})) }() if err = genOutput.WriteInt(FORMAT_SEGMENTS_GEN_CURRENT); err == nil { if err = genOutput.WriteLong(generation); err == nil { if err = genOutput.WriteLong(generation); err == nil { err = codec.WriteFooter(genOutput) } } } return err }(); err != nil { // It's OK if we fail to write this file since it's used only as // one of the retry fallbacks. dir.DeleteFile(INDEX_FILENAME_SEGMENTS_GEN) // Ignore error; this file is only used in a retry fallback on init } }
func (sis *SegmentInfos) finishCommit(dir store.Directory) (fileName string, err error) { assert(dir != nil) assert2(sis.pendingSegnOutput != nil, "prepareCommit was not called") if err = func() error { var success = false defer func() { if !success { // Closes pendingSegnOutput & delets partial segments_N: sis.rollbackCommit(dir) } else { err := func() error { var success = false defer func() { if !success { // Closes pendingSegnOutput & delets partial segments_N: sis.rollbackCommit(dir) } else { sis.pendingSegnOutput = nil } }() err := sis.pendingSegnOutput.Close() success = err == nil return err }() assertn(err == nil, "%v", err) // no shadow } }() if err := codec.WriteFooter(sis.pendingSegnOutput); err != nil { return err } success = true return nil }(); err != nil { return } // NOTE: if we crash here, we have left a segments_N file in the // directory in a possibly corrupt state (if some bytes made it to // stable storage and others didn't). But, the segments_N file // includes checksum at the end, which should catch this case. So // when a reader tries to read it, it will return an index corrupt // error, which should cause the retry logic in SegmentInfos to // kick in and load the last good (previous) segments_N-1 file. fileName = util.FileNameFromGeneration(INDEX_FILENAME_SEGMENTS, "", sis.generation) if err = func() error { var success = false defer func() { if !success { dir.DeleteFile(fileName) // suppress error so we keep returning the original error } }() err := dir.Sync([]string{fileName}) success = err == nil return err }(); err != nil { return } sis.lastGeneration = sis.generation writeSegmentsGen(dir, sis.generation) return }