And I have news for you. I have an
addrman.h -
serialize.h solution that compiles!
The reason MSVC++ gets ill at addrman.h as you say:
was not only those extra
(()); around the big
IMPLEMENT_SERIALIZE(...) macro in the
CAddrMan class, that implements
GetSerializeSize() Serialize() and Unserialize(), but also the extra complexity of the imbedded
std::map mapUnkIds;!?
When the map<> is "levitated out" of the macro and placed in the
#define IMPLEMENT_SERIALIZE(statements) macro in
serialize.h the compiler hums!
Thanks Ron!
I will try this--do you have those two files online somewhere so I can see exactly what you mean?
No, but I'll put it here! This is 0.8.5 addrman.h though, not 0.8.6 I don't know if there's a difference?
#ifdef _MSC_VER
IMPLEMENT_SERIALIZE
(
LOCK(cs);
unsigned char
nVersion = 0;
READWRITE(nVersion);
READWRITE(nKey);
READWRITE(nNew);
READWRITE(nTried);
CAddrMan
*am = const_cast(this);
if (fWrite)
{
int
nUBuckets = ADDRMAN_NEW_BUCKET_COUNT;
READWRITE(nUBuckets);
/************
std::map
mapUnkIds;
************/
int
nIds = 0;
for (std::map::iterator it = am->mapInfo.begin(); it != am->mapInfo.end(); it++)
{
if (nIds == nNew)
break; // this means nNew was wrong, oh ow
mapUnkIds[(*it).first] = nIds;
CAddrInfo
&info = (*it).second;
if (info.nRefCount)
{
READWRITE(info);
nIds++;
}
}
nIds = 0;
for (std::map::iterator it = am->mapInfo.begin(); it != am->mapInfo.end(); it++)
{
if (nIds == nTried)
break; /* this means nTried was wrong, oh ow */
CAddrInfo
&info = (*it).second;
if (info.fInTried)
{
READWRITE(info);
nIds++;
}
}
for (
std::vector >::iterator it = am->vvNew.begin();
it != am->vvNew.end();
it++
)
{
std::set
&vNew = (*it);
int
nSize = int( vNew.size() );
READWRITE(nSize);
for (std::set::iterator it2 = vNew.begin(); it2 != vNew.end(); it2++)
{
int
nIndex = mapUnkIds[*it2];
READWRITE(nIndex);
}
}
}
else
{
int
nUBuckets = 0;
READWRITE(nUBuckets);
am->nIdCount = 0;
am->mapInfo.clear();
am->mapAddr.clear();
am->vRandom.clear();
am->vvTried =
std::vector >(
ADDRMAN_TRIED_BUCKET_COUNT,
std::vector(0)
);
am->vvNew =
std::vector >(
ADDRMAN_NEW_BUCKET_COUNT,
std::set()
);
for (int n = 0; n < am->nNew; n++)
{
CAddrInfo
&info = am->mapInfo[n];
READWRITE(info);
am->mapAddr[info] = n;
info.nRandomPos = int( vRandom.size() );
am->vRandom.push_back(n);
if (nUBuckets != ADDRMAN_NEW_BUCKET_COUNT)
{
am->vvNew[info.GetNewBucket(am->nKey)].insert(n);
info.nRefCount++;
}
}
am->nIdCount = am->nNew;
int
nLost = 0;
for (int n = 0; n < am->nTried; n++)
{
CAddrInfo
info;
READWRITE(info);
std::vector
&vTried = am->vvTried[info.GetTriedBucket(am->nKey)];
if (vTried.size() < ADDRMAN_TRIED_BUCKET_SIZE)
{
info.nRandomPos = int( vRandom.size() );
info.fInTried = true;
am->vRandom.push_back(am->nIdCount);
am->mapInfo[am->nIdCount] = info;
am->mapAddr[info] = am->nIdCount;
vTried.push_back(am->nIdCount);
am->nIdCount++;
}
else
{
nLost++;
}
}
am->nTried -= nLost;
for (int b = 0; b < nUBuckets; b++)
{
std::set
&vNew = am->vvNew[b];
int
nSize = 0;
READWRITE(nSize);
for (int n = 0; n < nSize; n++)
{
int
nIndex = 0;
READWRITE(nIndex);
CAddrInfo
&info = am->mapInfo[nIndex];
if (
(nUBuckets == ADDRMAN_NEW_BUCKET_COUNT) &&
(info.nRefCount < ADDRMAN_NEW_BUCKETS_PER_ADDRESS)
)
{
info.nRefCount++;
vNew.insert(nIndex);
}
}
}
}
)
#else
And in serialize.h :
#ifdef _MSC_VER
#define IMPLEMENT_SERIALIZE(statements) \
unsigned int GetSerializeSize(int nType, int nVersion) const \
{ \
CSerActionGetSerializeSize ser_action; \
const bool fGetSize = true; \
const bool fWrite = false; \
const bool fRead = false; \
unsigned int nSerSize = 0; \
ser_streamplaceholder s; \
assert(fGetSize||fWrite||fRead); /* suppress warning */ \
s.nType = nType; \
s.nVersion = nVersion; \
std::map mapUnkIds; \
{statements} \
return nSerSize; \
} \
template \
void Serialize(Stream& s, int nType, int nVersion) const \
{ \
CSerActionSerialize ser_action; \
const bool fGetSize = false; \
const bool fWrite = true; \
const bool fRead = false; \
unsigned int nSerSize = 0; \
assert(fGetSize||fWrite||fRead); /* suppress warning */ \
std::map mapUnkIds; \
{statements} \
} \
template \
void Unserialize(Stream& s, int nType, int nVersion) \
{ \
CSerActionUnserialize ser_action; \
const bool fGetSize = false; \
const bool fWrite = false; \
const bool fRead = true; \
unsigned int nSerSize = 0; \
std::map mapUnkIds; \
assert(fGetSize||fWrite||fRead); /* suppress warning */ \
{statements} \
}
#else
Try that on your MSVC++ 2012 preprocessor/first pass! I think it will like it! My MSVC++ 2005 SP1 seems to digest it just fine. I know it is kind of an engineering hack to just make it work, But I'm an engineer! Software, hardware. We just make things work. It's sort of like what physicists do to mathematics
If I remove the extra parens, the MSVC preprocessor actually truncates the source so I think I have a good case for opening up a MS tech support ticket but I can't stomach that right now.
I am very curious, needless to say, how you have built your levelDB static .lib file!
I built the whole 0.8.6 source from the distribution in the setup file, which includes the levelDB source--I never went to google to get it. In other words, I installed 0.8.6 Bitcoin and used the src directory that ships with the installation. I never had trouble building levelDB but I did create the project file from scratch. I have no idea if my port of Bitcoin would pass all regression tests but it seems to work for me on testnet.
Just made a static library project for leveldb source tree, right out of the bitcoin sources. Actually downloaded all the versions too, from
https://code.google.com/p/leveldb/downloads/listfrom 1.9 to 1.15, since bitcoin used 1.9 in 0.8.1 They all have the same directory "shape" as the leveldb directory in bitcoin. Then "exclude from project" all the ones that say *_test.cc and *_bench.cc, "exclude" all port_*.* except port_win.*, ditto for env_*.cc except env_win.cc. I kept
memenv_test.cc because that is what bitcoin does when it builds its .a files? That's about it. I don't even think you have to add
LEVELDB_PLATFORM_WINDOWS to the prepocessor definitions? I think it "knows"? Don't remember. Oops, it seems I forgot a lot! I worked from this:
http://leveldb.googlecode.com/git-history/windows/WINDOWS Add each _test.cc, _bench.cc back in one at a time, compile (as and exe) any run them. I did and the code passed all its own tests. I think 12 of the 15, the other 3 need environment variables to drive the tests and I couldn't find any guidance on that
Another "how to build static libraries" videos seems needed!
Also, to continue from my personal message, one of the reasons I am publishing this is because I would like to see the mainstream financial world take a closer look at Bitcoin.
I agree. But I think you are too kind
I want every desktop Windows machine on the internet using bitcoin! If you saw my link,
http://www.netmarketshare.com/operating-system-market-share.aspx?qprid=10&qpcustomd=0 in a previous messages here, there are 9 times more Windows desktops on the internet, that can be running full clients than all the others (Linux, mac, etc.) combined! So I think that what you and I are doing is great!
I know from experience that many mainstream corporate software developers (at least the ones I know) will *NOT* enthusiastically embrace MinGW, gcc, etc, unless, maybe, if it involved Android. But on Windows?? No way. But the main reason is because I wanted to learn how it works and MSVC is great for stepping through code in debug.
Absolutely! And the full screen real time debugger can do much more (this is to whet the appetite of those gcc-ers who have never seen a VC++ IDE in incremental link edit-compile-link-debug). You can even edit while debugging and continue debugging! All local variables, and automatics, globals, displayed in hex or decimal, with the ability to follow all the classes, members, derived, overloaded, resolved,..., watch points, intellisense,... It may have been one of the few things that Microsoft got right. Oh and it can compile all of it for the ARM and other processor architectures too. And it's all free with the Express editions. The VS (Visual Studios) that one pays for have even more goodies. Even program guided optimization for those with the time and desire! I'm not really trying to sell it since it is free
And it can help you edit and understand your code even if you stay in gcc! Its "solution explorer in Class View" shows all the classes, etc. etc.
And then I thought it would be nice if I share my work
I thank you for that. I will too, when I can get it to honestly save a new block (every time)! It's close. I think I am getting some "deadlock" conditions while "-reindex"-ing and "compacting"? Not always, leveldb will "corrupt" the last index file (.sst file in the chainstate directory) and drop out, letting bitcoin start to connect to peers. Then random "deadlocks" occur in the net.cpp thread
ThreadSocketHandler(). Back to debugging.
You know what Brian Kernighan said about debugging:
http://en.wikiquote.org/wiki/Brian_KernighanRon