# HG changeset patch # User Jens Alfke # Date 1254264402 25200 # Node ID 629f61203db1fd8007718b4e3e57d5a582d931a7 # Parent 21a6c17f4e3e9c20f66abec2556cd91c128c8d20 * Merged in jbm's changes for Linux compatibility, fixing Mac compatibility in the process :) * Fixed two regressions having to do with the _previousTrailerPosition in VersionDictionary.cpp. * Made sure RTTI is enabled in the OttomanTest target because gtest requires it. diff -r 21a6c17f4e3e -r 629f61203db1 Ottoman.xcodeproj/project.pbxproj --- a/Ottoman.xcodeproj/project.pbxproj Mon Sep 28 23:39:08 2009 -0700 +++ b/Ottoman.xcodeproj/project.pbxproj Tue Sep 29 15:46:42 2009 -0700 @@ -409,6 +409,7 @@ ALWAYS_SEARCH_USER_PATHS = NO; COPY_PHASE_STRIP = NO; GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_CPP_RTTI = YES; GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_MODEL_TUNING = G5; GCC_OPTIMIZATION_LEVEL = 0; @@ -423,6 +424,7 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_CPP_RTTI = YES; GCC_MODEL_TUNING = G5; INSTALL_PATH = /usr/local/bin; PRODUCT_NAME = OttomanTest; @@ -434,6 +436,7 @@ buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_BIT)"; GCC_C_LANGUAGE_STANDARD = c99; + GCC_ENABLE_CPP_RTTI = NO; GCC_INLINES_ARE_PRIVATE_EXTERN = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PRECOMPILE_PREFIX_HEADER = YES; diff -r 21a6c17f4e3e -r 629f61203db1 include/Base.h --- a/include/Base.h Mon Sep 28 23:39:08 2009 -0700 +++ b/include/Base.h Tue Sep 29 15:46:42 2009 -0700 @@ -13,17 +13,8 @@ #include #include -#if OSX -/* OS X specific bits */ -#include +#ifdef __MACH__ /* OS X specific bits */ #include - -#else -/* OS X fixup kludge bits */ - -#include -#include - #endif namespace Mooseyard { @@ -105,7 +96,8 @@ _value = p._value; return *this; } - + +#ifdef __COREFOUNDATION_CFBYTEORDER__ template <> inline uint32_t LittleEndian::makeLittle (uint32_t i) {return OSSwapHostToLittleInt32(i);} template <> inline uint32_t LittleEndian::makeNative (uint32_t i) @@ -118,7 +110,21 @@ {return CFConvertDoubleHostToSwapped(d);} template <> inline double LittleEndian::makeNative (CFSwappedFloat64 d) {return CFConvertDoubleSwappedToHost(d);} - +#else + //FIXME: Not implemented yet for non-Mac platforms + template <> inline uint32_t LittleEndian::makeLittle (uint32_t i) + {return i;} + template <> inline uint32_t LittleEndian::makeNative (uint32_t i) + {return i;} + template <> inline uint16_t LittleEndian::makeLittle (uint16_t i) + {return i;} + template <> inline uint16_t LittleEndian::makeNative (uint16_t i) + {return i;} + template <> inline CFSwappedFloat64 LittleEndian::makeLittle (double d) + {return d;} + template <> inline double LittleEndian::makeNative (CFSwappedFloat64 d) + {return d;} +#endif } #endif /* _MOOSEYARD_BASE_ */ diff -r 21a6c17f4e3e -r 629f61203db1 include/File.h --- a/include/File.h Mon Sep 28 23:39:08 2009 -0700 +++ b/include/File.h Tue Sep 29 15:46:42 2009 -0700 @@ -30,8 +30,7 @@ static const int kEOF = 10001; - File (const char *filename, bool writeable =false, bool create =false) throw(Error); - File (const char *filename, int oflag, bool locked) throw(Error); + File (const char *filename, int oflag, bool locked =false) throw(Error); ~File(); off_t length() const throw(Error); @@ -90,10 +89,6 @@ private: static int _open (const char *filename, int posixMode) throw(Error); static int _check (int result) throw(Error); -#ifdef OSX /* On linux, these are the same type signature to gcc */ - static ssize_t _check (ssize_t result) throw(Error) {_check((int)result); return result;} - static off_t _check (off_t result) throw(Error) {_check((int)result); return result;} -#endif static void _checkRead (ssize_t result, size_t expectedSize) throw(Error); bool _lock (bool block); void _unlock(); diff -r 21a6c17f4e3e -r 629f61203db1 src/File.cpp --- a/src/File.cpp Mon Sep 28 23:39:08 2009 -0700 +++ b/src/File.cpp Tue Sep 29 15:46:42 2009 -0700 @@ -21,14 +21,8 @@ namespace Mooseyard { - File::File (const char *filename, bool writeable, bool create) throw(Error) - :_fd(_check( ::open(filename, writeable ?(create ?O_RDWR|O_CREAT :O_RDWR) :O_RDONLY, 0644) )), - _memoryMap(NULL), - _locked(0) - { } - File::File (const char *filename, int oflag, bool locked) throw(Error) -#if BSD +#ifdef _DARWIN_C_SOURCE :_fd(_check( ::open(filename, oflag | (locked ? O_EXLOCK : 0), 0644) )), #else :_fd(_check( ::open(filename, oflag, 0644) )), @@ -36,7 +30,7 @@ _memoryMap(NULL), _locked( locked ? 1 : 0) { -#if !BSDISH +#ifndef _DARWIN_C_SOURCE _check( ::flock(_fd, LOCK_EX) ); #endif } @@ -59,15 +53,21 @@ } off_t File::position() const throw(Error) { - return _check( lseek(_fd,0,SEEK_CUR) ); + off_t pos = lseek(_fd,0,SEEK_CUR); + if (pos < 0) + _check(-1); + return pos; } void File::setPosition (off_t pos) throw(Error) { - _check( lseek(_fd,pos,SEEK_SET) ); + _check( (int) lseek(_fd,pos,SEEK_SET) ); } off_t File::setPositionToEnd (off_t bytesBefore) throw(Error) { - return _check( lseek(_fd,-bytesBefore,SEEK_END) ); + off_t pos = lseek(_fd,-bytesBefore,SEEK_END); + if (pos < 0) + _check(-1); + return pos; } void File::read (void *dst, size_t size) throw(Error) { @@ -111,7 +111,13 @@ } void File::flushDisk() throw(Error) { -#if OSX +#if _DARWIN_C_SOURCE + /* F_FULLFSYNC is Mac/Darwin specific. From the man page: + Does the same thing as fsync(2) then asks the drive to flush all buffered data to + the permanent storage device (arg is ignored). This is currently implemented on + HFS, MS-DOS (FAT), and Universal Disk Format (UDF) file systems. The operation may + take quite a while to complete. Certain FireWire drives have also been known to + ignore the request to flush their buffered data. */ _check( ::fcntl(_fd,F_FULLFSYNC) ); #else _check( fsync(_fd) ); diff -r 21a6c17f4e3e -r 629f61203db1 src/Index.cpp --- a/src/Index.cpp Mon Sep 28 23:39:08 2009 -0700 +++ b/src/Index.cpp Tue Sep 29 15:46:42 2009 -0700 @@ -15,10 +15,6 @@ #include #include #include - -#define __STDC_LIMIT_MACROS /* I <3 you, C99 */ -# define UINT32_MAX (4294967295U) - #include diff -r 21a6c17f4e3e -r 629f61203db1 src/Ottoman.cpp --- a/src/Ottoman.cpp Mon Sep 28 23:39:08 2009 -0700 +++ b/src/Ottoman.cpp Tue Sep 29 15:46:42 2009 -0700 @@ -42,6 +42,7 @@ Ottoman::Ottoman() :_writeable(true), + _file(NULL), _filename(NULL), _lastVersion(NULL), _current( new OverlayDictionary(&Dictionary::kEmpty) ) @@ -96,6 +97,9 @@ delete _file; _file = curFile; } + + if (changed) + versionsChanged(); return changed; } @@ -196,11 +200,12 @@ if (!lastVersion) lastVersion = new VersionDictionary(dstFile); VersionDictionary *saved = lastVersion->_appendAndOpen(_current->overlay(), - dstFile, - _current->baseReplaced()); + dstFile, + _current->baseReplaced()); // (don't delete _lastVersion: saved->_previousVersion now points to it.) _lastVersion = saved; _current->revertTo(_lastVersion); + versionsChanged(); } bool Ottoman::save() { @@ -235,6 +240,7 @@ File *dstFile = _writeTo(dstFileName, overwriteAllowed); free(_filename); _filename = strdup(dstFileName); + delete _file; _file = dstFile; } @@ -242,8 +248,13 @@ if (!_file) return false; char tempFileName[1024]; +#ifdef _DARWIN_C_SOURCE + ::strlcpy(tempFileName, _filename, sizeof(tempFileName)-1); + ::strlcat(tempFileName, "~", sizeof(tempFileName)); +#else ::strncpy(tempFileName, _filename, sizeof(tempFileName)-1); ::strncat(tempFileName, "~", sizeof(tempFileName)); +#endif File *tempFile; { // Check for conflict in existing file: diff -r 21a6c17f4e3e -r 629f61203db1 src/VersionDictionary.cpp --- a/src/VersionDictionary.cpp Mon Sep 28 23:39:08 2009 -0700 +++ b/src/VersionDictionary.cpp Tue Sep 29 15:46:42 2009 -0700 @@ -12,13 +12,12 @@ #include "Index.h" #include "File.h" #include "Chunk.h" +#include #include #include -#include +#include #include -# define UINT32_MAX (4294967295U) - namespace Mooseyard { @@ -153,9 +152,8 @@ // Verify Indexes: for (int i=0; i<256; i++) { - if (_indexPositions[i] > 0) - if (_indexPositions[i] < _previousTrailerPosition || _indexPositions[i] >= _trailerPosition) - throw File::Error("Bad VersionDictionary trailer (illegal index position)"); + if (_indexPositions[i] >= _trailerPosition) + throw File::Error("Bad VersionDictionary trailer (illegal index position)"); const Index *index = _index(i); if (index) index->validate(); @@ -289,10 +287,13 @@ dstFile->flushDisk(); // Write the trailer: + FilePosition previousTrailerPosition = 0; + if (dstFile==srcFile) + previousTrailerPosition = baseDict->_trailerPosition; FilePosition newTrailerPosition = pos; VersionDictionary::Trailer trailer(newCount, newIndexPositions, - baseDict->_trailerPosition, + previousTrailerPosition, baseDict->generation() + 1); pos += dstFile->write(trailer); @@ -312,10 +313,7 @@ } } - -#pragma mark - -#pragma mark TESTING-ONLY: - + VersionDictionary* VersionDictionary::_appendAndOpen (const Dictionary *addDict, File *dstFile, bool replace) const @@ -326,6 +324,10 @@ return nextVersion; } + +#pragma mark - +#pragma mark TESTING-ONLY: + VersionDictionary* VersionDictionary::create (File *file, const Dictionary *srcDict) { return VersionDictionary(file)._appendAndOpen(srcDict, file, true); } diff -r 21a6c17f4e3e -r 629f61203db1 test/TestUtils.cpp --- a/test/TestUtils.cpp Mon Sep 28 23:39:08 2009 -0700 +++ b/test/TestUtils.cpp Tue Sep 29 15:46:42 2009 -0700 @@ -25,7 +25,7 @@ void shuffle(int a[], int n, unsigned seed) { if (seed==0) { -#ifdef BSD +#ifdef _DARWIN_C_SOURCE srandomdev(); #endif seed = random(); @@ -54,16 +54,11 @@ while (NULL != ::fgets(word, 4096, in)) { wordLen = ::strlen(word); if (word[wordLen-1]=='\n') { - word[wordLen-1] = '\0'; - wordLen--; - } - - if (wordLen == 0) continue; - - sWords[sNWords] = strdup(word); - //if( sNWords % 10000 == 0) - // printf("'%s' ... ", sWords[sNWords]->string()); - sNWords++; + word[wordLen-1] = '\0'; + wordLen--; + } + if (wordLen > 0) + sWords[sNWords++] = strdup(word); } } } @@ -99,7 +94,7 @@ using namespace Mooseyard; int main(int argc, char **argv) { -#if BSD +#ifdef _DARWIN_C_SOURCE srandomdev(); #endif try { diff -r 21a6c17f4e3e -r 629f61203db1 test/VersionDictionary_test.cpp --- a/test/VersionDictionary_test.cpp Mon Sep 28 23:39:08 2009 -0700 +++ b/test/VersionDictionary_test.cpp Tue Sep 29 15:46:42 2009 -0700 @@ -46,16 +46,16 @@ TEST(File,HasPath) { { - File f("/tmp/jubba", O_RDWR | O_CREAT | O_TRUNC, true); + File f("/tmp/jubba", O_RDWR | O_CREAT | O_TRUNC); f.write("howdy"); } { - File f("/tmp/jubba", O_RDWR, true); + File f("/tmp/jubba", O_RDWR); EXPECT_TRUE(f.hasPath("/tmp/jubba")); File::unlink("/tmp/jubba"); EXPECT_FALSE(f.hasPath("/tmp/jubba")); - File f2("/tmp/jubba", O_RDWR | O_CREAT | O_TRUNC, true); + File f2("/tmp/jubba", O_RDWR | O_CREAT | O_TRUNC); f2.write("howdy"); f2.flush(); @@ -108,7 +108,7 @@ time_t startTime = ::time(NULL); time_t createTime; { - File file("/tmp/hashfiletest", O_RDWR | O_CREAT | O_TRUNC, true); + File file("/tmp/hashfiletest", O_RDWR | O_CREAT | O_TRUNC); VersionDictionary *hf; { Timer t("Creating & writing VersionDictionary", nWords); @@ -124,7 +124,7 @@ delete hf; } { - File file("/tmp/hashfiletest"); + File file("/tmp/hashfiletest", O_RDONLY); VersionDictionary hf(&file); ASSERT_EQ(0, hf.generation()); ASSERT_EQ(createTime, hf.timestamp()); @@ -152,7 +152,7 @@ } { printf("Opening OverlayVersionDictionary...\n"); - File file("/tmp/hashfiletest", O_RDWR, true); + File file("/tmp/hashfiletest", O_RDWR); OverlayVersionDictionary hf(&file); EXPECT_EQ( nWords , hf.count() ); EXPECT_TRUE(hf.get("abatement").equals("abatement")); @@ -196,7 +196,7 @@ } { printf("Re-opening OverlayVersionDictionary...\n"); - File file("/tmp/hashfiletest"); + File file("/tmp/hashfiletest", O_RDONLY); OverlayVersionDictionary hf(&file); ASSERT_EQ(1, hf.generation()); @@ -222,17 +222,17 @@ } { printf("Writing VersionDictionary to a new file...\n"); - File oldFile("/tmp/hashfiletest"); + File oldFile("/tmp/hashfiletest", O_RDONLY); OverlayVersionDictionary oldhf(&oldFile); - File newFile("/tmp/hashfiletest2", O_RDWR | O_CREAT | O_TRUNC, true); + File newFile("/tmp/hashfiletest2", O_RDWR | O_CREAT | O_TRUNC); newFile.write("Ha5h", 4); // VersionDictionary won't write to an empty file oldhf.saveAs(&newFile); printf("File size: %llu bytes\n", newFile.length()); } { printf("Opening new file...\n"); - File file("/tmp/hashfiletest2"); + File file("/tmp/hashfiletest2", O_RDONLY); OverlayVersionDictionary hf(&file); EXPECT_EQ( nWords , hf.count() );