Bug 106386 Correct misspellings in source code

patch by unknown@simplemachines.org r=timeless rs=brendan
This commit is contained in:
timeless%mozdev.org 2005-11-25 08:05:54 +00:00
Родитель f048013d47
Коммит 8049c182cd
39 изменённых файлов: 1 добавлений и 16683 удалений

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,150 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
// DebuggerChannel.h
//
// Scott M. Silver
// A simple minded communication stream for
// the debugger pieces client/server
#ifndef _H_DEBUGGERCHANNEL
#define _H_DEBUGGERCHANNEL
#include "prio.h"
#include "prprf.h"
#include "Fundamentals.h"
#include "prlock.h"
#ifdef assert
#undef assert
#include <assert.h>
#endif
#ifdef XP_PC
# include <wtypes.h>
#endif
// FIX-ME endianness???
struct DebuggerMessageRequest
{
Int32 request;
};
struct DebuggerMessageResponse
{
Int32 status; // 0 = succesful, non-zero is an error code
};
const Int32 kAddressToMethod = 120;
const Int32 kMethodToAddress = 121;
const Int32 kRequestNotifyMethodCompiledLoaded = 122;
const Int32 kNotifyMethodCompiledLoaded = 123;
const Int32 kRunClass = 124;
const Int32 kNotifyOnClassLoad = 125;
const Int32 kNotifyOnException = 126;
const Int32 kRequestDebuggerThread = 127;
class NS_EXTERN DebuggerStream
{
PRFileDesc* mFileDesc;
public:
DebuggerStream(PRFileDesc* inCommChannel) :
mFileDesc(inCommChannel) { }
DebuggerStream() :
mFileDesc(0) { }
void writeRequest(Int32 inRequest);
Int32 readRequest();
void writeResponse(Int32 inStatus);
Int32 readResponse();
Int32 readLength(); // actual binary int32
void writeString(const char* inString);
char* readString(); // string must be deleted [] by callee
void* readPtr();
void writePtr(const void* inPtr);
// r/w raw buffer dumping
void writeDataRaw(const void* inData, Int32 inLength);
void readDataRaw(void* outData, Int32 inLength);
// r/w length preceded data
void writeData(const void* inData, Int32 inLength);
void* readData();
};
#ifdef WIN32
void NS_EXTERN setDebuggerThreadID(DWORD inThreadID);
DWORD NS_EXTERN getDebuggerThreadID();
#define SET_DEBUGGER_THREAD_ID(inID) \
PR_BEGIN_MACRO \
setDebuggerThreadID(inID); \
PR_END_MACRO
#else
#define SET_DEBUGGER_THREAD_ID(inID) \
PR_BEGIN_MACRO \
PR_END_MACRO
#endif
const int kDebuggerPort = 8001;
typedef void (*NotifyCompileOrLoadedMethodHandler)(const char*, void*);
class NS_EXTERN DebuggerClientChannel
{
DebuggerStream mSync;
DebuggerStream mAsync;
NotifyCompileOrLoadedMethodHandler mCompLoadHandler;
PRLock* mLock;
public:
static DebuggerClientChannel* createClient();
char* requestAddressToMethod(const void* inAddress, Int32& outOffset);
void* requestMethodToAddress(const char* inMethodName);
void sendOneCharacterRequest(char inCharRequest);
void* requestDebuggerThread();
Int32 requestNotifyOnMethodCompileLoad(const char* inMethodName);
Int32 requestRunClass(const char* inClassName);
Int32 requestNotifyOnClassLoad(const char* inClassName);
Int32 requestNotifyOnException(const char* inClassName);
void setCompileOrLoadMethodHandler(NotifyCompileOrLoadedMethodHandler inHandler) { mCompLoadHandler = inHandler; }
protected:
DebuggerClientChannel(PRFileDesc* inSync, PRFileDesc* inAsync);
void handleCompileOrLoadedMethod(const char* inMethodName, void *inAddress)
{
if (mCompLoadHandler)
(*mCompLoadHandler)(inMethodName, inAddress);
}
bool waitForAsyncRequest();
static void asyncRequestThread(void* inThisPtr);
void handleAsyncRequest(Int32 inRequest);
};
#endif

Просмотреть файл

@ -1,591 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "JavaVM.h"
#include "Debugger.h"
#include "jvmdi.h"
#include "NativeCodeCache.h"
#include "Thread.h"
extern "C" {
static JVMDI_EventHook eventHook;
/*
* Return via "statusPtr" the status of the thread as one of
* JVMDI_THREAD_STATUS_*.
* Errors: JVMDI_ERROR_INVALID_THREAD, JVMDI_ERROR_NULL_POINTER
*/
JNIEXPORT JNICALL(jvmdiError)
JVMDI_GetThreadStatus(JNIEnv * /* env */, jthread thread, jint *statusPtr)
{
if (statusPtr == NULL) {
return JVMDI_ERROR_NULL_POINTER;
}
Thread::JavaThread *jt = (Thread::JavaThread *) thread;
Thread *t = (Thread*)static_cast<int32>(jt->eetop);
*statusPtr = t->getStatus();
return JVMDI_ERROR_NONE;
}
/* Note: jvm.h has suspend/resume (which may be deprecated - as
* Thread.suspend() has been). JVMDI version is different, as it
* takes precautions to attempt to avoid deadlock. Also it
* cannot be depreciated.
*/
/*
* Suspend the specified thread.
* Errors: JVMDI_ERROR_INVALID_THREAD, JVMDI_ERROR_THREAD_SUSPENDED,
* JVMDI_ERROR_VM_DEAD
*/
JNIEXPORT JNICALL(jvmdiError)
JVMDI_SuspendThread(JNIEnv * /*env*/, jthread thread)
{
Thread::JavaThread *jt = (Thread::JavaThread *) thread;
Thread *t = (Thread*)static_cast<int32>(jt->eetop);
t->suspend();
return JVMDI_ERROR_NONE;
}
/*
* Resume the specified thread.
* Errors: JVMDI_ERROR_INVALID_THREAD, JVMDI_ERROR_THREAD_NOT_SUSPENDED,
* JVMDI_ERROR_VM_DEAD
*/
JNIEXPORT JNICALL(jvmdiError)
JVMDI_ResumeThread(JNIEnv * /*env*/, jthread thread)
{
Thread::JavaThread *jt = (Thread::JavaThread *) thread;
Thread *t = (Thread*)static_cast<int32>(jt->eetop);
t->resume();
return JVMDI_ERROR_NONE;
}
/*
* If shouldStep is true cause the thread to generate a
* JVMDI_EVENT_SINGLE_STEP event with each byte-code executed.
* Errors: JVMDI_ERROR_INVALID_THREAD,
* JVMDI_ERROR_THREAD_NOT_SUSPENDED (should suspension be a requirement?),
* JVMDI_ERROR_VM_DEAD
*/
JNIEXPORT JNICALL(jvmdiError)
JVMDI_SetSingleStep(JNIEnv * /*env*/, jthread thread, jboolean shouldStep)
{
Thread::JavaThread *jt = (Thread::JavaThread *) thread;
jt->single_step = shouldStep;
return JVMDI_ERROR_NONE;
}
/*
* Thread Groups
*/
/*
* Return in 'groupsPtr' an array of top-level thread groups (parentless
* thread groups).
* Note: array returned via 'groupsPtr' is allocated globally and must be
* explictly freed with DeleteGlobalRef.
* Errors: JVMDI_ERROR_NULL_POINTER, JVMDI_ERROR_OUT_OF_MEMORY
*/
JNIEXPORT JNICALL(jvmdiError)
JVMDI_GetTopThreadGroups(JNIEnv * /*env*/, jobjectArray * /*groupsPtr*/)
{
return JVMDI_ERROR_NOT_IMPLEMENTED;
}
/*
* Return in 'threadsPtr' an array of the threads within the specified
* thread group.
* Note: array returned via 'threadsPtr' is allocated globally and must be
* explictly freed with DeleteGlobalRef.
* Errors: JVMDI_ERROR_INVALID_THREAD_GROUP, JVMDI_ERROR_NULL_POINTER,
* JVMDI_ERROR_OUT_OF_MEMORY
*/
JNIEXPORT JNICALL(jvmdiError)
JVMDI_GetGroupsThreads(JNIEnv * /*env*/, jthreadGroup /*group*/,
jobjectArray * /*threadsPtr*/)
{
return JVMDI_ERROR_NOT_IMPLEMENTED;
}
/*
* Return in 'groupsPtr' an array of the thread groups within the
* specified thread group.
* Note: array returned via 'groupsPtr' is allocated globally and must be
* explictly freed with DeleteGlobalRef.
* Errors: JVMDI_ERROR_INVALID_THREAD_GROUP, JVMDI_ERROR_NULL_POINTER,
* JVMDI_ERROR_OUT_OF_MEMORY
*/
JNIEXPORT JNICALL(jvmdiError)
JVMDI_GetGroupsThreadGroups(JNIEnv * /*env*/, jthreadGroup /*group*/,
jobjectArray * /*groupsPtr*/)
{
return JVMDI_ERROR_NOT_IMPLEMENTED;
}
/*
* Suspend all threads recursively contained in the thread group,
* except the specified threads.
* If except is NULL suspend all threads in group.
* Errors: JVMDI_ERROR_INVALID_THREAD_GROUP, JVMDI_ERROR_INVALID_THREAD
*/
JNIEXPORT JNICALL(jvmdiError)
JVMDI_SuspendThreadGroup(JNIEnv * /*env*/, jthreadGroup /*group*/,
jobjectArray /*except*/)
{
return JVMDI_ERROR_NOT_IMPLEMENTED;
}
/*
* Resume all threads (recursively) in the thread group, except the
* specified threads. If except is NULL resume all threads in group.
* Errors: JVMDI_ERROR_INVALID_THREAD_GROUP, JVMDI_ERROR_INVALID_THREAD
*/
JNIEXPORT JNICALL(jvmdiError)
JVMDI_ResumeThreadGroup(JNIEnv * /*env*/, jthreadGroup /*group*/, jobjectArray /*except*/)
{
return JVMDI_ERROR_NOT_IMPLEMENTED;
}
/*
* Stack access
*/
/*
* Return via "framePtr" the frame ID for the current stack frame
* of this thread. Thread must be suspended. Only Java and
* Java native frames are returned. FrameIDs become invalid if
* the frame is resumed.
* Errors: JVMDI_ERROR_NO_MORE_FRAMES, JVMDI_ERROR_INVALID_THREAD,
* JVMDI_ERROR_THREAD_NOT_SUSPENDED, JVMDI_ERROR_NULL_POINTER
*/
JNIEXPORT JNICALL(jvmdiError)
JVMDI_GetCurrentFrame(JNIEnv * /*env*/, jthread /*thread*/, jframeID* framePtr)
{
if (framePtr == NULL) {
return JVMDI_ERROR_NULL_POINTER;
}
return JVMDI_ERROR_NONE;
}
/*
* Return via "framePtr" the frame ID for the stack frame that called
* the specified frame. Only Java and Java native frames are returned.
* Errors: JVMDI_ERROR_NO_MORE_FRAMES, JVMDI_ERROR_INVALID_FRAMEID,
* JVMDI_ERROR_NULL_POINTER
*/
JNIEXPORT JNICALL(jvmdiError)
JVMDI_GetCallerFrame(JNIEnv * /* env */, jframeID /* called*/, jframeID * /*framePtr*/)
{
// Use code from the stackwalker here
return JVMDI_ERROR_NOT_IMPLEMENTED;
}
/*
* Return via "classPtr" and "methodPtr" the active method in the
* specified frame.
* Note: class returned via 'classPtr' is allocated globally and must be
* explictly freed with DeleteGlobalRef.
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_NULL_POINTER
* JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_OUT_OF_MEMORY
*/
JNIEXPORT JNICALL(jvmdiError)
JVMDI_GetFrameMethod(JNIEnv * /*env*/, jframeID /*frame*/,
jclass * /*classPtr*/, jmethodID * /*methodPtr*/)
{
// Use code from the stackwalker here
return JVMDI_ERROR_NOT_IMPLEMENTED;
}
/*
* Return via "bciPtr" the byte-code index within the active method of
* the specified frame. This is the index of the currently executing
* instruction.
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_NATIVE_FRAME,
* JVMDI_ERROR_NULL_POINTER
*/
JNIEXPORT JNICALL(jvmdiError)
JVMDI_GetFrameBCI(JNIEnv * /*env*/, jframeID /*frame*/, jint * /*bciPtr*/)
{
return JVMDI_ERROR_NOT_IMPLEMENTED;
}
/*
* Local variables
*/
/*
* Return via "valuePtr" the value of the local variable at the
* specificied slot.
* Note: object returned via 'valuePtr' is allocated globally and must be
* explictly freed with DeleteGlobalRef.
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_INVALID_SLOT,
* JVMDI_ERROR_TYPE_MISMATCH, JVMDI_ERROR_NULL_POINTER,
* JVMDI_ERROR_NATIVE_FRAME, JVMDI_ERROR_OUT_OF_MEMORY
*/
JNIEXPORT JNICALL(jvmdiError)
JVMDI_GetLocalObject(JNIEnv * /*env*/, jframeID /*frame*/, jint /*slot*/,
jobject * /*valuePtr*/)
{
return JVMDI_ERROR_NOT_IMPLEMENTED;
}
/*
* Return via "valuePtr" the value of the local variable at the
* specificied slot.
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_INVALID_SLOT,
* JVMDI_ERROR_TYPE_MISMATCH, JVMDI_ERROR_NULL_POINTER,
* JVMDI_ERROR_NATIVE_FRAME
*/
JNIEXPORT JNICALL(jvmdiError)
JVMDI_GetLocalInt(JNIEnv * /*env*/, jframeID /*frame*/, jint /*slot*/,
jint * /*valuePtr*/)
{
return JVMDI_ERROR_NOT_IMPLEMENTED;
}
/*
* Return via "valuePtr" the value of the local variable at the
* specificied slot.
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_INVALID_SLOT,
* JVMDI_ERROR_TYPE_MISMATCH, JVMDI_ERROR_NULL_POINTER,
* JVMDI_ERROR_NATIVE_FRAME
*/
JNIEXPORT JNICALL(jvmdiError)
JVMDI_GetLocalLong(JNIEnv * /*env*/, jframeID /*frame*/, jint /*slot*/,
jlong * /*valuePtr*/)
{
return JVMDI_ERROR_NOT_IMPLEMENTED;
}
/*
* Return via "valuePtr" the value of the local variable at the
* specificied slot.
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_INVALID_SLOT,
* JVMDI_ERROR_TYPE_MISMATCH, JVMDI_ERROR_NULL_POINTER,
* JVMDI_ERROR_NATIVE_FRAME
*/
JNIEXPORT JNICALL(jvmdiError)
JVMDI_GetLocalFloat(JNIEnv * /*env*/, jframeID /*frame*/, jint /*slot*/,
jfloat * /*valuePtr*/)
{
return JVMDI_ERROR_NOT_IMPLEMENTED;
}
/*
* Return via "valuePtr" the value of the local variable at the
* specificied slot.
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_INVALID_SLOT,
* JVMDI_ERROR_TYPE_MISMATCH, JVMDI_ERROR_NULL_POINTER,
* JVMDI_ERROR_NATIVE_FRAME
*/
JNIEXPORT JNICALL(jvmdiError)
JVMDI_GetLocalDouble(JNIEnv * /*env*/, jframeID /*frame*/, jint /*slot*/,
jdouble * /*valuePtr*/)
{
return JVMDI_ERROR_NOT_IMPLEMENTED;
}
/*
* Set the value of the local variable at the specificied slot.
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_INVALID_SLOT,
* JVMDI_ERROR_TYPE_MISMATCH, JVMDI_ERROR_NATIVE_FRAME
*/
JNIEXPORT JNICALL(jvmdiError)
JVMDI_SetLocalObject(JNIEnv * /*env*/, jframeID /*frame*/, jint /*slot*/, jobject /*value*/)
{
return JVMDI_ERROR_NOT_IMPLEMENTED;
}
/*
* Set the value of the local variable at the specificied slot.
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_INVALID_SLOT,
* JVMDI_ERROR_TYPE_MISMATCH, JVMDI_ERROR_NATIVE_FRAME
*/
JNIEXPORT JNICALL(jvmdiError)
JVMDI_SetLocalInt(JNIEnv * /*env*/, jframeID /*frame*/, jint /*slot*/, jint /*value*/)
{
return JVMDI_ERROR_NOT_IMPLEMENTED;
}
/*
* Set the value of the local variable at the specificied slot.
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_INVALID_SLOT,
* JVMDI_ERROR_TYPE_MISMATCH, JVMDI_ERROR_NATIVE_FRAME
*/
JNIEXPORT JNICALL(jvmdiError)
JVMDI_SetLocalLong(JNIEnv * /*env*/, jframeID /*frame*/, jint /*slot*/, jlong /*value*/)
{
return JVMDI_ERROR_NOT_IMPLEMENTED;
}
/*
* Set the value of the local variable at the specificied slot.
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_INVALID_SLOT,
* JVMDI_ERROR_TYPE_MISMATCH, JVMDI_ERROR_NATIVE_FRAME
*/
JNIEXPORT JNICALL(jvmdiError)
JVMDI_SetLocalFloat(JNIEnv * /*env*/, jframeID /*frame*/, jint /*slot*/, jfloat /*value*/)
{
return JVMDI_ERROR_NOT_IMPLEMENTED;
}
/*
* Set the value of the local variable at the specificied slot.
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_INVALID_SLOT,
* JVMDI_ERROR_TYPE_MISMATCH, JVMDI_ERROR_NATIVE_FRAME
*/
JNIEXPORT JNICALL(jvmdiError)
JVMDI_SetLocalDouble(JNIEnv * /*env*/, jframeID /*frame*/, jint /*slot*/, jdouble /*value*/)
{
return JVMDI_ERROR_NOT_IMPLEMENTED;
}
/*
* Breakpoints
*/
/*
* Set a breakpoint. Send a JVMDI_EVENT_BREAKPOINT event when the
* instruction at the specified byte-code index in the specified
* method is about to be executed.
* Errors: JVMDI_ERROR_INVALID_METHODID, JVMDI_ERROR_INVALID_CLASS,
* JVMDI_ERROR_INVALID_BCI, JVMDI_ERROR_DUPLICATE_BREAKPOINT,
* JVMDI_ERROR_VM_DEAD, JVMDI_ERROR_OUT_OF_MEMORY
*/
JNIEXPORT JNICALL(jvmdiError)
JVMDI_SetBreakpoint(JNIEnv * /*env*/, jclass /* clazz */,
jmethodID method, jint /*bci*/)
{
CacheEntry* ce;
ce = NativeCodeCache::getCache().lookupByRange((Uint8*) method);
if (ce == NULL) {
/* either the method is not compiled - in which case compile it */
return JVMDI_ERROR_INVALID_METHODID;
}
void *code = addressFunction(ce->descriptor.method->getCode());
if (code == NULL) {
return JVMDI_ERROR_INVALID_METHODID;
} // else if (code == stub) compile and then break;
// Convert the bci to a pc offset and add it to code
VM::debugger.setBreakPoint(code);
return JVMDI_ERROR_NONE;
}
/*
* Clear a breakpoint.
* Errors: JVMDI_ERROR_INVALID_METHODID, JVMDI_ERROR_INVALID_CLASS,
* JVMDI_ERROR_INVALID_BCI, JVMDI_ERROR_NO_SUCH_BREAKPOINT,
* JVMDI_ERROR_VM_DEAD
*/
JNIEXPORT JNICALL(jvmdiError)
JVMDI_ClearBreakpoint(JNIEnv * /*env*/, jclass /*clazz*/, jmethodID /*method*/, jint /*bci*/)
{
return JVMDI_ERROR_NOT_IMPLEMENTED;
}
/*
* Clear all breakpoints.
* Errors: JVMDI_ERROR_VM_DEAD
*/
JNIEXPORT JNICALL(jvmdiError)
JVMDI_ClearAllBreakpoints(JNIEnv * /*env*/)
{
VM::debugger.clearAllBreakPoints();
return JVMDI_ERROR_NONE;
}
/*
* Set the routine which will handle in-coming events.
* Passing NULL as hook unsets hook.
*/
JNIEXPORT JNICALL(jvmdiError)
JVMDI_SetEventHook(JNIEnv * /*env*/, JVMDI_EventHook hook)
{
eventHook = hook;
return JVMDI_ERROR_NONE;
}
/*
* Method access
*/
/*
* Return via "namePtr" the method's name and via "signaturePtr" the
* method's signature.
* Note: strings returned via 'namePtr' and 'signaturePtr' are
* allocated globally and must be explictly freed with DeleteGlobalRef.
* Errors: JVMDI_ERROR_INVALID_METHODID, JVMDI_ERROR_INVALID_CLASS,
* JVMDI_ERROR_NULL_POINTER, JVMDI_ERROR_OUT_OF_MEMORY
*/
JNIEXPORT JNICALL(jvmdiError)
JVMDI_GetMethodName(JNIEnv * env, jclass /*clazz*/, jmethodID method,
jstring *namePtr, jstring *signaturePtr)
{
CacheEntry* ce;
ce = NativeCodeCache::getCache().lookupByRange((Uint8*) method);
if (namePtr == NULL || signaturePtr == NULL) {
return JVMDI_ERROR_NULL_POINTER;
}
if (ce == NULL) {
return JVMDI_ERROR_INVALID_METHODID;
}
*namePtr = (jstring) env->NewGlobalRef(
env->NewStringUTF(ce->descriptor.method->toString()));
*signaturePtr = (jstring) env->NewGlobalRef(
env->NewStringUTF(ce->descriptor.method->getSignatureString()));
return JVMDI_ERROR_NONE;
}
/*
* Return via "definingClassPtr" the class in which this method is
* defined.
* Note: class returned via 'definingClassPtr' is allocated globally
* and must be explictly freed with DeleteGlobalRef.
* Errors: JVMDI_ERROR_INVALID_METHODID, JVMDI_ERROR_INVALID_CLASS,
* JVMDI_ERROR_NULL_POINTER, JVMDI_ERROR_OUT_OF_MEMORY
*/
JNIEXPORT JNICALL(jvmdiError)
JVMDI_GetMethodDefiningClass(JNIEnv * env, jclass /* clazz */, jmethodID method,
jclass * definingClassPtr)
{
CacheEntry* ce;
ce = NativeCodeCache::getCache().lookupByRange((Uint8*) method);
if (definingClassPtr == NULL) {
return JVMDI_ERROR_NULL_POINTER;
}
*definingClassPtr = (jclass) (env->NewGlobalRef((jobject)
ce->descriptor.method->getDeclaringClass()));
return JVMDI_ERROR_NONE;
}
/*
* Return via "isNativePtr" a boolean indicating whether the method
* is native.
* Errors: JVMDI_ERROR_INVALID_METHODID, JVMDI_ERROR_INVALID_CLASS,
* JVMDI_ERROR_NULL_POINTER
*/
JNIEXPORT JNICALL(jvmdiError)
JVMDI_IsMethodNative(JNIEnv * /* env */, jclass /* clazz */, jmethodID method,
jboolean * isNativePtr)
{
if (isNativePtr == NULL) {
return JVMDI_ERROR_NULL_POINTER;
}
CacheEntry* ce;
ce = NativeCodeCache::getCache().lookupByRange((Uint8*) method);
if (ce == NULL) {
/* either the method is not compiled - in which case compile it */
return JVMDI_ERROR_INVALID_METHODID;
}
*isNativePtr = ce->descriptor.method->getMethodInfo().isNative();
return JVMDI_ERROR_NONE;
}
/*
* Misc
*/
/*
* Return via "classesPtr" all classes currently loaded in the VM.
* Note: array returned via 'classesPtr' is allocated globally
* and must be explictly freed with DeleteGlobalRef.
* Errors: JVMDI_ERROR_NULL_POINTER, JVMDI_ERROR_OUT_OF_MEMORY
*/
JNIEXPORT JNICALL(jvmdiError)
JVMDI_GetLoadedClasses(JNIEnv * /*env*/, jobjectArray * /*classesPtr*/)
{
return JVMDI_ERROR_NOT_IMPLEMENTED;
}
/*
* Return via "versionPtr" the JVMDI version number.
* Higher 16 bits is major version number, lower 16 bit is minor
* version number.
* Errors: JVMDI_ERROR_NULL_POINTER
*/
JNIEXPORT JNICALL(jvmdiError)
JVMDI_GetVersionNumber(JNIEnv * /*env*/, jint *versionPtr)
{
if (versionPtr == NULL) {
return JVMDI_ERROR_NULL_POINTER;
}
*versionPtr = 0x00000003;
return JVMDI_ERROR_NONE;
}
} // extern C

Просмотреть файл

@ -1,56 +0,0 @@
#!perl
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
use Cwd;
# Add our lib path to the Perl search path.
use lib "../PerlLib/";
use BuildMod;
use TestsMod;
use ReportMod;
while (1) {
# Build the Debug build.
#@args = ("efDbg.txt");
#$runTests = BuildMod::build(@args);
TestsMod::runSuite("testsuite.txt");
# Run the conformance tests only if the build was sucessful.
if ($runTests) {
print "Tests not being run right now.\n";
# Temp way to run the tests.
$save_dir = cwd;
chdir("D:/continuousbuilds/tests");
print ("running tests.\n");
system("tcl D:/continuousbuilds/scripts/runTestSuite.tcl");
chdir($save_dir);
}
# Build the Optimize build.
#@args = ("efOpt.txt");
#BuildMod::build(@args);
}

Просмотреть файл

@ -1,260 +0,0 @@
#!perl
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
package BuildMod;
use Exporter;
use Cwd;
@ISA = qw(Exporter);
@EXPORT = qw(checkArgs);
#
# build
#
# Builds all modules specified in the build file.
#
sub build {
local @args = @_;
# Global variables.
$buildFile = "";
$buildTitle = "";
$buildTarget = ""; # Dbg or Opt.
$buildPlatform = ""; # WIN32, UNIX, WIN16...
$buildName = ""; # $buildPlatform + $buildTarget
$buildLog = ""; # $buildPlatform + $buildTarget + "Log.txt";
$buildStatus = 0; # Build flag.
$buildStatusStr = "success";
$startTime = "";
&parseArgs(@args);
# Open the build file.
open BUILDFILE, $buildFile || die ("Cannot open build file.\n");
# Read in the build headers.
$buildTitle = <BUILDFILE>;
$buildPlatform = <BUILDFILE>;
$buildTarget = <BUILDFILE>;
# Remove \n, if any,
$buildTitle =~ s/\n$//;
$buildPlatform =~ s/\n$//;
$buildTarget =~ s/\n$//;
# Init variables.
$buildName = "${buildPlatform} ${buildTarget}";
$buildLog = "${buildPlatform}_${buildTarget}Log.txt";
$startTime = time - 60 * 10;
# Inform Tinderbox that we are starting a build.
&beginTinderbox;
# Open the build log.
open(LOG, ">${buildLog}") || die "Cannot open build log.\n";
# Read from the build file and do build.
while ($strBuf = <BUILDFILE>) {
#Remove any \n.
$strBuf =~ s/\n//;
# Check if the command is to change to a directory.
$loweredBuf = lc $strBuf;
if ($loweredBuf =~ /^cd /) {
$dir = $strBuf;
$dir =~ s/^cd\s+//;
print "Changing to $dir\n";
if (!chdir("$dir")) {
print LOG "Cannot change to directory $dir\n";
$buildStatus = 1;
}
} else {
print "$strBuf 2>&1 |\n";
print LOG "$strBuf 2>&1 |\n";
open(COMMAND,"$strBuf 2>&1 |");
# Tee the output
while( <COMMAND> ){
print $_;
print LOG $_;
}
close(COMMAND);
$buildStatus |= $?;
}
}
# Check if the build is busted or sucessful.
$buildStatusStr = ($buildStatus ? 'busted' : 'success');
print("Build Status: $buildStatusStr\n");
# Finish the log file and send it to tinderbox.
&endTinderbox(LOG);
# Rename the log file.
rename("${buildLog}", "${buildPlatform}${buildTarget}.last");
# Return 1 if build was sucessful, else return 0;
if ($buildStatusStr == 'success') {
return 1;
} else {
return 0;
}
}
#
# checkArgs
#
# Checks to see if there are command line arguments.
# Returns true(1) or false(0).
#
sub checkArgs {
local @args = @_;
# print("Number of args: $#args\n");
if ($#args == -1) {
return 0;
}
return 1;
}
#
# parseArgs
#
# Go through the argument list and set the matching global
# variables.
#
sub parseArgs {
local @args = @_;
# The first argument should the build file.
$buildFile = $args[0];
# Check if the file exits.
if (!(-e $buildFile)) {
die "Build file does not exist in the current directory.\n";
}
# Go through the rest of the arguments.
print("Args: ");
$i = 0;
while( $i < @args ){
print("$args[$i]", "\n");
$i++;
# Ignore the rest of the arguments.
}
print("\n");
return;
}
#
# beginTinderbox
#
# Sends mail to the Tinderbox daemon,
# that a build is about to start.
#
sub beginTinderbox {
print "Telling Tinderbox that we are starting a build.\n";
open( LOG, ">>logfile" );
print LOG "\n";
print LOG "tinderbox: tree: $buildTitle\n";
print LOG "tinderbox: builddate: $startTime\n";
print LOG "tinderbox: status: building\n";
print LOG "tinderbox: build: $buildName\n";
if ($buildPlatform =~ /WIN32/) {
print LOG "tinderbox: errorparser: windows\n";
print LOG "tinderbox: buildfamily: windows\n";
} else {
# ***** Need to add other platform specific info. *****
print LOG "tinderbox: errorparser: unknown\n";
print LOG "tinderbox: buildfamily: unknown\n";
}
print LOG "\n";
close( LOG );
# Send the logfile to Tinderbox.
if ($buildPlatform =~ /WIN32/) {
print "Sending logfile.\n";
system("$nstools\\bin\\blat logfile -t tinderbox-daemon\@warp" );
} else {
# ***** Need to add other platform specific mailing methods. *****
die "Don't know how to send on $buildPlatform\n";
}
return;
}
#
# endTinderbox
#
# Sends mail to the Tinderbox daemon,
# that a build is done.
#
sub endTinderbox {
my($LOG) = @_;
print "Telling Tinderbox that the build is done.\n";
print LOG "tinderbox: tree: $buildTitle\n";
print LOG "tinderbox: builddate: $startTime\n";
print LOG "tinderbox: status: $buildStatusStr\n";
print LOG "tinderbox: build: $buildName\n";
print LOG "tinderbox: errorparser: windows\n";
print LOG "tinderbox: buildfamily: windows\n";
close LOG;
# Inform Tinderbox that the build is done.
system("$nstools\\bin\\blat $buildLog -t tinderbox-daemon\@warp" );
return;
}

Просмотреть файл

@ -1,277 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/* Test program for ClassFileSummary */
#include "prinit.h"
#include "ClassFileSummary.h"
#include "ClassCentral.h"
#include "ErrorHandling.h"
char *fileName = 0;
char *className = 0;
char *classPath = 0;
void printUsage()
{
printf("Usage: classinfo [-f filename] [-cpath classpath] classname\n");
exit(0);
}
void parseOptions(int argc, char **argv)
{
int i;
for (i = 1; i < argc; i++)
if (!strcmp(argv[i], "-f"))
fileName = argv[++i];
else if (!strcmp(argv[i], "-cpath"))
classPath = argv[++i];
else if (!strcmp(argv[i], "-help"))
printUsage();
else if (className) {/* must be a classname */
printf("Syntax error or duplicate filename\n");
printUsage();
} else
className = argv[i];
if (!className) {
printf("Insufficient arguments\n");
printUsage();
}
}
Pool dynamicPool;
ClassWorld world(dynamicPool);
int main(int argc, char **argv)
{
int i;
#ifndef NO_NSPR
PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 1);
#endif
parseOptions(argc, argv);
// Pool dynamicPool;
StringPool sp(dynamicPool);
// ClassWorld world(dynamicPool);
ClassCentral central(dynamicPool, world, sp, classPath);
printf("Initializing distinguished objects....\n");
try {
initDistinguishedObjects(central);
} catch (VerifyError err) {
printf("Error initializing distinguished objects: %d\n", err.cause);
exit(1);
}
printf("Initialized distinguished objects!\n");
ClassFileSummary *info;
const ConstantPool *constantPool;
int constantPoolCount;
printf("Initialized class central\n");
try {
if (fileName) {
printf("Loading from file %s\n", fileName);
info = &central.addClass((const char *) className,
(const char *) fileName);
} else
info = &central.addClass((const char *) className);
} catch (VerifyError err) {
printf("Cannot load class %s: error %d\n", className, err.cause);
exit(1);
}
constantPool = info->getConstantPool();
constantPoolCount = info->getConstantPoolCount();
printf("Total size of object : %d\n", info->getObjSize());
/* Resolve fields, methods, constants, interfaceMethods */
for (i = 0; i < constantPoolCount; i++)
if (constantPool->get(i)) {
uint8 type = constantPool->get(i)->getType();
if (type == CR_CONSTANT_FIELDREF) {
ConstantFieldRef *ref = (ConstantFieldRef *) constantPool->get(i);
ConstantNameAndType *nameAndType = (ConstantNameAndType *) ref->getTypeInfo();
ConstantClass *cclass = ref->getClassInfo();
printf("--> Resolving field %s::%s...\n",
cclass->getUtf()->getUtfString(),
nameAndType->getName()->getUtfString());
uint32 offset;
bool isVolatile, isConstant;
bool isStatic = false;
TypeKind tk;
ValueKind vk;
try {
tk = info->lookupInstanceField(i, vk,
offset, isVolatile, isConstant);
} catch (VerifyError err) {
printf("\tlookupInstanceField() failed with error %d.\n",
err.cause);
printf("\tOk, so it's not an instance field. Trying static.\n");
addr a;
try {
tk = info->lookupStaticField(i, vk, a, isVolatile, isConstant);
isStatic = true;
} catch (VerifyError err) {
printf("Cannot resolve field %s: %d\n",
nameAndType->getName()->getUtfString(), err.cause);
}
}
if (isStatic)
printf("Resolved as static field.\n");
else
printf("Resolved as instance field with offset %u\n", offset);
} else if (type == CR_CONSTANT_METHODREF) {
ConstantMethodRef *ref = (ConstantMethodRef *) constantPool->get(i);
ConstantNameAndType *nameAndType = (ConstantNameAndType *) ref->getTypeInfo();
ConstantClass *cclass = ref->getClassInfo();
const char *methodName = nameAndType->getName()->getUtfString();
printf("--> Resolving method %s::%s...\n",
cclass->getUtf()->getUtfString(),
methodName);
uint32 vIndex;
addr a;
Signature sig;
bool dynamicallyResolved = false;
if (!strcmp(methodName, "<init>") || !strcmp(methodName, "<clinit>")) {
try {
info->lookupSpecialMethod(i, sig, a);
printf("\tResolved special method %s.\n", methodName);
} catch (VerifyError err) {
printf("Could not resolve special method %s: error %d\n",
methodName, err.cause);
exit(1);
}
} else {
try {
dynamicallyResolved =
info->lookupVirtualMethod(i, sig, vIndex, a);
} catch (VerifyError err) {
printf("\tlookupVirtualMethod() failed with erorr %d\n",
err.cause);
printf("\tOk, so method is not virtual. trying static...\n");
try {
info->lookupStaticMethod(i, sig, a);
} catch (VerifyError err) {
printf("Cannot resolve method %s: %d\n",
nameAndType->getName()->getUtfString(), err.cause);
exit(1);
}
}
}
if (dynamicallyResolved)
printf("\tResolved method %s as virtual: vindex %u.\n",
nameAndType->getName()->getUtfString(), vIndex);
else {
printf("\tResolved method %s statically\n",
nameAndType->getName()->getUtfString());
}
} else if (type == CR_CONSTANT_INTERFACEMETHODREF) {
ConstantMethodRef *ref = (ConstantMethodRef *) constantPool->get(i);
ConstantNameAndType *nameAndType = (ConstantNameAndType *) ref->getTypeInfo();
ConstantClass *cclass = ref->getClassInfo();
const char *methodName = nameAndType->getName()->getUtfString();
printf("--> Resolving interface method %s::%s...\n",
cclass->getUtf()->getUtfString(),
methodName);
Signature sig;
uint32 interfaceIndex;
addr a;
uint32 nArgs;
if (!strcmp(methodName, "<init>") || !strcmp(methodName, "<clinit>")) {
try {
info->lookupSpecialMethod(i, sig, a);
printf("\tResolved special method %s.\n", methodName);
} catch (VerifyError err) {
printf("Could not resolve special method %s: error %d\n",
methodName, err.cause);
exit(1);
}
} else {
try {
bool staticallyResolved = info->lookupInterfaceMethod(i, sig,
interfaceIndex,
a,
nArgs);
printf("\tResolved interface method %s %s.\n",
nameAndType->getName()->getUtfString(),
(staticallyResolved) ? "statically" : "dynamically");
} catch (VerifyError err) {
printf("\tCould not resolve interface method %s: error %d\n",
nameAndType->getName()->getUtfString(), err.cause);
exit(1);
}
}
}
}
printf("Successfully loaded class file. \n");
printf("Getting class descriptor...\n");
Class *clazz = static_cast<Class *>(info->getThisClass());
printf("Obtained class descriptor.\n");
/* Now look up all the interfaces this class implements */
printf("Loading interfaces...\n");
const Interface **interfaces = info->getInterfaces();
printf("Done!\n");
return 0;
}
#ifdef DEBUG_LAURENT
#ifdef __GNUC__
// for gcc with -fhandle-exceptions
void terminate() {}
#endif
#endif

Просмотреть файл

@ -1,273 +0,0 @@
/* deflate.h -- internal compression state
* Copyright (C) 1995-1996 Jean-loup Gailly
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
#ifndef _DEFLATE_H
#define _DEFLATE_H
#include "zutil.h"
/* ===========================================================================
* Internal compression state.
*/
#define LENGTH_CODES 29
/* number of length codes, not counting the special END_BLOCK code */
#define LITERALS 256
/* number of literal bytes 0..255 */
#define L_CODES (LITERALS+1+LENGTH_CODES)
/* number of Literal or Length codes, including the END_BLOCK code */
#define D_CODES 30
/* number of distance codes */
#define BL_CODES 19
/* number of codes used to transfer the bit lengths */
#define HEAP_SIZE (2*L_CODES+1)
/* maximum heap size */
#define MAX_BITS 15
/* All codes must not exceed MAX_BITS bits */
#define INIT_STATE 42
#define BUSY_STATE 113
#define FINISH_STATE 666
/* Stream status */
/* Data structure describing a single value and its code string. */
typedef struct ct_data_s {
union {
ush freq; /* frequency count */
ush code; /* bit string */
} fc;
union {
ush dad; /* father node in Huffman tree */
ush len; /* length of bit string */
} dl;
} FAR ct_data;
#define Freq fc.freq
#define Code fc.code
#define Dad dl.dad
#define Len dl.len
typedef struct static_tree_desc_s static_tree_desc;
typedef struct tree_desc_s {
ct_data *dyn_tree; /* the dynamic tree */
int max_code; /* largest code with non zero frequency */
static_tree_desc *stat_desc; /* the corresponding static tree */
} FAR tree_desc;
typedef ush Pos;
typedef Pos FAR Posf;
typedef unsigned IPos;
/* A Pos is an index in the character window. We use short instead of int to
* save space in the various tables. IPos is used only for parameter passing.
*/
typedef struct internal_state {
z_streamp strm; /* pointer back to this zlib stream */
int status; /* as the name implies */
Bytef *pending_buf; /* output still pending */
Bytef *pending_out; /* next pending byte to output to the stream */
int pending; /* nb of bytes in the pending buffer */
int noheader; /* suppress zlib header and adler32 */
Byte data_type; /* UNKNOWN, BINARY or ASCII */
Byte method; /* STORED (for zip only) or DEFLATED */
int last_flush; /* value of flush param for previous deflate call */
/* used by deflate.c: */
uInt w_size; /* LZ77 window size (32K by default) */
uInt w_bits; /* log2(w_size) (8..16) */
uInt w_mask; /* w_size - 1 */
Bytef *window;
/* Sliding window. Input bytes are read into the second half of the window,
* and move to the first half later to keep a dictionary of at least wSize
* bytes. With this organization, matches are limited to a distance of
* wSize-MAX_MATCH bytes, but this ensures that IO is always
* performed with a length multiple of the block size. Also, it limits
* the window size to 64K, which is quite useful on MSDOS.
* To do: use the user input buffer as sliding window.
*/
ulg window_size;
/* Actual size of window: 2*wSize, except when the user input buffer
* is directly used as sliding window.
*/
Posf *prev;
/* Link to older string with same hash index. To limit the size of this
* array to 64K, this link is maintained only for the last 32K strings.
* An index in this array is thus a window index modulo 32K.
*/
Posf *head; /* Heads of the hash chains or NIL. */
uInt ins_h; /* hash index of string to be inserted */
uInt hash_size; /* number of elements in hash table */
uInt hash_bits; /* log2(hash_size) */
uInt hash_mask; /* hash_size-1 */
uInt hash_shift;
/* Number of bits by which ins_h must be shifted at each input
* step. It must be such that after MIN_MATCH steps, the oldest
* byte no longer takes part in the hash key, that is:
* hash_shift * MIN_MATCH >= hash_bits
*/
long block_start;
/* Window position at the beginning of the current output block. Gets
* negative when the window is moved backwards.
*/
uInt match_length; /* length of best match */
IPos prev_match; /* previous match */
int match_available; /* set if previous match exists */
uInt strstart; /* start of string to insert */
uInt match_start; /* start of matching string */
uInt lookahead; /* number of valid bytes ahead in window */
uInt prev_length;
/* Length of the best match at previous step. Matches not greater than this
* are discarded. This is used in the lazy match evaluation.
*/
uInt max_chain_length;
/* To speed up deflation, hash chains are never searched beyond this
* length. A higher limit improves compression ratio but degrades the
* speed.
*/
uInt max_lazy_match;
/* Attempt to find a better match only when the current match is strictly
* smaller than this value. This mechanism is used only for compression
* levels >= 4.
*/
# define max_insert_length max_lazy_match
/* Insert new strings in the hash table only if the match length is not
* greater than this length. This saves time but degrades compression.
* max_insert_length is used only for compression levels <= 3.
*/
int level; /* compression level (1..9) */
int strategy; /* favor or force Huffman coding*/
uInt good_match;
/* Use a faster search when the previous match is longer than this */
int nice_match; /* Stop searching when current match exceeds this */
/* used by trees.c: */
/* Didn't use ct_data typedef below to supress compiler warning */
struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
struct tree_desc_s l_desc; /* desc. for literal tree */
struct tree_desc_s d_desc; /* desc. for distance tree */
struct tree_desc_s bl_desc; /* desc. for bit length tree */
ush bl_count[MAX_BITS+1];
/* number of codes at each bit length for an optimal tree */
int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
int heap_len; /* number of elements in the heap */
int heap_max; /* element of largest frequency */
/* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
* The same heap array is used to build all trees.
*/
uch depth[2*L_CODES+1];
/* Depth of each subtree used as tie breaker for trees of equal frequency
*/
uchf *l_buf; /* buffer for literals or lengths */
uInt lit_bufsize;
/* Size of match buffer for literals/lengths. There are 4 reasons for
* limiting lit_bufsize to 64K:
* - frequencies can be kept in 16 bit counters
* - if compression is not successful for the first block, all input
* data is still in the window so we can still emit a stored block even
* when input comes from standard input. (This can also be done for
* all blocks if lit_bufsize is not greater than 32K.)
* - if compression is not successful for a file smaller than 64K, we can
* even emit a stored file instead of a stored block (saving 5 bytes).
* This is applicable only for zip (not gzip or zlib).
* - creating new Huffman trees less frequently may not provide fast
* adaptation to changes in the input data statistics. (Take for
* example a binary file with poorly compressible code followed by
* a highly compressible string table.) Smaller buffer sizes give
* fast adaptation but have of course the overhead of transmitting
* trees more frequently.
* - I can't count above 4
*/
uInt last_lit; /* running index in l_buf */
ushf *d_buf;
/* Buffer for distances. To simplify the code, d_buf and l_buf have
* the same number of elements. To use different lengths, an extra flag
* array would be necessary.
*/
ulg opt_len; /* bit length of current block with optimal trees */
ulg static_len; /* bit length of current block with static trees */
ulg compressed_len; /* total bit length of compressed file */
uInt matches; /* number of string matches in current block */
int last_eob_len; /* bit length of EOB code for last block */
#ifdef DEBUG_ZIP
ulg bits_sent; /* bit length of the compressed data */
#endif
ush bi_buf;
/* Output buffer. bits are inserted starting at the bottom (least
* significant bits).
*/
int bi_valid;
/* Number of valid bits in bi_buf. All bits above the last valid bit
* are always zero.
*/
} FAR deflate_state;
/* Output a byte on the stream.
* IN assertion: there is enough room in pending_buf.
*/
#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
/* Minimum amount of lookahead, except at the end of the input file.
* See deflate.c for comments about the MIN_MATCH+1.
*/
#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD)
/* In order to simplify the code, particularly on 16 bit machines, match
* distances are limited to MAX_DIST instead of WSIZE.
*/
/* in trees.c */
void _tr_init OF((deflate_state *s));
int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
ulg _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len,
int eof));
void _tr_align OF((deflate_state *s));
void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len,
int eof));
#endif

Просмотреть файл

@ -1,521 +0,0 @@
/* gzio.c -- IO on .gz files
* Copyright (C) 1995-1996 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include <stdio.h>
#include "zutil.h"
struct internal_state {int dummy;}; /* for buggy compilers */
#define Z_BUFSIZE 4096
#define ALLOC(size) malloc(size)
#define TRYFREE(p) {if (p) free(p);}
static int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
/* gzip flag byte */
#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
#define COMMENT 0x10 /* bit 4 set: file comment present */
#define RESERVED 0xE0 /* bits 5..7: reserved */
typedef struct gz_stream {
z_stream stream;
int z_err; /* error code for last stream operation */
int z_eof; /* set if end of input file */
FILE *file; /* .gz file */
Byte *inbuf; /* input buffer */
Byte *outbuf; /* output buffer */
uLong crc; /* crc32 of uncompressed data */
char *msg; /* error message */
char *path; /* path name for debugging only */
int transparent; /* 1 if input file is not a .gz file */
char mode; /* 'w' or 'r' */
} gz_stream;
local gzFile gz_open OF((const char *path, const char *mode, int fd));
local int get_byte OF((gz_stream *s));
local void check_header OF((gz_stream *s));
local int destroy OF((gz_stream *s));
local void putLong OF((FILE *file, uLong x));
local uLong getLong OF((gz_stream *s));
/* ===========================================================================
Opens a gzip (.gz) file for reading or writing. The mode parameter
is as in fopen ("rb" or "wb"). The file is given either by file descriptor
or path name (if fd == -1).
gz_open return NULL if the file could not be opened or if there was
insufficient memory to allocate the (de)compression state; errno
can be checked to distinguish the two cases (if errno is zero, the
zlib error is Z_MEM_ERROR).
*/
local gzFile gz_open (path, mode, fd)
const char *path;
const char *mode;
int fd;
{
int err;
int level = Z_DEFAULT_COMPRESSION; /* compression level */
char *p = (char*)mode;
gz_stream *s;
char fmode[80]; /* copy of mode, without the compression level */
char *m = fmode;
if (!path || !mode) return Z_NULL;
s = (gz_stream *)ALLOC(sizeof(gz_stream));
if (!s) return Z_NULL;
s->stream.zalloc = (alloc_func)0;
s->stream.zfree = (free_func)0;
s->stream.opaque = (voidpf)0;
s->stream.next_in = s->inbuf = Z_NULL;
s->stream.next_out = s->outbuf = Z_NULL;
s->stream.avail_in = s->stream.avail_out = 0;
s->file = NULL;
s->z_err = Z_OK;
s->z_eof = 0;
s->crc = crc32(0L, Z_NULL, 0);
s->msg = NULL;
s->transparent = 0;
s->path = (char*)ALLOC(strlen(path)+1);
if (s->path == NULL) {
return destroy(s), (gzFile)Z_NULL;
}
strcpy(s->path, path); /* do this early for debugging */
s->mode = '\0';
do {
if (*p == 'r') s->mode = 'r';
if (*p == 'w' || *p == 'a') s->mode = 'w';
if (*p >= '0' && *p <= '9') {
level = *p - '0';
} else {
*m++ = *p; /* copy the mode */
}
} while (*p++ && m != fmode + sizeof(fmode));
if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL;
if (s->mode == 'w') {
err = deflateInit2(&(s->stream), level,
Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, 0);
/* windowBits is passed < 0 to suppress zlib header */
s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
if (err != Z_OK || s->outbuf == Z_NULL) {
return destroy(s), (gzFile)Z_NULL;
}
} else {
err = inflateInit2(&(s->stream), -MAX_WBITS);
s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE);
if (err != Z_OK || s->inbuf == Z_NULL) {
return destroy(s), (gzFile)Z_NULL;
}
}
s->stream.avail_out = Z_BUFSIZE;
errno = 0;
s->file = fd < 0 ? FOPEN(path, fmode) : (FILE*)fdopen(fd, fmode);
if (s->file == NULL) {
return destroy(s), (gzFile)Z_NULL;
}
if (s->mode == 'w') {
/* Write a very simple .gz header:
*/
fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE);
} else {
check_header(s); /* skip the .gz header */
}
return (gzFile)s;
}
/* ===========================================================================
Opens a gzip (.gz) file for reading or writing.
*/
gzFile gzopen (path, mode)
const char *path;
const char *mode;
{
return gz_open (path, mode, -1);
}
/* ===========================================================================
Associate a gzFile with the file descriptor fd. fd is not dup'ed here
to mimic the behavio(u)r of fdopen.
*/
gzFile gzdopen (fd, mode)
int fd;
const char *mode;
{
char name[20];
if (fd < 0) return (gzFile)Z_NULL;
sprintf(name, "<fd:%d>", fd); /* for debugging */
return gz_open (name, mode, fd);
}
/* ===========================================================================
Read a byte from a gz_stream; update next_in and avail_in. Return EOF
for end of file.
IN assertion: the stream s has been sucessfully opened for reading.
*/
local int get_byte(s)
gz_stream *s;
{
if (s->z_eof) return EOF;
if (s->stream.avail_in == 0) {
errno = 0;
s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file);
if (s->stream.avail_in == 0) {
s->z_eof = 1;
if (ferror(s->file)) s->z_err = Z_ERRNO;
return EOF;
}
s->stream.next_in = s->inbuf;
}
s->stream.avail_in--;
return *(s->stream.next_in)++;
}
/* ===========================================================================
Check the gzip header of a gz_stream opened for reading. Set the stream
mode to transparent if the gzip magic header is not present; set s->err
to Z_DATA_ERROR if the magic header is present but the rest of the header
is incorrect.
IN assertion: the stream s has already been created sucessfully;
s->stream.avail_in is zero for the first time, but may be non-zero
for concatenated .gz files.
*/
local void check_header(s)
gz_stream *s;
{
int method; /* method byte */
int flags; /* flags byte */
uInt len;
int c;
/* Check the gzip magic header */
for (len = 0; len < 2; len++) {
c = get_byte(s);
if (c != gz_magic[len]) {
s->transparent = 1;
if (c != EOF) s->stream.avail_in++, s->stream.next_in--;
s->z_err = s->stream.avail_in != 0 ? Z_OK : Z_STREAM_END;
return;
}
}
method = get_byte(s);
flags = get_byte(s);
if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
s->z_err = Z_DATA_ERROR;
return;
}
/* Discard time, xflags and OS code: */
for (len = 0; len < 6; len++) (void)get_byte(s);
if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
len = (uInt)get_byte(s);
len += ((uInt)get_byte(s))<<8;
/* len is garbage if EOF but the loop below will quit anyway */
while (len-- != 0 && get_byte(s) != EOF) ;
}
if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
while ((c = get_byte(s)) != 0 && c != EOF) ;
}
if ((flags & COMMENT) != 0) { /* skip the .gz file comment */
while ((c = get_byte(s)) != 0 && c != EOF) ;
}
if ((flags & HEAD_CRC) != 0) { /* skip the header crc */
for (len = 0; len < 2; len++) (void)get_byte(s);
}
s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
}
/* ===========================================================================
* Cleanup then free the given gz_stream. Return a zlib error code.
Try freeing in the reverse order of allocations.
*/
local int destroy (s)
gz_stream *s;
{
int err = Z_OK;
if (!s) return Z_STREAM_ERROR;
TRYFREE(s->msg);
if (s->stream.state != NULL) {
if (s->mode == 'w') {
err = deflateEnd(&(s->stream));
} else if (s->mode == 'r') {
err = inflateEnd(&(s->stream));
}
}
if (s->file != NULL && fclose(s->file)) {
err = Z_ERRNO;
}
if (s->z_err < 0) err = s->z_err;
TRYFREE(s->inbuf);
TRYFREE(s->outbuf);
TRYFREE(s->path);
TRYFREE(s);
return err;
}
/* ===========================================================================
Reads the given number of uncompressed bytes from the compressed file.
gzread returns the number of bytes actually read (0 for end of file).
*/
int gzread (file, buf, len)
gzFile file;
voidp buf;
unsigned len;
{
gz_stream *s = (gz_stream*)file;
Bytef *start = buf; /* starting point for crc computation */
Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */
if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR;
if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1;
if (s->z_err == Z_STREAM_END) return 0; /* EOF */
s->stream.next_out = next_out = buf;
s->stream.avail_out = len;
while (s->stream.avail_out != 0) {
if (s->transparent) {
/* Copy first the lookahead bytes: */
uInt n = s->stream.avail_in;
if (n > s->stream.avail_out) n = s->stream.avail_out;
if (n > 0) {
zmemcpy(s->stream.next_out, s->stream.next_in, n);
next_out += n;
s->stream.next_out = next_out;
s->stream.next_in += n;
s->stream.avail_out -= n;
s->stream.avail_in -= n;
}
if (s->stream.avail_out > 0) {
s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out,
s->file);
}
return (int)(len - s->stream.avail_out);
}
if (s->stream.avail_in == 0 && !s->z_eof) {
errno = 0;
s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file);
if (s->stream.avail_in == 0) {
s->z_eof = 1;
if (ferror(s->file)) {
s->z_err = Z_ERRNO;
break;
}
}
s->stream.next_in = s->inbuf;
}
s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
if (s->z_err == Z_STREAM_END) {
/* Check CRC and original size */
s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
start = s->stream.next_out;
if (getLong(s) != s->crc || getLong(s) != s->stream.total_out) {
s->z_err = Z_DATA_ERROR;
} else {
/* Check for concatenated .gz files: */
check_header(s);
if (s->z_err == Z_OK) {
inflateReset(&(s->stream));
s->crc = crc32(0L, Z_NULL, 0);
}
}
}
if (s->z_err != Z_OK || s->z_eof) break;
}
s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
return (int)(len - s->stream.avail_out);
}
/* ===========================================================================
Writes the given number of uncompressed bytes into the compressed file.
gzwrite returns the number of bytes actually written (0 in case of error).
*/
int gzwrite (file, buf, len)
gzFile file;
const voidp buf;
unsigned len;
{
gz_stream *s = (gz_stream*)file;
if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
s->stream.next_in = buf;
s->stream.avail_in = len;
while (s->stream.avail_in != 0) {
if (s->stream.avail_out == 0) {
s->stream.next_out = s->outbuf;
if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
s->z_err = Z_ERRNO;
break;
}
s->stream.avail_out = Z_BUFSIZE;
}
s->z_err = deflate(&(s->stream), Z_NO_FLUSH);
if (s->z_err != Z_OK) break;
}
s->crc = crc32(s->crc, buf, len);
return (int)(len - s->stream.avail_in);
}
/* ===========================================================================
Flushes all pending output into the compressed file. The parameter
flush is as in the deflate() function.
gzflush should be called only when strictly necessary because it can
degrade compression.
*/
int gzflush (file, flush)
gzFile file;
int flush;
{
uInt len;
int done = 0;
gz_stream *s = (gz_stream*)file;
if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
s->stream.avail_in = 0; /* should be zero already anyway */
for (;;) {
len = Z_BUFSIZE - s->stream.avail_out;
if (len != 0) {
if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) {
s->z_err = Z_ERRNO;
return Z_ERRNO;
}
s->stream.next_out = s->outbuf;
s->stream.avail_out = Z_BUFSIZE;
}
if (done) break;
s->z_err = deflate(&(s->stream), flush);
/* deflate has finished flushing only when it hasn't used up
* all the available space in the output buffer:
*/
done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break;
}
fflush(s->file);
return s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
}
/* ===========================================================================
Outputs a long in LSB order to the given file
*/
local void putLong (file, x)
FILE *file;
uLong x;
{
int n;
for (n = 0; n < 4; n++) {
fputc((int)(x & 0xff), file);
x >>= 8;
}
}
/* ===========================================================================
Reads a long in LSB order from the given gz_stream. Sets
*/
local uLong getLong (s)
gz_stream *s;
{
uLong x = (uLong)get_byte(s);
int c;
x += ((uLong)get_byte(s))<<8;
x += ((uLong)get_byte(s))<<16;
c = get_byte(s);
if (c == EOF) s->z_err = Z_DATA_ERROR;
x += ((uLong)c)<<24;
return x;
}
/* ===========================================================================
Flushes all pending output if necessary, closes the compressed file
and deallocates all the (de)compression state.
*/
int gzclose (file)
gzFile file;
{
int err;
gz_stream *s = (gz_stream*)file;
if (s == NULL) return Z_STREAM_ERROR;
if (s->mode == 'w') {
err = gzflush (file, Z_FINISH);
if (err != Z_OK) return destroy(file);
putLong (s->file, s->crc);
putLong (s->file, s->stream.total_in);
}
return destroy(file);
}
/* ===========================================================================
Returns the error message for the last error which occured on the
given compressed file. errnum is set to zlib error number. If an
error occured in the file system and not in the compression library,
errnum is set to Z_ERRNO and the application may consult errno
to get the exact error code.
*/
const char* gzerror (file, errnum)
gzFile file;
int *errnum;
{
char *m;
gz_stream *s = (gz_stream*)file;
if (s == NULL) {
*errnum = Z_STREAM_ERROR;
return (const char*)ERR_MSG(Z_STREAM_ERROR);
}
*errnum = s->z_err;
if (*errnum == Z_OK) return (const char*)"";
m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg);
if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err);
TRYFREE(s->msg);
s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3);
strcpy(s->msg, s->path);
strcat(s->msg, ": ");
strcat(s->msg, m);
return (const char*)s->msg;
}

Просмотреть файл

@ -1,727 +0,0 @@
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#######################################################################
### ###
### R U L E S O F E N G A G E M E N T ###
### ###
#######################################################################
#######################################################################
# Double-Colon rules for utilizing the binary release model. #
#######################################################################
all:: export libs program install
autobuild:: export private_export libs program install
platform::
@echo $(OBJDIR_NAME)
#
# IMPORTS will always be associated with a component. Therefore,
# the "import" rule will always change directory to the top-level
# of a component, and traverse the IMPORTS keyword from the
# "manifest.mn" file located at this level only.
#
# note: if there is a trailing slash, the component will be appended
# (see import.pl - only used for xpheader.jar)
import::
@echo "== import.pl =="
@perl -I$(DEPTH)/config/core $(DEPTH)/config/core/import.pl \
"RELEASE_TREE=$(RELEASE_TREE)" \
"IMPORTS=$(IMPORTS)" \
"VERSION=$(VERSION)" \
"OS_ARCH=$(OS_ARCH)" \
"PLATFORM=$(PLATFORM)" \
"SOURCE_RELEASE_PREFIX=$(SOURCE_RELEASE_XP_DIR)" \
"SOURCE_MD_DIR=$(SOURCE_MD_DIR)" \
"SOURCE_XP_DIR=$(XPDIST)" \
"FILES=$(XPCLASS_JAR) $(XPHEADER_JAR) $(MDHEADER_JAR) $(MDBINARY_JAR)" \
"$(XPCLASS_JAR)=$(RELEASE_XP_DIR)|$(SOURCE_CLASSES_DIR)" \
"$(XPHEADER_JAR)=$(RELEASE_XP_DIR)|$(XPDIST)/public/" \
"$(MDHEADER_JAR)=$(RELEASE_MD_DIR)|$(SOURCE_MD_DIR)/include" \
"$(MDBINARY_JAR)=$(RELEASE_MD_DIR)|$(SOURCE_MD_DIR)"
# perl -I$(DEPTH)/config/core $(DEPTH)/config/core/import.pl \
# "IMPORTS=$(IMPORTS)" \
# "RELEASE_TREE=$(RELEASE_TREE)" \
# "VERSION=$(VERSION)" \
# "PLATFORM=$(PLATFORM)" \
# "SOURCE_MD_DIR=$(SOURCE_MD_DIR)" \
# "SOURCE_XP_DIR=$(XPDIST)" \
# "OS_ARCH=$(OS_ARCH)" ;
export::
ifndef NO_EXPORT_IN_SUBDIRS
+$(LOOP_OVER_DIRS)
endif
private_export::
+$(LOOP_OVER_DIRS)
release_export::
+$(LOOP_OVER_DIRS)
libs :: $(TARGETS)
ifndef NO_LIBS_IN_SUBDIRS
+$(LOOP_OVER_DIRS)
endif
program :: $(TARGETS)
ifndef NO_PROGRAM_IN_SUBDIRS
+$(LOOP_OVER_DIRS)
endif
install:: $(TARGETS)
ifdef LIBRARY
$(INSTALL) -m 444 $(LIBRARY) $(DIST)/lib
endif
ifdef SHARED_LIBRARY
$(INSTALL) -m 555 $(SHARED_LIBRARY) $(DIST)/bin
endif
ifdef IMPORT_LIBRARY
$(INSTALL) -m 555 $(IMPORT_LIBRARY) $(DIST)/lib
endif
ifdef PROGRAM
$(INSTALL) -m 555 $(PROGRAM) $(DIST)/bin
endif
ifdef PROGRAMS
$(INSTALL) -m 555 $(PROGRAMS) $(DIST)/bin
endif
ifndef NO_INSTALL_IN_SUBDIRS
+$(LOOP_OVER_DIRS)
endif
tests::
+$(LOOP_OVER_DIRS)
clean clobber::
rm -rf $(ALL_TRASH)
+$(LOOP_OVER_DIRS)
realclean clobber_all::
rm -rf $(wildcard *.OBJ) dist $(ALL_TRASH)
+$(LOOP_OVER_DIRS)
#ifdef ALL_PLATFORMS
#all_platforms:: $(NFSPWD)
# @d=`$(NFSPWD)`; \
# if test ! -d LOGS; then rm -rf LOGS; mkdir LOGS; fi; \
# for h in $(PLATFORM_HOSTS); do \
# echo "On $$h: $(MAKE) $(ALL_PLATFORMS) >& LOGS/$$h.log";\
# rsh $$h -n "(chdir $$d; \
# $(MAKE) $(ALL_PLATFORMS) >& LOGS/$$h.log; \
# echo DONE) &" 2>&1 > LOGS/$$h.pid & \
# sleep 1; \
# done
#
#$(NFSPWD):
# cd $(@D); $(MAKE) $(@F)
#endif
#######################################################################
# Double-Colon rules for populating the binary release model. #
#######################################################################
release_clean::
rm -rf $(XPDIST)/release
release:: release_clean release_export release_md release_jars release_cpdistdir
release_cpdistdir::
@echo "== cpdist.pl =="
@perl -I$(DEPTH)/config/core $(DEPTH)/config/core/cpdist.pl \
"RELEASE_TREE=$(RELEASE_TREE)" \
"MODULE=${MODULE}" \
"OS_ARCH=$(OS_ARCH)" \
"RELEASE=$(RELEASE)" \
"PLATFORM=$(PLATFORM)" \
"RELEASE_VERSION=$(RELEASE_VERSION)" \
"SOURCE_RELEASE_PREFIX=$(SOURCE_RELEASE_XP_DIR)" \
"RELEASE_XP_DIR=$(RELEASE_XP_DIR)" \
"RELEASE_MD_DIR=$(RELEASE_MD_DIR)" \
"FILES=$(XPCLASS_JAR) $(XPHEADER_JAR) $(MDHEADER_JAR) $(MDBINARY_JAR) XP_FILES MD_FILES" \
"$(XPCLASS_JAR)=$(SOURCE_RELEASE_CLASSES_DIR)|x"\
"$(XPHEADER_JAR)=$(SOURCE_RELEASE_XPHEADERS_DIR)|x" \
"$(MDHEADER_JAR)=$(SOURCE_RELEASE_MDHEADERS_DIR)|m" \
"$(MDBINARY_JAR)=$(SOURCE_RELEASE_MD_DIR)|m" \
"XP_FILES=$(XP_FILES)|xf" \
"MD_FILES=$(MD_FILES)|mf"
# Add $(SOURCE_RELEASE_XPSOURCE_JAR) to FILES line when ready
# $(SOURCE_RELEASE_xxx_JAR) is a name like yyy.jar
# $(SOURCE_RELEASE_xx_DIR) is a name like
release_jars::
@echo "== release.pl =="
@perl -I$(DEPTH)/config/core $(DEPTH)/config/core/release.pl \
"RELEASE_TREE=$(RELEASE_TREE)" \
"PLATFORM=$(PLATFORM)" \
"OS_ARCH=$(OS_ARCH)" \
"RELEASE_VERSION=$(RELEASE_VERSION)" \
"SOURCE_RELEASE_DIR=$(SOURCE_RELEASE_DIR)" \
"FILES=$(XPCLASS_JAR) $(XPHEADER_JAR) $(MDHEADER_JAR) $(MDBINARY_JAR)" \
"$(XPCLASS_JAR)=$(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_CLASSES_DIR)|b"\
"$(XPHEADER_JAR)=$(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_XPHEADERS_DIR)|a" \
"$(MDHEADER_JAR)=$(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_MDHEADERS_DIR)|a" \
"$(MDBINARY_JAR)=$(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_MD_DIR)|bi"
# "$(XPSOURCE_JAR)=$(SOURCE_RELEASE_PREFIX)|a"
release_md::
ifdef LIBRARY
$(INSTALL) -m 444 $(LIBRARY) $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)
endif
ifdef SHARED_LIBRARY
$(INSTALL) -m 555 $(SHARED_LIBRARY) $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)
endif
ifdef IMPORT_LIBRARY
$(INSTALL) -m 555 $(IMPORT_LIBRARY) $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)
endif
ifdef PROGRAM
$(INSTALL) -m 555 $(PROGRAM) $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_BIN_DIR)
endif
ifdef PROGRAMS
$(INSTALL) -m 555 $(PROGRAMS) $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_BIN_DIR)
endif
+$(LOOP_OVER_DIRS)
alltags:
rm -f TAGS
find . -name dist -prune -o \( -name '*.[hc]' -o -name '*.cp' -o -name '*.cpp' \) -print | xargs etags -a
find . -name dist -prune -o \( -name '*.[hc]' -o -name '*.cp' -o -name '*.cpp' \) -print | xargs ctags -a
$(PROGRAM): $(OBJS)
@$(MAKE_OBJDIR)
ifeq ($(OS_ARCH),WINNT)
$(CC) $(OBJS) -Fe$@ -link $(LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS)
else
$(CC) -o $@ $(CFLAGS) $(OBJS) $(LDFLAGS) $(OS_LIBS)
endif
$(INSTALL) -m 555 $(PROGRAM) $(DIST)/bin
$(LIBRARY): $(OBJS)
@$(MAKE_OBJDIR)
rm -f $@
$(AR) $(OBJS)
$(RANLIB) $@
$(INSTALL) -m 444 $(LIBRARY) $(DIST)/lib
ifeq ($(OS_TARGET), WIN16)
$(IMPORT_LIBRARY): $(SHARED_LIBRARY)
wlib +$(SHARED_LIBRARY)
$(INSTALL) -m 555 $(IMPORT_LIBRARY) $(DIST)lib
endif
$(SHARED_LIBRARY): $(OBJS)
@$(MAKE_OBJDIR)
rm -f $@
ifeq ($(OS_ARCH), AIX)
echo "#!" > $(OBJDIR)/lib$(LIBRARY_NAME)_syms
nm -B -C -g $(OBJS) \
| awk '/ [T,D] / {print $$3}' \
| sed -e 's/^\.//' \
| sort -u >> $(OBJDIR)/lib$(LIBRARY_NAME)_syms
$(LD) $(XCFLAGS) -o $@ $(OBJS) -bE:$(OBJDIR)/lib$(LIBRARY_NAME)_syms \
-bM:SRE -bnoentry $(OS_LIBS) $(EXTRA_LIBS)
else
ifeq ($(OS_ARCH), WINNT)
ifeq ($(OS_TARGET), WIN16)
echo system windows dll initinstance >w16link
echo option map >>w16link
echo option oneautodata >>w16link
echo option heapsize=32K >>w16link
echo debug watcom all >>w16link
echo name $@ >>w16link
echo file >>w16link
echo $(W16OBJS) >>w16link
echo $(W16LIBS) >>w16link
#echo extra: $(EXTRA_LIBS), os_libs: $(OS_LIBS), $(W16LIBS) >>w16link
echo libfile libentry >>w16link
$(LINK) @w16link.
rm w16link
else
$(LINK_DLL) -MAP $(DLLBASE) $(OS_LIBS) $(EXTRA_LIBS) $(OBJS) $(LDFLAGS)
endif
$(INSTALL) -m 555 $(LIBRARY) $(DIST)/lib
else
$(MKSHLIB) -o $@ $(OBJS) $(LD_LIBS) $(OS_LIBS) $(EXTRA_LIBS)
chmod +x $@
endif
endif
ifeq ($(OS_ARCH),WINNT)
$(INSTALL) -m 555 $(SHARED_LIBRARY) $(DIST)/bin
else
$(INSTALL) -m 555 $(SHARED_LIBRARY) $(DIST)/lib
endif
$(PURE_LIBRARY):
rm -f $@
ifneq ($(OS_ARCH), WINNT)
$(AR) $(OBJS)
endif
$(RANLIB) $@
ifeq ($(OS_ARCH), WINNT)
$(RES): $(RESNAME)
@$(MAKE_OBJDIR)
$(RC) -Fo$(RES) $(RESNAME)
@echo $(RES) finished
$(DLL): $(OBJS) $(EXTRA_LIBS)
@$(MAKE_OBJDIR)
rm -f $@
$(LINK_DLL) $(OBJS) $(OS_LIBS) $(EXTRA_LIBS)
endif
$(OBJDIR)/$(PROG_PREFIX)%$(PROG_SUFFIX): $(OBJDIR)/$(PROG_PREFIX)%$(OBJ_SUFFIX)
@$(MAKE_OBJDIR)
ifeq ($(OS_ARCH),WINNT)
$(CC) $(OBJDIR)/$(PROG_PREFIX)$*$(OBJ_SUFFIX) -Fe$@ -link $(LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS)
else
$(CC) -o $@ $(OBJDIR)/$(PROG_PREFIX)$*$(OBJ_SUFFIX) $(LDFLAGS)
endif
ifdef HAVE_PURIFY
$(OBJDIR)/$(PROG_PREFIX)%.pure: $(OBJDIR)/%$(OBJ_SUFFIX)
@$(MAKE_OBJDIR)
ifeq ($(OS_ARCH),WINNT)
$(PURIFY) $(CC) -Fo$@ -c $(CFLAGS) $(OBJDIR)/$(PROG_PREFIX)$*$(OBJ_SUFFIX) $(PURELDFLAGS)
else
$(PURIFY) $(CC) -o $@ $(CFLAGS) $(OBJDIR)/$(PROG_PREFIX)$*$(OBJ_SUFFIX) $(PURELDFLAGS)
endif
endif
WCCFLAGS1 := $(subst /,\\,$(CFLAGS))
WCCFLAGS2 := $(subst -I,-i=,$(WCCFLAGS1))
WCCFLAGS3 := $(subst -D,-d,$(WCCFLAGS2))
$(OBJDIR)/$(PROG_PREFIX)%$(OBJ_SUFFIX): %.c
@$(MAKE_OBJDIR)
ifeq ($(OS_ARCH), WINNT)
ifeq ($(OS_TARGET), WIN16)
# $(DEPTH)/config/core/w16opt $(WCCFLAGS3)
echo $(WCCFLAGS3) >w16wccf
$(CC) -zq -fo$(OBJDIR)\\$(PROG_PREFIX)$*$(OBJ_SUFFIX) @w16wccf $*.c
rm w16wccf
else
ifdef GENERATE_BROWSE_INFO
@mkdir $(BROWSE_INFO_DIR)
$(CC) -Fo$@ -c $(CFLAGS) $*.c -FR$(BROWSE_INFO_DIR)/$*.sbr
else
$(CC) -Fo$@ -c $(CFLAGS) $*.c
endif
endif
else
$(CC) -o $@ -c $(CFLAGS) $*.c
endif
$(OBJDIR)/$(PROG_PREFIX)%$(OBJ_SUFFIX): %.s
@$(MAKE_OBJDIR)
$(AS) -o $@ $(ASFLAGS) -c $*.s
$(OBJDIR)/$(PROG_PREFIX)%$(OBJ_SUFFIX): %.S
@$(MAKE_OBJDIR)
$(AS) -o $@ $(ASFLAGS) -c $*.S
$(OBJDIR)/$(PROG_PREFIX)%: %.cpp
@$(MAKE_OBJDIR)
ifeq ($(OS_ARCH), WINNT)
$(CCC) -o $@ -c $(CFLAGS) $<
endif
#
# Please keep the next two rules in sync.
#
$(OBJDIR)/$(PROG_PREFIX)%$(OBJ_SUFFIX): %.cc
@$(MAKE_OBJDIR)
$(CCC) -o $@ -c $(CFLAGS) $*.cc
$(OBJDIR)/$(PROG_PREFIX)%$(OBJ_SUFFIX): %.cpp
@$(MAKE_OBJDIR)
ifdef STRICT_CPLUSPLUS_SUFFIX
echo "#line 1 \"$*.cpp\"" | cat - $*.cpp > $(OBJDIR)/t_$*.cc
$(CCC) -o $@ -c $(CFLAGS) $(OBJDIR)/t_$*.cc
rm -f $(OBJDIR)/t_$*.cc
else
ifeq ($(OS_ARCH),WINNT)
ifdef GENERATE_BROWSE_INFO
@mkdir $(BROWSE_INFO_DIR)
$(CCC) -Fo$@ -c $(CFLAGS) $*.cpp -FR$(BROWSE_INFO_DIR)/$*.sbr
else
$(CCC) -Fo$@ -c $(CFLAGS) $*.cpp
endif
else
$(CCC) -o $@ -c $(CFLAGS) $*.cpp
endif
endif #STRICT_CPLUSPLUS_SUFFIX
%.i: %.cpp
$(CCC) -C -E $(CFLAGS) $< > $*.i
%.i: %.c
$(CC) -C -E $(CFLAGS) $< > $*.i
$(OBJDIR)/%: %.pl
rm -f $@; cp $*.pl $@; chmod +x $@
%: %.sh
rm -f $@; cp $*.sh $@; chmod +x $@
ifdef DIRS
$(DIRS)::
@if test -d $@; then \
set $(EXIT_ON_ERROR); \
echo "cd $@; $(MAKE)"; \
cd $@; $(MAKE); \
set +e; \
else \
echo "Skipping non-directory $@..."; \
fi; \
$(CLICK_STOPWATCH)
endif
################################################################################
# Bunch of things that extend the 'export' rule (in order):
################################################################################
$(JAVA_DESTPATH) $(JAVA_DESTPATH)/$(PACKAGE) $(JMCSRCDIR)::
@if test ! -d $@; then \
echo Creating $@; \
rm -rf $@; \
$(NSINSTALL) -D $@; \
fi
################################################################################
## IDL_GEN
ifneq ($(IDL_GEN),)
#export::
# $(IDL2JAVA) $(IDL_GEN)
#all:: export
#clobber::
# rm -f $(IDL_GEN:.idl=.class) # XXX wrong!
endif
################################################################################
### JSRCS -- for compiling java files
ifneq ($(JSRCS),)
export:: $(JAVA_DESTPATH) $(JAVA_DESTPATH)/$(PACKAGE)
@list=`perl $(DEPTH)/config/core/outofdate.pl $(PERLARG) \
-d $(JAVA_DESTPATH)/$(PACKAGE) $(JSRCS)`; \
if test "$$list"x != "x"; then \
echo $(JAVAC) $$list; \
$(JAVAC) $$list; \
fi
all:: export
clobber::
rm -f $(XPDIST)/classes/$(PACKAGE)/*.class
endif
#
# JDIRS -- like JSRCS, except you can give a list of directories and it will
# compile all the out-of-date java files in those directories.
#
# NOTE: recursing through these can speed things up, but they also cause
# some builds to run out of memory
#
ifdef JDIRS
export:: $(JAVA_DESTPATH) $(JAVA_DESTPATH)/$(PACKAGE)
@for d in $(JDIRS); do \
if test -d $$d; then \
set $(EXIT_ON_ERROR); \
files=`echo $$d/*.java`; \
list=`perl $(DEPTH)/config/core/outofdate.pl $(PERLARG) \
-d $(JAVA_DESTPATH)/$(PACKAGE) $$files`; \
if test "$${list}x" != "x"; thecoreconfn \
echo Building all java files in $$d; \
echo $(JAVAC) $$list; \
$(JAVAC) $$list; \
fi; \
set +e; \
else \
echo "Skipping non-directory $$d..."; \
fi; \
$(CLICK_STOPWATCH); \
done
endif
#
# JDK_GEN -- for generating "old style" native methods
#
# Generate JDK Headers and Stubs into the '_gen' and '_stubs' directory
#
ifneq ($(JDK_GEN),)
ifdef NSBUILDROOT
INCLUDES += -I$(JDK_GEN_DIR) -I$(XPDIST)
else
INCLUDES += -I$(JDK_GEN_DIR)
endif
JDK_PACKAGE_CLASSES := $(JDK_GEN)
JDK_PATH_CLASSES := $(subst .,/,$(JDK_PACKAGE_CLASSES))
JDK_HEADER_CLASSFILES := $(patsubst %,$(JAVA_DESTPATH)/%.class,$(JDK_PATH_CLASSES))
JDK_STUB_CLASSFILES := $(patsubst %,$(JAVA_DESTPATH)/%.class,$(JDK_PATH_CLASSES))
JDK_HEADER_CFILES := $(patsubst %,$(JDK_GEN_DIR)/%.h,$(JDK_GEN))
JDK_STUB_CFILES := $(patsubst %,$(JDK_STUB_DIR)/%.c,$(JDK_GEN))
$(JDK_HEADER_CFILES): $(JDK_HEADER_CLASSFILES)
$(JDK_STUB_CFILES): $(JDK_STUB_CLASSFILES)
export::
@echo Generating/Updating JDK headers
$(JAVAH) -d $(JDK_GEN_DIR) $(JDK_PACKAGE_CLASSES)
@echo Generating/Updating JDK stubs
$(JAVAH) -stubs -d $(JDK_STUB_DIR) $(JDK_PACKAGE_CLASSES)
endif
#
# JRI_GEN -- for generating JRI native methods
#
# Generate JRI Headers and Stubs into the 'jri' directory
#
ifneq ($(JRI_GEN),)
ifdef NSBUILDROOT
INCLUDES += -I$(JRI_GEN_DIR) -I$(XPDIST)
else
INCLUDES += -I$(JRI_GEN_DIR)
endif
JRI_PACKAGE_CLASSES := $(JRI_GEN)
JRI_PATH_CLASSES := $(subst .,/,$(JRI_PACKAGE_CLASSES))
JRI_HEADER_CLASSFILES := $(patsubst %,$(JAVA_DESTPATH)/%.class,$(JRI_PATH_CLASSES))
JRI_STUB_CLASSFILES := $(patsubst %,$(JAVA_DESTPATH)/%.class,$(JRI_PATH_CLASSES))
JRI_HEADER_CFILES := $(patsubst %,$(JRI_GEN_DIR)/%.h,$(JRI_GEN))
JRI_STUB_CFILES := $(patsubst %,$(JRI_GEN_DIR)/%.c,$(JRI_GEN))
$(JRI_HEADER_CFILES): $(JRI_HEADER_CLASSFILES)
$(JRI_STUB_CFILES): $(JRI_STUB_CLASSFILES)
export::
@echo Generating/Updating JRI headers
$(JAVAH) -jri -d $(JRI_GEN_DIR) $(JRI_PACKAGE_CLASSES)
@echo Generating/Updating JRI stubs
$(JAVAH) -jri -stubs -d $(JRI_GEN_DIR) $(JRI_PACKAGE_CLASSES)
endif
#
# JMC_EXPORT -- for declaring which java classes are to be exported for jmc
#
ifneq ($(JMC_EXPORT),)
JMC_EXPORT_PATHS := $(subst .,/,$(JMC_EXPORT))
JMC_EXPORT_FILES := $(patsubst %,$(JAVA_DESTPATH)/$(PACKAGE)/%.class,$(JMC_EXPORT_PATHS))
#
# We're doing NSINSTALL -t here (copy mode) because calling INSTALL will pick up
# your NSDISTMODE and make links relative to the current directory. This is a
# problem because the source isn't in the current directory:
#
export:: $(JMC_EXPORT_FILES) $(JMCSRCDIR)
$(NSINSTALL) -t -m 444 $(JMC_EXPORT_FILES) $(JMCSRCDIR)
endif
#
# JMC_GEN -- for generating java modules
#
# Provide default export & install rules when using JMC_GEN
#
ifneq ($(JMC_GEN),)
INCLUDES += -I$(JMC_GEN_DIR) -I.
JMC_HEADERS := $(patsubst %,$(JMC_GEN_DIR)/%.h,$(JMC_GEN))
JMC_STUBS := $(patsubst %,$(JMC_GEN_DIR)/%.c,$(JMC_GEN))
JMC_OBJS := $(patsubst %,$(OBJDIR)/%$(OBJ_SUFFIX),$(JMC_GEN))
$(JMC_GEN_DIR)/M%.h: $(JMCSRCDIR)/%.class
$(JMC) -d $(JMC_GEN_DIR) -interface $(JMC_GEN_FLAGS) $(?F:.class=)
$(JMC_GEN_DIR)/M%.c: $(JMCSRCDIR)/%.class
$(JMC) -d $(JMC_GEN_DIR) -module $(JMC_GEN_FLAGS) $(?F:.class=)
$(OBJDIR)/M%$(OBJ_SUFFIX): $(JMC_GEN_DIR)/M%.h $(JMC_GEN_DIR)/M%.c
@$(MAKE_OBJDIR)
$(CC) -o $@ -c $(CFLAGS) $(JMC_GEN_DIR)/M$*.c
export:: $(JMC_HEADERS) $(JMC_STUBS)
endif
#
# Copy each element of EXPORTS to $(XPDIST)/public/$(MODULE)/
#
ifneq ($(EXPORTS),)
$(XPDIST)/public/$(MODULE)::
@if test ! -d $@; then \
echo Creating $@; \
$(NSINSTALL) -D $@; \
fi
export:: $(EXPORTS) $(XPDIST)/public/$(MODULE)
$(INSTALL) -m 444 $(EXPORTS) $(XPDIST)/public/$(MODULE)
endif
# Duplicate export rule for private exports, with different directories
ifneq ($(PRIVATE_EXPORTS),)
$(XPDIST)/private/$(MODULE)::
@if test ! -d $@; then \
echo Creating $@; \
$(NSINSTALL) -D $@; \
fi
private_export:: $(PRIVATE_EXPORTS) $(XPDIST)/private/$(MODULE)
$(INSTALL) -m 444 $(PRIVATE_EXPORTS) $(XPDIST)/private/$(MODULE)
else
private_export::
endif
# Duplicate export rule for releases, with different directories
ifneq ($(EXPORTS),)
$(XPDIST)/release/include::
@if test ! -d $@; then \
echo Creating $@; \
$(NSINSTALL) -D $@; \
fi
release_export:: $(EXPORTS) $(XPDIST)/release/include
$(INSTALL) -m 444 $(EXPORTS) $(XPDIST)/release/include
endif
################################################################################
ifneq ($(DEPENDENCIES),)
-include $(DEPENDENCIES)
endif
ifneq ($(OS_ARCH),WINNT)
# Can't use sed because of its 4000-char line length limit, so resort to perl
.DEFAULT:
@perl -e ' \
open(MD, "< $(DEPENDENCIES)"); \
while (<MD>) { \
if (m@ \.*/*$< @) { \
$$found = 1; \
last; \
} \
} \
if ($$found) { \
print "Removing stale dependency $< from $(DEPENDENCIES)\n"; \
seek(MD, 0, 0); \
$$tmpname = "$(OBJDIR)/fix.md" . $$$$; \
open(TMD, "> " . $$tmpname); \
while (<MD>) { \
s@ \.*/*$< @ @; \
if (!print TMD "$$_") { \
unlink(($$tmpname)); \
exit(1); \
} \
} \
close(TMD); \
if (!rename($$tmpname, "$(DEPENDENCIES)")) { \
unlink(($$tmpname)); \
} \
} elsif ("$<" ne "$(DEPENDENCIES)") { \
print "$(MAKE): *** No rule to make target $<. Stop.\n"; \
exit(1); \
}'
endif
#############################################################################
# X dependency system
#############################################################################
$(MKDEPENDENCIES): $(CSRCS) $(CPPSRCS) $(ASFILES) Makefile \
$(EXPORTS) $(LOCAL_EXPORTS)
@$(MAKE_OBJDIR)
touch $(MKDEPENDENCIES)
$(MKDEPEND) -p$(OBJDIR_NAME)/ -o'$(OBJ_SUFFIX)' -f$(MKDEPENDENCIES) $(INCLUDES) $(SYS_INCLUDES) $(CSRCS) $(CPPSRCS) $(ASFILES)
$(MKDEPEND):
cd $(MKDEPEND_DIR); $(MAKE)
ifdef OBJS
depend:: $(MKDEPEND) $(MKDEPENDENCIES)
else
depend::
endif
+$(LOOP_OVER_DIRS)
dependclean::
rm -f $(MKDEPENDENCIES)
+$(LOOP_OVER_DIR)
# CUR_DIR is neccesary since it seems to crash gmake otherwise
CUR_DIR = $(shell pwd)
ifndef NO_IMPLICIT_DEPENDENCIES
ifdef OBJS
libs:: $(MKDEPENDENCIES)
endif
endif
ifneq ($(wildcard $(CUR_DIR)/$(OBJDIR)/depend.mk),)
-include $(CUR_DIR)/$(OBJDIR)/depend.mk
endif
################################################################################
# Special gmake rules.
################################################################################
#
# Re-define the list of default suffixes, so gmake won't have to churn through
# hundreds of built-in suffix rules for stuff we don't need.
#
.SUFFIXES:
.SUFFIXES: .out .a .ln .o .obj .c .cc .C .cpp .y .l .s .S .h .sh .i .pl .class .java .html
#
# Don't delete these files if we get killed.
#
.PRECIOUS: .java $(JDK_HEADERS) $(JDK_STUBS) $(JRI_HEADERS) $(JRI_STUBS) $(JMC_HEADERS) $(JMC_STUBS)
#
# Fake targets. Always run these rules, even if a file/directory with that
# name already exists.
#
.PHONY: all all_platforms alltags boot clean clobber clobber_all export install libs realclean release $(OBJDIR) $(DIRS)

Просмотреть файл

@ -1,135 +0,0 @@
#! gmake
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
include $(DEPTH)/config/ruleset.mk
# Set TARGETS to null so that the config/corerules work
#TARGETS =
# This is actually our modified version of
# $(DEPTH)/config/core/rules.mk, and should
# hopefully be temporary until we can get the
# config/core people to merge our changes with theirs
include $(DEPTH)/config/corerules.mk
ifneq ($(MODULE_NAME),)
# OBJFILTERS is neccesary for the ifneq check below
# since OBJS seems to have an undetermined number of blanks in it
OBJFILTERS = $(filter %$(OBJ_SUFFIX),$(OBJS))
ifneq ($(OBJFILTERS),)
MODULE_FILE = $(OBJDIR)/moduleFile
$(MODULE_FILE): $(OBJS)
@$(MKDIR) $(DIST)/modules/$(MODULE_NAME)
@$(MAKE_OBJDIR)
cp -f $? $(DIST)/modules/$(MODULE_NAME)
touch $(MODULE_FILE)
libs:: $(MODULE_FILE)
clean::
rm -f $(MODULE_FILE)
endif
endif
ifneq ($(HEADER_GEN),)
$(HEADER_INCLUDES):
@$(MKDIR) $(HEADER_GEN_DIR)
$(JAVAH) -d $(HEADER_GEN_DIR) $(HEADER_GEN)
$(OBJS) : $(HEADER_INCLUDES)
endif
ifneq ($(filter %.h,$(LOCAL_EXPORTS)),)
LOCAL_EXPORT_FILES = $(addprefix $(LOCAL_EXPORT_DIR)/,$(LOCAL_EXPORTS))
$(LOCAL_EXPORT_DIR)/%.h : %.h
@$(MKDIR) $(LOCAL_EXPORT_DIR)
@rm -f $(LOCAL_EXPORT_DIR)/$<
$(LN) $(CUR_DIR)/$< $(LOCAL_EXPORT_DIR)/$<
export:: $(LOCAL_EXPORT_FILES)
endif
ifneq ($(filter %.h,$(LOCAL_MD_EXPORTS_x86)),)
LOCAL_MD_x86_EXPORT_FILES = $(addprefix $(LOCAL_EXPORT_DIR)/md/x86/,$(LOCAL_MD_EXPORTS_x86))
$(LOCAL_EXPORT_DIR)/md/x86/%.h : %.h
@$(MKDIR) $(LOCAL_EXPORT_DIR)/md/x86
@rm -f $(LOCAL_EXPORT_DIR)/md/x86/$<
$(LN) $(CUR_DIR)/$< $(LOCAL_EXPORT_DIR)/md/x86/$<
export:: $(LOCAL_MD_x86_EXPORT_FILES)
endif
ifneq ($(filter %.h,$(LOCAL_MD_EXPORTS_ppc)),)
export::
@$(MKDIR) $(LOCAL_EXPORT_DIR)/md/ppc
@$(LN) $(LOCAL_MD_EXPORTS_ppc) $(LOCAL_EXPORT_DIR)/md/ppc
endif
ifneq ($(filter %.h,$(LOCAL_MD_EXPORTS_sparc)),)
export::
@$(MKDIR) $(LOCAL_EXPORT_DIR)/md/sparc
@$(LN) $(LOCAL_MD_EXPORTS_sparc) $(LOCAL_EXPORT_DIR)/md/sparc
endif
ifneq ($(filter %.h,$(LOCAL_MD_EXPORTS_hppa)),)
export::
@$(MKDIR) $(LOCAL_EXPORT_DIR)/md/hppa
@$(LN) $(LOCAL_MD_EXPORTS_hppa) $(LOCAL_EXPORT_DIR)/md/hppa/$<
endif
# Browse information
$(BROWSE_INFO_FILE): $(BROWSE_INFO_OBJS)
$(BROWSE_INFO_PROGRAM) $(BROWSE_INFO_FLAGS) -o $(BROWSE_INFO_FILE) $(BROWSE_INFO_OBJS)
@cp $(BROWSE_INFO_FILE) $(DIST)/lib
# Remove additional ef-specific junk
clean::
rm -f $(OBJDIR)/vc50*.*
rm -f $(OBJDIR)/BrowseInfo/*.sbr
clobber::
rm -r -f $(OBJDIR)/BrowseInfo
ifneq ($(LIBRARIES),)
# Add the lib prefix on all platforms except WINNT
ifeq ($(OS_ARCH),WINNT)
LIBRARIES := $(addprefix $(DIST)/lib/,$(LIBRARIES))
LIBRARIES := $(addsuffix .lib,$(LIBRARIES))
else
LIBRARIES := $(addprefix -l,$(LIBRARIES))
endif
LDFLAGS += $(LIBRARIES)
endif

Просмотреть файл

@ -1,77 +0,0 @@
MailStone 4.15: Changes to Mailstone since version 4.1
* Setup now checks license acceptance and configures a basic
setup. By default, it will also create a user LDIF file with a
'allusers' account.
* All parameters and and testbed information may now be specified
in the workload files (*.wld). New sections: CONFIG, CLIENT,
MONITOR, PRETEST, and POSTTEST. Command line parameters still
override the files. A complete copy of the configuration is saved
in results/<TIMESTAMP>/all.wld.
* The '*.pl', '*.tbd', and 'config*' files in ./conf/ are
depreciated. These should still work, but the new sections are
simpler and more flexible.
* Any CONFIG parameter can now be specified on the command line
using the form: 'PARAMETER=value'. Note that PARAMETER is case
insensitive. No whitespace is allowed before or after the '='.
* The new switch '-l' or CONFIG parameter 'ClientCount' can now
specify the total number of clients. The 'MaxClients' and
'MaxThreads' parameters in each CLIENT section control load
balancing. If the 'processes' and 'threads' parameters are set,
then the load for that CLIENT section will not be adjusted, but
will be taken into account when calculating other CLIENT sections.
If just 'processes' is set, then only the thread count will be
adjusted. All hosts in a CLIENT section will run the same number
of processes and threads.
* bin/makeusers.pl now creates users, broadcast account, etc.
Numbered passwords are now suppored. The new user/password format
now replaces '%ld' with the user number to match the rest of
mailstone. The ldif/ directory is obsolete. Run "perl/bin/perl
bin/makeusers.pl -h" for usage.
* NT client machines may now be used from a Unix test master. See
conf/sample.wld for configuration details.
* Commands can now be run for a specified block count, error
count, or time (whichever comes first). Set 'maxBlocks' and/or
'maxErrors'.
* Telemetry logging to /var/tmp/mstone-log.pn.tn is now performed
when "telemetry 1" is specified.
* The name used in the "CLIENT" section is now used to match
"HOSTS=..." qualifier. Compatibility with "hostname" is no longer
needed.
* Config values can now use quoted characters such as \n, \r, \t
* Config values can be continued using \ (backslash)
* System configuration information (SYSCONFIG) can now be
specified entirely within a workload file by quoting the newlines.
* Config values get enclosing double-quotes stripped
* Preliminary support for HTTP and WMAP (WebMail) testing.
* New table formats are easier to interpret and allow more protocols.
* The new text format report is easier to machine processes.
* The following command line switches are now obsolete: -f, -g,
-e, -p, and -l. The same functionality can be obtained by
FREQUENCY=<interval>, GNUPLOT=<path>, RSH=<path>, RCP=<path>, and
TEMPDIR=<directory> respectively.
* File backups are now created. When ./process is run multiple
times, the old files are moved to the ./tmp/<TIMESTAMP>/
directory.
* perl has been updated to include full perl5.005_03 install
package. Perl support for each architecture is now under the
perl/ directory.

Просмотреть файл

@ -1,222 +0,0 @@
Mstone 4.15 Quick Installation
This version of Mstone runs on many current UNIX platforms and NT.
Only a web browser and text editor are needed to view the results and
configure tests.
QUICK INSTALL
-------------
IMPORTANT: If you have an existing mstone, save a copy of the
mstone/conf directory to preserve any configuration files you may want
to keep.
Unpack distribution:
tar xzf /tmp/mstone_OPT.tar.gz
or
gunzip -c /tmp/mstone_OPT.tar.gz | tar xf -
or
unzip /tmp/mstone_OPT.zip
cd mstone
Both the tar.gz file and the zip file are identical. Use whichever is
more convenient for you.
This will create a sub-directory named "mstone" with files and
directories under that.
cd mstone
NOTE: all scripts must be run from the mstone directory.
Do initial configuration:
Run "mstone config". It will ask you about your system configuration.
Fill in the appropriate values and create the optional user accounts
and broadcast account. When it asks about client machines, enter them
seperated by commas, with no spaces (e.g. host1,host2,host3). If you
need to re-configure, run "mstone config".
The machine starting the test may also be a client. For accurate
results, clients should not be run on the test mailserver machine (or
its directory server). If all the client machines are not running
the same operating system version, see "Configuring Client Machines"
below to configure for different OSes.
When the test master is on NT, only the local machine may be a client
and only one process is allowed. You will not be asked about client
machines.
Setup only configures the most important parameters. If you have more
advanced needs, edit conf/general.wld appropriately.
Run "mstone setup". It will now push the necessary files to each
client machine. If there are problems (i.e. with rsh permissions),
fix them and re-run "mstone setup" until everything works.
Install test accounts:
Setup will create a file called conf/MAILHOST.ldif (where MAILHOST is the
name of your mail server). If you are not using Netscape Messaging
and Directory Servers, then you may have to edit the ldif file or use
alternate means to create the user accounts.
To import these users into Netscape Messaging Server, use "add
entries" from the directory console or use the ldapmodify command line
utility.
Note: imports will go faster if access logging is disabled. For large
user counts (more than 10,000 users), it may be much faster to export
the current database, merge the files together manually, and then
import the new database.
Here is how the ldapmodify supplied with Netscape Messaging Server
would be used.
setenv LD_LIBRARY_PATH /usr/netscape/messaging/lib
cd /usr/netscape/messaging
shared/bin/ldapmodify -h mailhost -a -D 'cn=directory manager' -w d_m_password < conf/MAILHOST.ldif
Check time consistency:
IMPORTANT: The system time on each client machine must be synchronized
within one second of each other for accurate results graphs.
Run "checktime" to see the time on each client. There should not be
more than two seconds difference among the displayed time.
The best way to synchronize clients is use NTP (Network Time Protocol)
or similar protocols (like rdate or timeslave) that have sub second
accuracy.
A simple utility called "timesync" is provide to push the local
system time to all clients. You must be root and have root rsh
permissions to use timesync. Timesync only works on OSs that support
setting seconds using "date MMDDhhmmCCYY.ss". Timesync is only
accurate to a second (at best) and should only be used if better
protocols aren't available.
When running the test master on NT, "checktime" and "timesync" are
never needed (because there is only one client machine). Timesync
will be ignored for NT clients, another method must be used
(e.g. timeserv or Dimension4).
Run tests:
Try it out. Use small process and thread counts until everything is
working.
mstone pop -t 30s
The script will tell you how many processes and threads it is running
on each system and where errors are logged. At the end of the test,
it will print out a URL for the test results and an indication of the
size of the errorlog file (stderr).
The results of the mstone run will display statistics for each
protocol that was tested. The results are presented in both a HTML
web page and a text file. The text file is simple and uniform, while
the web page is more user readable. The web page has links to the
test configuration files, error log, and the text version.
For long tests run (e.g. 8 hours), the results can be updated while
the test is running by using the "process" utility. Don't run
"process" near the very end of the test.
If a test has to be aborted, then use "process" to generate a report
using the available data.
Customize tests:
Copy and edit the scripts (e.g. "conf/pop.wld") to define new tests.
The CONFIG section specifies all the attributes used in the test.
Other sections specify the protocols to be tested and the parameters
for them.
All switches can be overridden on the command line to facilitate
easier testing. The exact configuration (include command line
overrides) is stored with the results from each test.
Maintenance:
You can run "mstone setup" at any time (except during a test :-) to
update the files on the client machines.
Use "mstone cleanup" to remove the files created by "mstone setup".
After the test is finished, the directories under "tmp/" can be
compressed or deleted to save space. All the information about a test
run is stored in the "results/" directories.
Configuring client machines:
Edit conf/general.wld to include CLIENT sections for each machines to
use.
You can also specify the OS type for each client machine. Set the
"Arch" parameter in each CLIENT section as appropriate (e.g. SunOS5.6,
Linux2.2_x86, AIX4.2, HP-UXB.11.00, IRIX6.5, OSF1V4.0, WINNT4.0). The
directories under "bin" specify the available OS types.
For NT4.0 clients with a UNIX test master, you will need to configure
"command" and "tempDir" for proper operation. See the "HOSTS=winnt01"
example in conf/sample.wld.
The total number of processes and threads that can be supported on a
client is dependent on the number of commands in the test, the OS, and
available memory. Check the stderr log for messages about not being
able to create processes or threads. Check on the client machines
during the test and make sure they aren't running out of CPU. The
UNIX programs "top" and "vmstat" are good for this. If the client CPU
is more than 75% busy, use more machines.
Also watch out for network saturation. You may have to use machines
with separate networks to the server to reach full server load.
Know problems:
There can be extraneous errors or connections after the specified end
of the test. These are most likely do to stopping the test and should
be ignored.
At the end of the test, all current connections will logout without
any delays. This can cause very high peak loads.
If one process exits early (due to misconfiguration or resource
exhaustion) and the monitoring command did not specify a count (%c),
then the monitoring tasks will be terminated early as well.
Monitoring commands that specify a count (%c), may take longer than
predicted and delay the processing of test results. This is because
vmstat actually delays the requested time plus the time needed to
generate the statistics summary.
If you are doing tests with large thread counts, you may have to run
as root to allow mailclient to raise its resource limits.
The telemetry logging for SMTP, POP3, and IMAP4 is incomplete. Most
commands are captured, but banners and message contents may be missing.
The MaxBlocks parameter gets divided by the total number of processes
before starting each client. This doesn't account for clients that
don't have commands to run.
The HTTP protocol used by WMAP allows connections to be dropped and
re-connected as needed. WMAP logs this as an error and an additional
connect. The error log must be consulted to distinguish another types
of connection errors (timeout or connection refused) from an automatic
re-connect.
The HTTP protocol test is experimental and subject to change.

Просмотреть файл

@ -1,246 +0,0 @@
# Makefile for mstone
# use gmake
# Builds each of the components and then packages everything
topsrcdir = .
CP := cp -p
ifndef INCLUDED_CONFIG_MK
include $(topsrcdir)/config/config.mk
endif
# dynamically find the optional directories names
LIBGD_DIR = $(wildcard gd?.*)
GNUPLOT_DIR = $(wildcard gnuplot-?.*)
PERL_DIR = $(wildcard perl5.*)
# file that we package
GDFILES = gd.txt gd.html libgd.* gd.h demoin.gif gddemo giftogd webgif
GNUPLOTFILES = gnuplot Copyright gnuplot_x11 gnuplot.1 gnuplot.gih
VERSION = 4.3
TARBALL = mstone-$(VERSION)-$(NSARCH)$(OBJDIR_TAG).tar.gz
ZIPFILE = mstone-$(VERSION)-$(NSARCH)$(OBJDIR_TAG).zip
TARBALL_ALL = mstone-$(VERSION)-all$(OBJDIR_TAG).tar.gz
ZIPFILE_ALL = mstone-$(VERSION)-all$(OBJDIR_TAG).zip
NTFILES = mstone.bat process.bat setup.bat
all:: usage
usage::
@$(ECHO) "gmake [ release | rpackage | debug | dpackage ]"
@$(ECHO) " [ DIST=/m/dist/mailstone/1999xxxx dist ]"
@$(ECHO) " [ all_DBG | all_OPT ]"
@$(ECHO) "perl is" $(PERL_DIR) ". gd is" $(LIBGD_DIR) ". gnuplot is" $(GNUPLOT_DIR) "."
targets:: $(OBJDIR) mailclient
ifneq (,$(LIBGD_DIR))
targets:: libgd
endif
ifneq (,$(GNUPLOT_DIR))
targets:: gnuplot
endif
ifneq (,$(PERL_DIR))
targets:: perl
endif
$(OBJDIR):
-mkdir -p $(OBJDIR)
mailclient::
@$(ECHO) "\n===== [`date`] making OS_CONFIG=$(NSARCH) BUILD_VARIANT=$(BUILD_VARIANT)\n"
cd src; $(MAKE) BUILD_VARIANT=$(BUILD_VARIANT) OBJDIR=../$(OBJDIR) PKGDIR=../$(PKGDIR) all
# Use our top level makefiles to drive the component builds
libgd $(OBJDIR)/gd/libgd.a::
$(MAKE) -f gd.mk LIBGD_DIR=$(LIBGD_DIR) libgd
gnuplot $(OBJDIR)/gnuplot/gnuplot::
$(MAKE) -f gnuplot.mk LIBGD_DIR=$(LIBGD_DIR) GNUPLOT_DIR=$(GNUPLOT_DIR) gnuplot
perl $(OBJDIR)/perl/perl::
$(MAKE) -f perl.mk PERL_DIR=$(PERL_DIR) perl
# Create packaging binary directories
# Note: dont make gd or gnuplot here. For multi-OS, they are links
mkpkgdirs:: $(PKGDIR)/bin $(PKGDIR)/conf $(PKGDIR)/data $(PKGDIR)/doc
$(PKGDIR)/bin:
mkdir -p $(PKGDIR)/bin
$(PKGDIR)/conf:
mkdir -p $(PKGDIR)/conf
$(PKGDIR)/data:
mkdir -p $(PKGDIR)/data
$(PKGDIR)/doc:
mkdir -p $(PKGDIR)/doc
$(PKGDIR)/gd:
mkdir -p $(PKGDIR)/gd
$(PKGDIR)/gnuplot:
mkdir -p $(PKGDIR)/gnuplot
$(PKGDIR)/perl:
mkdir -p $(PKGDIR)/perl
# operating system independent share-files (at least for Unix)
pkg-share-files:: mkpkgdirs
@$(ECHO) "\n===== [`date`] making package share-files...\n"
$(CP) mstone process $(PKGDIR)
(cd $(PKGDIR); [ ! -f setup ] || rm -f setup; ln -s mstone setup)
(cd $(PKGDIR); [ ! -f cleanup ] || rm -f cleanup; ln -s mstone cleanup)
(cd $(PKGDIR); [ ! -f checktime ] || rm -f checktime; ln -s mstone checktime)
(cd $(PKGDIR); [ ! -f timesync ] || rm -f timesync; ln -s mstone timesync)
$(CP) nsarch bin/*.pl $(PKGDIR)/bin
$(CP) conf/*.wld conf/*.wld.in conf/*.html $(PKGDIR)/conf
$(CP) data/*.msg $(PKGDIR)/data
$(CP) doc/*.html doc/*.gif $(PKGDIR)/doc
$(CP) INSTALL $(PKGDIR)
$(CP) README $(PKGDIR)
$(CP) ChangeLog $(PKGDIR)
$(CP) LICENSE $(PKGDIR)
# split out OS specific file so that combined packaging possible (set PKGDIR)
pkg-arch-files-gd:: $(PKGDIR)/gd $(OBJDIR)/gd/libgd.a
$(CP) $(addprefix $(OBJDIR)/gd/, $(GDFILES)) $(PKGDIR)/gd
-$(STRIP) $(PKGDIR)/gd/webgif $(PKGDIR)/gd/giftogd $(PKGDIR)/gd/gddemo
pkg-arch-files-gnuplot:: $(PKGDIR)/gnuplot $(OBJDIR)/gnuplot/gnuplot
$(CP) $(addprefix $(OBJDIR)/gnuplot/, $(GNUPLOTFILES)) $(PKGDIR)/gnuplot
-$(STRIP) $(PKGDIR)/gnuplot/gnuplot $(PKGDIR)/gnuplot/gnuplot_x11
ifneq (,$(LIBGD_DIR))
pkg-arch-files:: pkg-arch-files-gd
endif
ifneq (,$(GNUPLOT_DIR))
pkg-arch-files:: pkg-arch-files-gnuplot
endif
pkg-arch-files:: $(PKGDIR)/bin $(OBJDIR)/mailclient
@$(ECHO) "\n===== [`date`] making package arch-files...\n"
$(CP) $(OBJDIR)/mailclient $(PKGDIR)/bin
-$(STRIP) $(PKGDIR)/bin/mailclient
pkg-perl-files:: $(PKGDIR)/bin $(OBJDIR)/perl/perl
@$(ECHO) "\n===== [`date`] making package perl-files...\n"
$(MAKE) -f perl.mk PERL_DIR=$(PERL_DIR) \
BUILD_VARIANT=$(BUILD_VARIANT) \
OBJDIR=$(OBJDIR) PKGDIR=$(PKGDIR) package-perl
find $(PKGDIR)/perl/lib -name .packlist -exec rm {} \; -print
-$(STRIP) $(PKGDIR)/perl/bin/perl
-$(STRIP) $(PKGDIR)/perl/bin/a2p
# for combined packaging, this should not be part of pkg-arch-files
# perl is handled seperately do to its size
ifneq (,$(PERL_DIR))
pkg:: pkg-perl-files
endif
pkg:: targets pkg-share-files pkg-arch-files
tarball: build/$(TARBALL)
build/$(TARBALL):
@$(ECHO) "\n===== [`date`] making os tar file...\n"
-rm -f build/$(TARBALL)
cd $(dir $(PKGDIR)) && tar cf - . | gzip > ../../$(TARBALL)
zipfile: build/$(ZIPFILE)
build/$(ZIPFILE):
@$(ECHO) "\n===== [`date`] making os zip file...\n"
-rm -f build/$(ZIPFILE)
cd $(dir $(PKGDIR)) && zip -r -q ../../$(ZIPFILE) .
########################################################################
# Generate a combined build for every Unix OS that is already packaged
# NT has to be done seperately because it has different file names
# We have to nuke some old parts, because permissions wont allow overwrites
# Finally, dont ship perl development headers and libraries
all_DBG all_OPT::
@$(ECHO) "===== [`date`] unified packaging for $@..."
$(MAKE) NSARCH=$@ OBJDIR_TAG='' \
PKGDIR=$(topsrcdir)/build/package/$@.OBJ/mstone pkg-share-files
./ospkg.sh $@.OBJ \
$(notdir $(shell ls -d build/package/[A-Z]*$(subst all,,$@.OBJ)))
[ -d $(topsrcdir)/build/package/$@.OBJ/mstone/bin/WINNT4.0 ] \
&& cp -p $(NTFILES) $(topsrcdir)/build/package/$@.OBJ/mstone; :
-rm -f ./build/mstone-$(VERSION)-$@.tar.gz
cd ./build/package/$@.OBJ \
&& tar cf - . | gzip > ../../mstone-$(VERSION)-$@.tar.gz
-rm -f ./build/mstone-$(VERSION)-$@.zip
cd ./build/package/$@.OBJ \
&& zip -r -q ../../mstone-$(VERSION)-$@.zip .
########################################################################
# Copy all the packaged trees to the distribution site
# Copy in the unified tarball and zip file
# Link mstone to mailstone for Netscape back compatibility
# Re-map short Linux name to standard Netscape convention
dist::
@[ "$(DIST)" != "" ] || ($(MAKE) usage && /bin/false)
@[ ! -d "$(DIST)" ] || ($(ECHO) "Error: $(DIST) already exists" && \
$(MAKE) usage && /bin/false)
mkdir -p $(DIST)
cp -p build/mstone-$(VERSION)-all_*.*[a-z] $(DIST)/
(cd build/package; tar cf - *.OBJ) | (cd $(DIST); tar xf - )
for l in $(DIST)/*_???.OBJ ; do \
(cd $$l; ln -s mstone mailstone); done
cd $(DIST); for l in Linux*_???.OBJ ; do \
nn=`echo $$l | sed -e 's/_OPT/_glibc_PTH_OPT/' | sed -e 's/_DBG/_glibc_PTH_DBG/'`; \
ln -s $$l $$nn; done
# since the default is release mode, this can just work off a dependency
release:: targets
#release::
# @$(ECHO) "\n===== [`date`] making release build..."
# $(MAKE) BUILD_VARIANT=release OBJDIR_TAG=_OPT targets
@$(ECHO) "\n===== [`date`] making release build done."
rpackage:: release pkg #tarball zipfile
#rpackage:: release
# @$(ECHO) "\n===== [`date`] making release package..."
# $(MAKE) BUILD_VARIANT=release OBJDIR_TAG=_OPT pkg tarball zipfile
@$(ECHO) "\n===== [`date`] making release package done."
# since the default is release mode, start a make with the right mode
debug::
@$(ECHO) "\n===== [`date`] making debug build..."
$(MAKE) BUILD_VARIANT=debug OBJDIR_TAG=_DBG targets
@$(ECHO) "\n===== [`date`] making debug build done."
# We dont usually bother to tar up a debug build
dpackage:: debug
@$(ECHO) "\n===== [`date`] making debug package..."
$(MAKE) BUILD_VARIANT=debug OBJDIR_TAG=_DBG pkg
@$(ECHO) "\n===== [`date`] making debug package done."
# These are old and may be broken
cleanvariant::
(cd src; $(MAKE) OBJDIR=../$(OBJDIR) clean)
rm -rf $(PKGDIR)
clean::
$(MAKE) BUILD_VARIANT=release OBJDIR_TAG=_OPT cleanvariant
$(MAKE) BUILD_VARIANT=debug OBJDIR_TAG=_DBG cleanvariant
distcleanvariant::
(cd src; $(MAKE) OBJDIR=../$(OBJDIR) distclean)
rm -rf $(OBJDIR) $(PKGDIR)
distclean:: clean
$(MAKE) BUILD_VARIANT=release OBJDIR_TAG=_OPT distcleanvariant
$(MAKE) BUILD_VARIANT=debug OBJDIR_TAG=_DBG distcleanvariant

Просмотреть файл

@ -1,189 +0,0 @@
Mstone TODO List
Updated:
3-20-2000 Dan Christian
======================================================================
Minor improvements
Data reduction at each testbed client
Test message generator (plain and MIME styles)
More graphs for multiple runs
Option to drop a fraction of connections
IMAP delete without reading
Just get the message list and delete everything. This could
be the fastest way to drain out the store.
Display MIN/MAX or standard deviation on graphs
Gnuplot can do data points with error bars. You could either
use MIN/MAX or the standard deviation for the error bars. There are
issues with calculating the standard deviation numbers throughout the
graph that need to be addressed.
Statistics reset
At least the MIN and MAX statistics could be easily reset
during the test (after ramp up). This keeps the transients during
startup and shutdown from dominating these numbers. The standard
deviation statistics are much trickier to reset during the run. It
may be better to isolate sections in post processing.
Perl web server
Sometimes it would be nice to include our own web server to
provide the results (instead of using file: URLs). This would also be
a gateway to form based test configuration editing and allow results
to be interactively updated during tests. Perl with a socket library
could handle this without too much trouble.
Dynamic test loading
Finalize an API for dynamically loading tests. This would
allow tests to be added or updated separately from the core
functionality. This may be needed for some types of security testing.
Link graphs to the results tables
There are already tags by each graph. You should be able to
link the appropriate results table entry to each graph. This sort of
tricky since graphs often combine multiple entries.
Show statistics for every block
Statistics are actually kept for every block in every thread.
There should be a way to view information at this detail.
Man pages
The online docs are nice, but good 'ol man pages would be
great in a different way.
Reduce namespace polution
Scripts names like setup and cleanup are too general. They
should be part of the main 'mstone' script (e.g. mstone setup).
Examples of script series
Include example scripts to run entire series of tests in a
sane way.
Fix FORMAT clash
At the start of a test, each client process outputs the
information needed to report all its protocols. When there are
multiple processes on one client, these FORMAT lines can intermix and
cause parsing errors.
Set connection drop rate
Drop some percentage of the connections without a proper
shutdown. This tests how well a server can detect and recover from
hard disconnects.
Improve randomness
The way that we generate random numbers in a range may be not
generate the proper randomness. We are using lrand48()%range we
should use (lrand48/RAND_RANGE)*range. There are some end conditions
that need to be thought about. All of this is in the sequence code;
one change should fix (or break :) everything.
Also, we may be generating numbers that are never used. This
may be costly, and can create holes in the proper sequence.
Improve printing
The color graphs are great on screen, but tend to print
poorly. Either we need a better way to generate a printable version
(maybe through a CGI button), or the seperate protocols need to be
printed individually. Also, Communicator does a lousy job of keeping
title with tables or graphs. Hopefully, Mozilla will do better.
======================================================================
Whole new protocol tests:
ICQ
Test high volume instant messaging. Very useful for the
bridges and gateways that people are considering using.
WAP
WAP is the emerging standard for mobile phones.
WCAP
Web based calendar services
LDAP
Use the LDAP SDK to do basic LDAP testing. The SDK probably
isn't fast enough to call this a real performance test, but you can at
least test performance degredation due to load from a real application
(like a mail server).
DNS
Mail servers use DNS a lot. You should at least be able to
see if performance is degrading due to load.
Disk/filesystem
Test read, write, sync, link, un-link, and append performance under
multiple threads.
Cert servers
Test certificate authenticity checking performance
======================================================================
Possible dummy servers:
SMTP
Receive mail via SMTP and ignore it. Usefull for SMTP relay
testing.
DNS
Simulate slow DNS server lookups. Usefull for SMTP relay testing.
======================================================================
Major changes
Throttling
Monitor and control transaction rates so that specific load
levels can be easily specified. The rates should be able to vary to
simulate peek hour usage and disconnect-restore.
NSPR threading
Use NSPR for threading and sockets. This may allow other OSes
to be used as clients. This might be easy, since mstone does not need
any locking, just simple thread creation and harvesting. NSPR
argument parsing and hashes may also be useful.
SSL
Support SSL on the protocols that allow it. May require NSPR.
Line speed emulation
Simulate the variable delays and limited throughput of dial up
connections.
Scripting
Allow more detailed control of protocol tests. It looks
difficult to make this scalable and fast.
Combined tests
Deliver mail over SMTP and then see when it arrives using IMAP.

Просмотреть файл

@ -1,462 +0,0 @@
#!/bin/ksh
########################################################################
# buildall - automated multi-platform build tool
#
# 10/09/97 - marcel - created
# 10/13/97 - marcel - support shared build tree
# 2/11/98 - marcel - updated for 4.0 Beta builds (need -update)
# 2/26/98 - marcel - added -r, -t and host specifiers
# 7/01/99 - robodan - added VAR=value ability
# 8/01/99 - robodan - explicitly know about building on localhost
# 10/15/99 - robodan - remove older OSes from build list
# 2000/4/7 - robodan - Created mstone version
########################################################################
#
# This script is intended to do a set of UNIX builds for a
# given CVS module. It is designed to use 'rsh' between a
# set of trusting hosts and use shared NFS storage with common
# mount points (e.g. /u/username/...)
#
# To check if you have rights to rsh to a particular host, try:
# rsh hostname "echo $PATH"
# You may have to edit your .rhosts or /etc/hosts.equiv
#
# A target directory will be created based on the current date.
#
# A set of global build logs plus a log per platform are kept
# in a log directory under the target
#
# It will checkout a copy of the source, duplicate it for
# each platform and perform a set of remote builds in parallel.
# The script will exit when all the work has been completed.
#
# Example usage:
# cd ~/src; buildall msg
# Result:
# ~/src/19980210_40.1/
# ~/src/19980210_40.1/logs/...
# ~/src/19980210_40.1/src/...
# ...
#
# Buildhosts
DEFAULT_BUILDHOSTS="kimo nugget vsync shave purgatory trex0"
usage() {
echo ""
echo "usage: buildall [ make assigns... ] < -t | target > [ -r ] [ buildhosts... ]"
echo " [ -t | --test]: just test rsh and report OS versions."
echo " [-r | --respin]: rebuild in place using existing source."
echo " [-p | --postbuild]: Execute post build command too."
echo " [make assigns]: e.g. VARIANT=release"
echo " <target>: one of: mstone42"
echo " [buildhosts...]: default [$DEFAULT_BUILDHOSTS]"
echo ""
exit 1
}
########################################################################
# Set these defaults and options for your desired build
########################################################################
# Target base destination directory
DESTBASE=`pwd`
# Can we do multiple ARCH builds in same source tree
SHARESRC=yes
DESCRIPTION=""
BUILDHOSTS=""
RESPIN="no"
POSTBUILD="no"
JUST_TEST="no"
DESTTYPE=""
CO_CMD="cvs -d $CVSROOT -q checkout"
CHECKOUT=""
CHECKOUT2=""
#MOZCVSROOT=':pserver:anonymous@cvs.mozilla.org:/cvsroot'
MOZCVSROOT=':pserver:robodan%netscape.com@cvs.mozilla.org:/cvsroot'
MAKE="gmake"
MK_ARG=""
ARGS="$@"
for ARG in "$@"; do
# If this is a make assignment (FOO=whatever), add it to make command
# Arguments with quotes in them dont go all the way through.
# Make args trick: 'FOO=nop -j 2'
# The pre-post arg stuff uses hostnames as a switch, ugly calling syntax.
if [[ -n "`echo z$ARG | egrep '^z[A-Z0-9_]+=[^ ]'`" ]] ; then
if [[ -n "$DESCRIPTION" ]] ; then
echo "Arg after target is ignored! ($ARG)"
continue
fi
if [[ -z "$BUILDHOSTS" ]] ; then # pre args
MAKE="$MAKE $ARG"
else # post args
MK_ARG="$MK_ARG $ARG"
fi
continue
fi
# should we just rebuild todays latest source...
if [[ "$ARG" = "-r" || "$ARG" = "--respin" || "$ARG" = "respin" ]]; then
RESPIN="yes"
continue
fi
# should we just run post build command...
if [[ "$ARG" = "-p" || "$ARG" = "--postbuild" || "$ARG" = "postbuild" ]]; then
POSTBUILD="yes"
continue
fi
# should we just test remote connectivity and execute permissions...
if [[ "$ARG" = "-t" || "$ARG" = "--test" ]]; then
JUST_TEST="yes"
RESPIN="yes"
continue
fi
# We will pull source using: "$CHECKOUT"
# And build on each machine: "cd $BUILDDIR && $BUILDCMD"
# expand targets (but dont confuse hosts for targets (msg7))
# These will build just mstone
# expand targets (but dont confuse hosts for targets (msg7))
if [[ "$BUILDCMD" = "" && "$ARG" = mailstone* ]]; then
case ${ARG#mstone} in
"")
"42")
DESTTYPE=_MSTONE42
MS_BRANCH=""
#BUILDCMD="$MAKE $MK_ARG debug release"
#POSTCMD="$MAKE $MK_ARG all_DBG.OBJ all_OPT.OBJ"
BUILDCMD="$MAKE $MK_ARG rpackage"
POSTCMD="$MAKE $MK_ARG all_OPT"
;;
*)
echo "Unknown mstone version in $ARG"
echo "Try mstone42"
exit 1;;
esac
DESCRIPTION="Mstone $MS_BRANCH"
BUILDDIR=./mozilla/mstone
CVSROOT=$MOZCVSROOT
CHECKOUT="$CO_CMD $MS_BRANCH mozilla/mstone"
# BUG No way to unpack perl, gd, and gnuplot before building
continue
fi
#########################
# Other...
#########################
# These will print some tools info
if [[ "$ARG" = "tools" ]]; then
CHECKOUT="$CO_CMD modules"
BUILDDIR=.
BUILDCMD="which gcc && ls -l /tools/ns/bin/gcc && which gcc-2.7.2.1 && ls -l /tools/ns/bin/gcc-2.7.2.1"
continue
fi
#########################
# Everything else is assumed to be a hostname
#########################
BUILDHOSTS="$ARG $BUILDHOSTS"
done # for ARG in $*; do
if [[ "$BUILDHOSTS" = "" ]]; then
BUILDHOSTS=$DEFAULT_BUILDHOSTS
fi
if [[ "$BUILDCMD" = "" && "$JUST_TEST" = "no" ]]; then
usage
fi
########################################################################
# You shouldn't have to modify stuff below here too much
########################################################################
# Who and Where are we
PROG=buildall
RSH=rsh
SYS=`uname -s`
echo SYS=$SYS
if [[ "$SYS" = "HP-UX" ]]; then
RSH=remsh
fi
########################################################################
# Simple log output function
########################################################################
log() {
# echo "[`date +\"%Y/%m/%d %H:%M:%S\"`] $PROG: $*"
echo "`date +\"%H:%M:%S\"` $PROG: $*"
}
########################################################################
# Error
########################################################################
quit() {
log "$* (exiting)..."
exit 1
}
# Where should the work be done
REV=1
WORKDIR=$DESTBASE/`date +"%Y%m%d"`$DESTTYPE.$REV
LASTWORKDIR=$WORKDIR
LASTREV=$REV
while [[ -d $WORKDIR ]]; do
LASTREV=$REV
let "REV= REV + 1"
LASTWORKDIR=$WORKDIR
WORKDIR=$DESTBASE/`date +"%Y%m%d"`$DESTTYPE.$REV
done
if [[ "$RESPIN" = "yes" ]]; then
WORKDIR=$LASTWORKDIR
REV=$LASTREV
fi
BUILDREV=$REV
if [[ ! -d $WORKDIR && "$RESPIN" = "yes" ]]; then
quit "missing expected respin workdir ($WORKDIR)"
fi
mkdir -p $WORKDIR
# Where to send logs
LOGDIR=$WORKDIR/logs
[[ -d $LOGDIR ]] || mkdir $LOGDIR
# What tool to use for compressed tar
if [[ -x /tools/ns/bin/tar ]] ; then # ROBDAN 9-15-98 for Linux
TAR=/tools/ns/bin/tar
else
TAR=tar
fi
SRCDIR=$WORKDIR/src
SRCTAR=$WORKDIR/src.tar.gz
########################################################################
# The function which extracts the source and prepares for copies
########################################################################
prepare_source() {
log "Preparing source code..."
mkdir $SRCDIR
(cd $SRCDIR;
log "Extracting source in $SRCDIR...";
log "$CHECKOUT > $LOGDIR/cvs-co.txt";
$CHECKOUT > $LOGDIR/cvs-co.txt;
RET=$?
if [[ $RET -ne 0 ]]; then quit "### Failed($RET): $CHECKOUT"; fi
if [[ "$CHECKOUT2" != "" ]]; then
log "$CHECKOUT2 >> $LOGDIR/cvs-co.txt";
$CHECKOUT2 >> $LOGDIR/cvs-co.txt;
RET=$?
if [[ $RET -ne 0 ]]; then quit "### Failed($RET): $CHECKOUT2"; fi
fi
log "Listing source...";
ls -Rl > $LOGDIR/src-ls-Rl.txt
log "Archiving source..."
$TAR czf $SRCTAR .
)
RET=$?
if [[ $RET -ne 0 ]]; then
quit "### Failed($RET): cannot prepare source";
else
log "Source extraction complete";
fi
}
########################################################################
# The function which does a build
########################################################################
do_rbuild() {
OSDEST=$1
if [ "$SHARESRC" = "yes" ]; then
RSRCDIR=$SRCDIR
else
RSRCDIR=$WORKDIR/$OSDEST
fi
[[ -d $RSRCDIR ]] || mkdir -p $RSRCDIR
cd $RSRCDIR;
# do any late variable expansions
RAWCMD=$BUILDCMD
BUILDCMD=$(eval echo $RAWCMD)
if [[ $RHOST = localhost ]] ; then
log "Build locally for $OSDEST ($BUILDCMD)...";
cd $BUILDDIR && pwd && $BUILDCMD && echo $PROG: Success
RET=$?
if [[ $RET -ne 0 ]]; then quit "### Failed($RET): $OSDEST build"; fi
log "Completed local build..."
return
fi
if [[ "$SHARESRC" != "yes" ]]; then
log "Extracting source for $OSDEST...";
$RSH $RHOST -n "cd $RSRCDIR && pwd && $TAR xzf $SRCTAR";
RET=$?
if [[ $RET -ne 0 ]]; then quit "### Failed($RET): $OSDEST source extraction"; fi
else
log "Using common source in $RSRCDIR";
fi
log "Building for $OSDEST ($BUILDCMD)...";
$RSH $RHOST -n "cd $RSRCDIR/$BUILDDIR && pwd && $BUILDCMD && echo $PROG: Success"
RET=$?
if [[ $RET -ne 0 ]]; then quit "### Failed($RET): $OSDEST build"; fi
log "Completed $OSDEST...";
}
buildhost() {
RHOST=$1
log "Query $RHOST configuration...";
if [[ $RHOST = localhost ]] ; then
uname -s > /tmp/$$.$RHOST 2>&1
else
$RSH $RHOST -n "uname -s" > /tmp/$$.$RHOST 2>&1
RET=$?
if [[ $RET -ne 0 ]]; then
quit "..[$RHOST] ### Failed($RET): $RSH $RHOST -n \"uname -s\"";
fi
fi
ROSTYPE=`tail -1 /tmp/$$.$RHOST`
if [[ "$ROSTYPE" = "AIX" ]]; then
$RSH $RHOST -n "uname -v" > /tmp/$$.$RHOST 2>&1
ROSTYPE=${ROSTYPE}`tail -1 /tmp/$$.$RHOST`
fi
if [[ $RHOST = localhost ]] ; then
uname -r > /tmp/$$.$RHOST 2>&1
else
$RSH $RHOST -n "uname -r" > /tmp/$$.$RHOST 2>&1
fi
ROSREV=`tail -1 /tmp/$$.$RHOST`
rm /tmp/$$.$RHOST
if [[ $RHOST = localhost ]] ; then
OSDEST=`hostname | cut -f1 -d.`-${ROSTYPE}${ROSREV}
else
OSDEST=${RHOST}-${ROSTYPE}${ROSREV}
fi
log "..Building on [$OSDEST]..."
REV=1 # find unique logfile name
OSLOG=$LOGDIR/$OSDEST.$REV
while [[ -f $OSLOG ]]; do
let "REV = REV + 1"
OSLOG=$LOGDIR/$OSDEST.$REV
done
if [[ "$JUST_TEST" = "yes" ]]; then
echo "$PROG: Success" > $OSLOG
else
( do_rbuild $OSDEST ) > $OSLOG 2>&1
fi
grep "$PROG: Success" $OSLOG > /dev/null
RET=$?
if [[ $RET -eq 0 ]]; then
RESULT="SUCCESS";
else
RESULT="FAILURE($RET)";
fi
log "..Completed [$OSDEST] <$RESULT>.";
}
########################################################################
# The function which initiates all the builds
########################################################################
do_builds() {
log "Launching builds..."
for HOST in $BUILDHOSTS; do
buildhost $HOST &
done
}
########################################################################
# main
########################################################################
main() {
if [[ "$JUST_TEST" = "yes" ]]; then
log "Automated test starting..."
else
log "Automated build of [$DESCRIPTION] starting..."
fi
log ""
log " ARGS = $ARGS"
log " BUILDHOSTS = $BUILDHOSTS"
log " WORKDIR = $WORKDIR"
log " SRCDIR = $SRCDIR"
log " LOGDIR = $LOGDIR"
log " CHECKOUT = $CHECKOUT"
log " BUILDDIR = $BUILDDIR"
log " BUILDCMD = $BUILDCMD"
log " RESPIN = $RESPIN"
log ""
[[ "$RESPIN" = "no" ]] && prepare_source
do_builds
log "Waiting for all builds to complete..."
wait
log "All builds completed."
if [[ -n "$POSTCMD" && "$POSTBUILD" = "yes" ]] ; then
log "Running post build command."
REV=1 # find unique logfile name
POSTLOG=$LOGDIR/postbuild.$REV
while [[ -f $POSTLOG ]]; do
let "REV = REV + 1"
POSTLOG=$LOGDIR/postbuild.$REV
done
echo "Dir $SRCDIR/$BUILDDIR" > $POSTLOG
echo "Cmd $POSTCMD" >> $POSTLOG
(cd $SRCDIR/$BUILDDIR && $POSTCMD && echo $PROG: Success) >> $POSTLOG 2>&1
log "Post build command completed."
elif [[ -n "$POSTCMD" ]] ; then
echo "Skipping post build command: $POSTCMD"
fi
}
REV=1
PROGLOG=$LOGDIR/$PROG.$REV
while [[ -f $PROGLOG ]]; do
REV=`expr $REV + 1`
PROGLOG=$LOGDIR/$PROG.$REV
done
main | tee $PROGLOG 2>&1
exit 0

Просмотреть файл

@ -296,7 +296,7 @@ sub kformat {
# simple function to formatted a time into Ns, Nms, or Nus
# the goal is to make a table of timss uncluttered and easy to read
# I dont convert to minutes or hours because the non-1000x multipliers
# I don't convert to minutes or hours because the non-1000x multipliers
# are hard to back solve in your head for comparisons
sub tformat {
my $n = shift;

Просмотреть файл

@ -1,576 +0,0 @@
#!/usr/bin/perl
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Netscape Mailstone utility,
# released March 17, 2000.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1997-2000 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Dan Christian <robodan@netscape.com>
# Marcel DePaolis <marcel@netcape.com>
# Mike Blakely
#
# Alternatively, the contents of this file may be used under the
# terms of the GNU Public License (the "GPL"), in which case the
# provisions of the GPL are applicable instead of those above.
# If you wish to allow use of your version of this file only
# under the terms of the GPL and not to allow others to use your
# version of this file under the NPL, indicate your decision by
# deleting the provisions above and replace them with the notice
# and other provisions required by the GPL. If you do not delete
# the provisions above, a recipient may use your version of this
# file under either the NPL or the GPL.
#####################################################
# see setup.pl for full usage
# mailmaster [-d] [-c <config file>] ...
# This script reads in the client configuration files and will
# fork children to rsh the mailclient process on network clients,
# each child will write test results to /mailstone directory before
# dying. The parent will the read and combine the results.
#
# Make sure the user running this script has rsh privilege across
# all client machines
print "Netscape Mailstone version 4.2\n";
print "Copyright (c) Netscape Communications Corp. 1997-2000\n";
# this parses the command line and config file
do 'args.pl'|| die "$@\n";
parseArgs(); # parse command line
{ # get unique date string
my ($sec, $min, $hour, $mday, $mon, $year) = localtime;
my $tstamp = sprintf ("%04d%02d%02d.%02d%02d",
1900+$year, 1+$mon, $mday, $hour, $min);
if ( -d "$resultbase/$tstamp") { # check for runs within a minute
my $tail = 'a';
while ( -d "$resultbase/$tstamp$tail" ) { $tail++; }
$tstamp .= $tail;
}
$params{TSTAMP} = $tstamp;
}
$resultdir = "$resultbase/$params{TSTAMP}";
$tmpdir = "$tmpbase/$params{TSTAMP}";
$resultstxt = "$resultdir/results.txt";
$resultshtml = "$resultdir/results.html";
mkdir ("$resultbase", 0775);
mkdir ("$tmpbase", 0775);
mkdir ("$resultdir", 0775);
mkdir ("$tmpdir", 0775);
# Make sure we have everything
die "Must specify the test time" unless $params{TIME};
die "Must specify a workload file" unless $params{WORKLOAD};
if ($params{TESTBED}) { # BACK COMPATIBILITY
readTestbedFile ($params{TESTBED}) || die "Error reading testbed: $@\n";
}
$testsecs = figureTimeSeconds ($params{TIME}, "seconds");
# figure out the processes and thread, given the desired number
# takes into account all the constraints. todo can be a float.
sub figurePT {
my $sec = shift;
my $todo = shift;
my $p = 1; # first guess
my $t = 1;
my $start = 1; # initial process guess
my $end = 250; # highest process guess
if ($todo < 1) { # mark this client as inactive
$sec->{PROCESSES} = 0;
$sec->{THREADS} = 0;
return 0;
}
if (($section->{MAXCLIENTS}) && ($todo > $section->{MAXCLIENTS})) {
$todo = $section->{MAXCLIENTS}; # trim to max client per host
}
if ($section->{PROCESSES}) { # they set this part already
$start = int ($section->{PROCESSES});
$end = $start;
$p = $start;
my $slist = $section->{sectionParams};
$slist =~ s/HOSTS=\s*//; # strip off initial bit
print "Using specified $p processes for clients $slist\n";
}
$end = int ($section->{MAXPROCESSES})
if ($section->{MAXPROCESSES}); # they set a max
if (($params{NT}) || ($section->{ARCH} eq "NT4.0")) {
$end = 1; # # NT is currently limited to 1 process
$start = 1;
$p = 1;
}
# step through some process counts
# it should first reduce errors due to MAXTHREADS,
# the it will reduce errors due to integer math.
# not optimal, just good enough
my $misses = 0;
for (my $n = $start; $n <= $end; $n++) { # try some process counts
my $tryt = int ($todo / $n);
if (($sec->{MAXTHREADS}) && ($tryt > $sec->{MAXTHREADS})) {
$tryt = $sec->{MAXTHREADS};
}
# see if this is a better match than the last one
if (abs ($todo - ($n * $tryt)) < abs ($todo - ($p * $t))) {
$p = $n;
$t = $tryt;
$misses = 0;
} else {
$misses++;
last if ($misses > 1); # getting worse
}
}
$sec->{PROCESSES} = $p;
$sec->{THREADS} = $t;
return $p * $t;
}
# Allocate CLIENTCOUNT to the client machines
# try NOT to turn this into a massive linear programming project
# works best to put bigger machines last
if ($params{CLIENTCOUNT}) {
my $todo = $params{CLIENTCOUNT};
my $softcli = 0; # how many can we play with
foreach $section (@workload) { # see which are already fixed
next unless ($section->{sectionTitle} =~ /CLIENT/o);
unless (($section->{PROCESSES}) && ($section->{THREADS})) {
$softcli++;
next;
}
my $slist = $section->{sectionParams};
$slist =~ s/HOSTS=\s*//; # strip off initial bit
my @hlist = split /[\s,]/, $slist;
my $hcnt = (1 + $#hlist);
# subtract fixed entries
my $tcount = ($section->{THREADS}) ? $section->{THREADS} : 1;
$todo -= $tcount * $section->{PROCESSES} * $hcnt;
$clientProcCount += $section->{PROCESSES} * $hcnt; # total processes
$params{DEBUG} &&
print "Fixed load group with $hcnt hosts: $section->{PROCESSES} x $tcount\n";
}
$params{DEBUG} &&
print "Allocating $todo clients over $softcli groups\n";
if ($softcli) {
foreach $section (@workload) {
next unless ($section->{sectionTitle} =~ /CLIENT/o);
next if (($section->{PROCESSES}) && ($section->{THREADS}));
my $slist = $section->{sectionParams};
$slist =~ s/HOSTS=\s*//; # strip off initial bit
my @hlist = split /[\s,]/, $slist;
my $hcnt = (1 + $#hlist);
#print "todo=$todo softcli=$softcli hcnt=$hcnt\n";
$todo -= $hcnt * figurePT ($section, $todo / ($softcli * $hcnt));
$clientProcCount += $hcnt * $section->{PROCESSES}; # total procs
$softcli--;
last if ($softcli <= 0); # should not happen
}
}
if ($todo) {
print "Warning: Could not allocate $todo of $params{CLIENTCOUNT} clients.\n";
$params{CLIENTCOUNT} -= $todo;
}
} else { # figure out the client count
my $cnt = 0;
foreach $section (@workload) { # see which are already fixed
next unless ($section->{sectionTitle} =~ /CLIENT/o);
next unless ($section->{PROCESSES});
my $slist = $section->{sectionParams};
$slist =~ s/HOSTS=\s*//; # strip off initial bit
my @hlist = split /[\s,]/, $slist;
my $hcnt = (1 + $#hlist);
# subtract fixed entries
my $tcount = ($section->{THREADS}) ? $section->{THREADS} : 1;
$cnt += $tcount * $section->{PROCESSES} * $hcnt;
$clientProcCount += $section->{PROCESSES} * $hcnt; # total processes
}
$params{CLIENTCOUNT} = $cnt;
die "No clients configured!\n" unless ($cnt > 0);
}
# This has to be written into save workload file for later processing
unless ($params{FREQUENCY}) { # unless frequency set on command line
my $chartp = ($params{CHARTPOINTS}) ? $params{CHARTPOINTS} : 464;
# approximate data points for good graphs (up to 2 times this)
$params{FREQUENCY} = int ($testsecs / $chartp);
if ($params{FREQUENCY} < 2) { # fastest is every 2 seconds
$params{FREQUENCY} = 2;
} elsif ($params{FREQUENCY} > 60) { # slowest is every minute
$params{FREQUENCY} = 60;
}
}
{ # set a unique block id on every section
my $id = 0;
my $configSeen = 0;
my $defaultSeen = 0;
foreach $section (@workload) {
if ($section->{"sectionTitle"} =~ /^CONFIG$/) {
next if $configSeen;
$configSeen++;
}
if ($section->{"sectionTitle"} =~ /^DEFAULT$/) {
next if $defaultSeen;
$defaultSeen++;
}
$id++; # number 1, 2, ...
if ($section->{"sectionTitle"} =~ /^(CONFIG|CLIENT)$/) {
$section->{BLOCKID} = $id;
} else {
push @{$section->{"lineList"}}, "blockID\t$id\n";
}
}
}
# Write the version we pass to mailclient
writeWorkloadFile ("$resultdir/work.wld", \@workload,
\@scriptWorkloadSections);
# Write the complete inclusive version
writeWorkloadFile ("$resultdir/all.wld", \@workload);
setConfigDefaults(); # pick up any missing defaults
unless ($#protocolsAll > 0) {
die "No protocols found. Test Failed!\n";
}
print "Starting: ", scalar(localtime), "\n";
# redirect STDERR
open SAVEERR, ">&STDERR";
open(STDERR, ">$resultdir/stderr") || warn "Can't redirect STDERR:$!\n";
$totalProcs = 0; # number of clients started
# iterate over every client in the testbed, complete the cmd and rsh
if ($params{NT}) { # single client on local host
pathprint ("Starting clients (errors logged to $resultdir/stderr)\n");
foreach $section (@workload) {
next unless ($section->{sectionTitle} =~ /CLIENT/o);
my $tcount = ($section->{THREADS}) ? $section->{THREADS} : 1;
# Build the initial Mailclient command line
my $preCmd = ($section->{COMMAND})
? $section->{COMMAND} : $params{CLIENTCOMMAND};
$preCmd .= " -s -t $params{TIME} -f $params{FREQUENCY}";
$preCmd .= " -d" if ($params{DEBUG});
$preCmd .= " -r" if ($params{TELEMETRY});
$preCmd .= " -R $params{RAMPTIME}" if ($params{RAMPTIME});
$preCmd .= " -m $params{MAXERRORS}" if ($params{MAXERRORS});
$preCmd .= " -M $params{MAXBLOCKS}" if ($params{MAXBLOCKS});
$preCmd .= " -n 1 -N $tcount";
$preCmd .= ($params{USEGROUPS} && $section->{GROUP})
? " -H $section->{GROUP}" : " -H $cli";
my $stdout = "$tmpdir/localhost.out";
$totalProcs += $tcount;
do 'makeindex.pl' || warn "$@\n"; # html index
printf "\nTest duration: %d %s. Rampup time: %d %s. Number of clients: %d\n",
figureTimeNumber ($params{TIME}),
figureTimeUnits ($params{TIME}, "seconds"),
figureTimeNumber ($params{RAMPTIME}),
figureTimeUnits ($params{RAMPTIME}, "seconds"),
$totalProcs;
print STDERR "localhost: cd $params{TEMPDIR}; $preCmd\n";
# Redirect STDIN, and STDOUT
#open SAVEIN, "<STDIN";
open STDIN, "<$resultdir/work.wld"
|| die "Coundn't open $resultdir/work.wld for input\n";
open SAVEOUT, ">&STDOUT";
open STDOUT, ">$stdout"
|| die "Couldnt open $stdout for output\n";
chdir $params{TEMPDIR} || die "Could not cd $params{TEMPDIR}: $!\n";
system $preCmd;
close STDOUT;
open STDOUT, ">&SAVEOUT";
printf "Test done.\n";
chdir $cwd || die "Could not cd $cwd: $!\n";
last; # only do the first one
}
} else { # not NT (forking works)
foreach $section (@workload) { # do pre run commands
next unless ($section->{sectionTitle} =~ /PRETEST/o);
unless ($section->{COMMAND}) {
print "PreTest with no Command for $section->{sectionParams}\n";
next;
}
my $slist = $section->{sectionParams};
$slist =~ s/HOSTS=\s*//; # strip off initial bit
my $myCmd = $section->{COMMAND};
$myCmd =~ s/%f/$params{FREQUENCY}/; # fill in frequency variable
if ($myCmd =~ m/%c/o) { # dont force down if count is used
$count = $testsecs / $params{FREQUENCY};
$myCmd =~ s/%c/$count/; # fill in count variable
}
my $rsh = ($section->{RSH}) ? $section->{RSH} : $params{RSH};
foreach $cli (split /[\s,]/, $slist) {
print "Running pre test command on $cli\n";
open PRE, ">>$resultdir/$cli-pre.log";
print PRE "========\n";
print PRE "$myCmd\n";
print PRE "========\n";
close PRE;
print STDERR "$cli: $myCmd\n"; # log the actual command
forkproc ($rsh, $cli, $myCmd,
"/dev/null", "$resultdir/$cli-pre.log");
}
foreach $cli (split /[\s,]/, $slist) {
wait(); # run multiple PRETEST section sequentially
}
}
foreach $section (@workload) { # start monitors
next unless ($section->{sectionTitle} =~ /MONITOR/o);
my $slist = $section->{sectionParams};
$slist =~ s/HOSTS=\s*//; # strip off initial bit
my $myCmd = ($section->{COMMAND})
? $section->{COMMAND} : $params{MONITORCOMMAND};
my $forceDown = 0;
$myCmd =~ s/,/ /g; # turn commas into spaces BACK COMPATIBIILITY
$myCmd =~ s/%f/$params{FREQUENCY}/; # fill in frequency variable
if ($myCmd =~ m/%c/o) { # dont force down if count is used
$count = $testsecs / $params{FREQUENCY};
$myCmd =~ s/%c/$count/; # fill in count variable
} else {
$forceDown = 1;
}
my $rsh = ($section->{RSH}) ? $section->{RSH} : $params{RSH};
foreach $cli (split /[\s,]/, $slist) {
printf "Monitoring on $cli\n";
open PRE, ">>$resultdir/$cli-run.log";
print PRE "========\n";
print PRE "$myCmd\n";
print PRE "========\n";
close PRE;
print STDERR "$cli: $myCmd\n"; # log the actual command
$pid = forkproc ($rsh, $cli, $myCmd,
"/dev/null", "$resultdir/$cli-run.log");
push @forceDownPids, $pid if ($forceDown); # save PID for shutdown
}
}
print "Starting clients (errors logged to $resultdir/stderr)\n";
foreach $section (@workload) {
next unless ($section->{sectionTitle} =~ /CLIENT/o);
next unless ($section->{PROCESSES}); # unused client
my $slist = $section->{sectionParams};
$slist =~ s/HOSTS=\s*//; # strip off initial bit
my $rsh = ($section->{RSH}) ? $section->{RSH} : $params{RSH};
my $pcount = $section->{PROCESSES};
my $tcount = ($section->{THREADS}) ? $section->{THREADS} : 0;
my $tempdir;
if ($section->{TEMPDIR}) {
$tempdir = $section->{TEMPDIR};
} elsif ($params{TEMPDIR}) {
$tempdir = $params{TEMPDIR};
}
my $preCmd = "./" . (($section->{COMMAND})
? $section->{COMMAND} : $params{CLIENTCOMMAND});
$preCmd .= " -s -t $params{TIME} -f $params{FREQUENCY}";
$preCmd .= " -d" if ($params{DEBUG});
$preCmd .= " -r" if ($params{TELEMETRY});
$preCmd .= " -R $params{RAMPTIME}" if ($params{RAMPTIME});
if ($params{MAXERRORS}) {
# distribute error count over processes, rounding up
my $n = int (($params{MAXERRORS} + $clientProcCount - 1)
/ $clientProcCount);
$n = 1 if ($n < 1);
$preCmd .= " -m $n";
}
if ($params{MAXBLOCKS}) {
# distribute block count over processes, rounding up
my $n = int (($params{MAXBLOCKS} + $clientProcCount - 1)
/ $clientProcCount);
$n = 1 if ($n < 1);
$preCmd .= " -M $n";
}
$preCmd = "cd $tempdir; " . $preCmd if ($tempdir);
$preCmd .= " -n $pcount";
$preCmd =~ s!/!\\!g if ($section->{ARCH} eq "NT4.0");
$preCmd =~ s/;/&&/g if ($section->{ARCH} eq "NT4.0");
foreach $cli (split /[\s,]/, $slist) {
my $stdout = getClientFilename ($cli, $section);
my $myCmd = $preCmd;
$myCmd .= ($params{USEGROUPS} && $section->{GROUP})
? " -H $section->{GROUP}" : " -H $cli";
if ($tcount) {
$myCmd .= " -N $tcount";
printf "Starting %d x %d on $cli\n", $pcount, $tcount;
$totalProcs += $pcount * $tcount;
} else {
printf "Starting %d processes on $cli\n", $pcount;
$totalProcs += $pcount;
}
print STDERR "$cli: $myCmd\n"; # log the actual command
$pid = forkproc ($rsh, $cli, $myCmd,
"$resultdir/work.wld", $stdout);
push @localPids, $pid if ($cli =~ /^localhost$/i);
}
}
if (@localPids) {
# print "Trapping extraneous local signals\n";
# This doesnt trap quite right. We dont die, but shell returns...
$SIG{ALRM} = 'IGNORE'; # in case we get an ALRM from the mailclient
}
printf "\nTest duration: %d %s. Rampup time: %d %s. Number of clients: %d\n",
figureTimeNumber ($params{TIME}),
figureTimeUnits ($params{TIME}, "seconds"),
figureTimeNumber ($params{RAMPTIME}),
figureTimeUnits ($params{RAMPTIME}, "seconds"),
$totalProcs;
do 'makeindex.pl' || warn "$@\n"; # html index
print "Waiting for test to finish.\n";
print "Waiting: ", scalar(localtime), "\n";
# wait for children to finish
$pid = wait();
if (@forceDownPids) { # shut down after the first return.
print "Shutting down @forceDownPids\n";
kill 1 => @forceDownPids; # sigHUP
# kill 9 => @forceDownPids; # sigTERM
}
while ($pid != -1) { # wait for all children
$pid = wait();
}
foreach $section (@workload) { # do post test commands
next unless ($section->{sectionTitle} =~ /POSTTEST/o);
unless ($section->{COMMAND}) {
print "PostTest with no command for $section->{sectionParams}\n";
next;
}
my $slist = $section->{sectionParams};
$slist =~ s/HOSTS=\s*//; # strip off initial bit
my $myCmd = $section->{COMMAND};
$myCmd =~ s/%f/$params{FREQUENCY}/; # fill in frequency variable
if ($myCmd =~ m/%c/o) { # dont force down if count is used
$count = $testsecs / $params{FREQUENCY};
$myCmd =~ s/%c/$count/; # fill in count variable
}
my $rsh = ($section->{RSH}) ? $section->{RSH} : $params{RSH};
foreach $cli (split /[\s,]/, $slist) {
printf "Running post test command on $cli\n";
open PRE, ">>$resultdir/$cli-post.log";
print PRE "========\n";
print PRE "$myCmd\n";
print PRE "========\n";
close PRE;
print STDERR "$cli: $myCmd\n"; # log the actual command
forkproc ($rsh, $cli, $myCmd,
"/dev/null", "$resultdir/$cli-post.log");
}
foreach $cli (split /[\s,]/, $slist) {
wait(); # run multiple POSTTEST section sequentially
}
}
}
print STDERR "\nDone.\n";
close(STDERR);
open STDERR, ">&SAVEERR";
print "\nClients done: ", scalar(localtime), "\n";
print "Collecting results\n";
do 'reduce.pl' || die "$@\n"; # generate graphs and sums
print "Generating results pages\n";
do 'report.pl' || die "$@\n";
# Now display that data to console
if ($params{VERBOSE}) {
fileShow ($resultstxt);
print "\n";
}
print "Processing done: ", scalar (localtime), "\n";
pathprint ("\nResults (text):\t$resultstxt\n");
pathprint ( "Results (HTML):\t$resultshtml\n");
print "Index of runs: \tfile://$cwd/$resultbase/index.html\n";
# Now check for major problems in the stderr file
if (open(RESULTSTXT, "$resultdir/stderr")) {
$ERRCNT=0;
while (<RESULTSTXT>) { $ERRCNT++; }
close(RESULTSTXT);
pathprint ("Error log ($ERRCNT lines):\t$resultdir/stderr\n");
}
{ # list user requested logging
my @logfiles = <$resultdir/*-pre.log>;
if (@logfiles) {
foreach $f (@logfiles) {
print "Pre test log: \t$f\n";
}
}
@logfiles = <$resultdir/*-run.log>;
if (@logfiles) {
foreach $f (@logfiles) {
print "Monitoring log: \t$f\n";
}
}
@logfiles = <$resultdir/*-post.log>;
if (@logfiles) {
foreach $f (@logfiles) {
print "Post test log: \t$f\n";
}
}
}
print "Mailmaster done: ", scalar(localtime), "\n"; exit 0;

Просмотреть файл

@ -1,115 +0,0 @@
#!/usr/bin/perl
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Netscape Mailstone utility,
# released March 17, 2000.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1997-2000 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Dan Christian <robodan@netscape.com>
# Marcel DePaolis <marcel@netcape.com>
#
# Alternatively, the contents of this file may be used under the
# terms of the GNU Public License (the "GPL"), in which case the
# provisions of the GPL are applicable instead of those above.
# If you wish to allow use of your version of this file only
# under the terms of the GPL and not to allow others to use your
# version of this file under the NPL, indicate your decision by
# deleting the provisions above and replace them with the notice
# and other provisions required by the GPL. If you do not delete
# the provisions above, a recipient may use your version of this
# file under either the NPL or the GPL.
#####################################################
# usage: perl -Ibin makeindex.pl
# Look at all the results files and create a top level index
unless ($resultbase) { # pick up systematic defaults, if needed
do 'args.pl'|| die $@;
parseArgs(); # parse command line
}
($testname = $params{WORKLOAD}) =~ s:conf/::;
$testname =~ s:.wld::;
my $entry = "";
$entry .= "<TR><TD><BR><A HREF=\"$params{TSTAMP}/results.html\">$params{TSTAMP}</A></TD>";
$entry .= "<TD>$testname</TD>\n";
$entry .= "<TD>$params{TITLE}</TD>\n";
$entry .= "<TD>$params{TIME}</TD>\n";
$entry .= "<TD>$params{CLIENTCOUNT}</TD>\n";
$entry .= "<TD><A HREF=\"$params{TSTAMP}/all.wld\">workload</A></TD>\n";
$entry .= "<TD><A HREF=\"$params{TSTAMP}/stderr\">stderr</A></TD></TR>\n";
if (-r "$resultbase/index.html") {
fileInsertAfter ("$resultbase/index.html",
"^<!-- INSERT TAGS HERE",
$entry);
} else { # create index from scratch
system ("cd $resultbase; ln -s ../doc .");
open(INDEXNEW, ">$resultbase/index.new") ||
die "Couldn't open $resultbase/index.new: $!";
print INDEXNEW <<END;
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<TITLE>
MailStone Results
</TITLE>
<HEAD>
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000FF" VLINK="#FF0000" ALINK="#000088">
<A HREF=$mailstoneURL>Mailstone documentation</A><BR>
<TABLE BORDER=2>
<CAPTION> Netscape MailStone Results Index </CAPTION>
<TR>
<TH>Run</TH> <TH>Testname</TH> <TH> Title </TH>
<TH>Duration</TH> <TH>Clients</TH> <TH>Details</TH> <TH>Error log</TH>
</TR>
<!-- INSERT TAGS HERE - DO NOT DELETE THIS LINE -->
END
print INDEXNEW $entry; # put in this entry
# Add in any existing entries
# get a list of all the results files
@resall = <$resultbase/*/results.html>;
# Write out all the links
# This could be rather slow, but we only do it when index.html is missing
foreach $filefull (reverse @resall) {
my $file = $filefull;
$file =~ s:$resultbase/::;
if ($file eq $params{TSTAMP}) { next; } # written above
my $dir = $file;
$dir =~ s:/results.html::;
# dont read in old workloads, it will override the current one
print INDEXNEW "<TR><TD><BR><A HREF=\"$file\">$dir</A></TD>\n";
print INDEXNEW "<TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>\n";
print INDEXNEW "<TD><A HREF=\"$dir/all.wld\">workload</A></TD>\n";
print INDEXNEW "<TD><A HREF=\"$dir/stderr\">stderr</A></TD></TR>\n";
}
print INDEXNEW <<END;
</TABLE>
</BODY>
</HTML>
END
close (INDEXNEW);
fileBackup ("$resultbase/index.html");
rename ("$resultbase/index.new", "$resultbase/index.html");
print "Created $resultbase/index.html\n";
}
return 1;

Просмотреть файл

@ -1,414 +0,0 @@
#!/usr/bin/perl
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Netscape Mailstone utility,
# released March 17, 2000.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1997-2000 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Dan Christian <robodan@netscape.com>
# Marcel DePaolis <marcel@netcape.com>
#
# Alternatively, the contents of this file may be used under the
# terms of the GNU Public License (the "GPL"), in which case the
# provisions of the GPL are applicable instead of those above.
# If you wish to allow use of your version of this file only
# under the terms of the GPL and not to allow others to use your
# version of this file under the NPL, indicate your decision by
# deleting the provisions above and replace them with the notice
# and other provisions required by the GPL. If you do not delete
# the provisions above, a recipient may use your version of this
# file under either the NPL or the GPL.
#####################################################
# script to create test user accounts for Netscape Messaging Server 3, 4
#
# Given a set of parameters, this script will create an LDIF file
# for a number of email users of the form:
# test1, test2, test3, ...
#
# usage: perl create_accounts_ldif [users] [broadcast] [postmaster] [ options ]
# [ -a allUsersAlias ]
# [ -b basedn ]
# [ -d maildomain ]
# [ -f firstaccount ]
# [ -k ]
# [ -m mailhost ]
# [ -n numaccounts ]
# [ -o outputfile ]
# [ -p password ]
# [ -s storebase ]
# [ -u username ]
# [ -v ]
# [ -w workload ]
# [ -x maxstores ]
# [ -3 ]
#
#perl -Ibin -- bin/makeusers.pl -d mailhost.example.com -m mailhost.example.com -b 'o=example.com' -u mailhost-test -n 100 -4 -o mailhost100.ldif
# Create the ldif for the user accounts and/or broadcast, postmaster account.
#
# The ldif then must be added to
# the directory by hand (ldapadd, or through the dir admin server's
# Database Mgmt->Add entries from an ldif file).
# A faster way
# is to export the existing directory, append the results of
# this script, and re-import the combined file. This can be
# done using the following Netscape Directory Server commands:
# stop-slapd
# db2ldif outputfile
# [ merge files ]
# ldif2db inputfile # for DS4 you would typically use -noconfig
# start-sladp
#
print "Netscape Mailstone.\nCopyright (c) 1998,1999 Netscape Communications Corp.\n";
# server to be used in the internet mail address of the users
$domain = "newdomain.example.net";
# machine that will act as the user's mailhost
$mailhost = "mailhost.example.net";
# base dn for the user entries, e.g. o=Ace Industry,c=US
$basedn = "o=Benchmark Lab, c=US";
# name of broadcast account
$bcastacct = "allusers";
# name of broadcast account
$postmasteraddr = "root\@localhost";
# base name to build user names, will construct test0, test1, ...
$username = "test%ld";
# user passwds, in SHA format, the passwd below is 'netscape'
#$userpassword = "{SHA}aluWfd0LYY9ImsJb3h4afrI4AXk=";
# these can also be imported as cleartext
$userpassword = "netscape";
# 0: no numbered passwords, 1: number with userID
$maxpass = 0;
# first account to use
$firstaccount = 0;
# number of user accounts to create ($first - $first+$num-1)
$numaccounts = 1_000;
# For larger systems, spreading the users over multiple partitions
# is usually a good idea. This example assumes you have
# created partitions named p0, p1, etc.
# store partition base name
$storebase = "p%ld";
# max store number (0 - maxstores-1), skip if 0
$maxstores = 0;
#default to msg 4 schemas
$usemsg4schema = 1;
#default to writing to stdout
$outfile = STDOUT;
# Initial UID for genpasswd
$firstuid = 1000;
sub usage {
print "Usage: perl -Ibin -- makeusers [users] [broadcast] [postmaster]\n";
print "\t[ -w workload ] [ -o outputFile ]\n";
print "\t[ -d mailDomain ] [ -m mailHost ] [ -b baseDN ]\n";
print "\t[ -u username ] [ -f firstAccount ] [ -n numAccounts ]\n";
print "\t[ -p password ] [ -k ]\n";
print "\t[ -s storeBase ] [ -x numStores ]\n";
print "\t[ -a allUsersAlias ] [ -t postmasterAddress ]\n";
print "\t[ -3 ]|[ -4 ]\n";
}
sub readWorkConfig { # read the workload in, parse our params
my $workloadfile = shift || die "Workload file name expected\n";
do 'args.pl'|| die $@;
readWorkloadFile ($workloadfile, \@workload)
|| die "Error reading workload: $@\n";
# assign all the parameters from the config
$mailhost = $defaultSection->{SERVER}
if ($defaultSection->{SERVER});
if ($defaultSection->{ADDRESSFORMAT}) {
my $addr = $defaultSection->{ADDRESSFORMAT};
$addr =~ s/^.*@//;
$domain = $addr;
}
if ($defaultSection->{LOGINFORMAT}) {
my $user = $defaultSection->{LOGINFORMAT};
#$user =~ s/%ld$//;
$username = $user;
}
$numaccounts = $defaultSection->{NUMLOGINS}
if ($defaultSection->{NUMLOGINS});
$firstaccount = $defaultSection->{FIRSTLOGINS}
if ($defaultSection->{FIRSTLOGINS});
$userpassword = $defaultSection->{PASSWDFORMAT}
if ($defaultSection->{SERVER});
if ($userpassword =~ m/%ld/) { # see if numbered passwords
$maxpass++;
#$userpassword =~ s/%ld//g;
}
# what isnt set: basedn, storebase, maxstores, usemsg4schema
}
while (@ARGV) {
$arg = shift(@ARGV);
if ($arg =~ /^-a$/i) { # allusers (broadcast) user name
$bcastacct = shift(@ARGV);
next;
}
if ($arg =~ /^-b$/i) { # LDAP base DN
$basedn = shift(@ARGV);
next;
}
if ($arg =~ /^-d$/i) { # mail domain
$domain = shift(@ARGV);
next;
}
if ($arg =~ /^-f$/i) { # initial account
$firstaccount = shift(@ARGV);
next;
}
if ($arg =~ /^-k$/i) { # use numbered passwords
$maxpass++;
next;
}
if ($arg =~ /^-h$/i) { # help
usage();
exit 0;
}
if ($arg =~ /^-m$/i) { # mail server name
$mailhost = shift(@ARGV);
next;
}
if ($arg =~ /^-n$/i) { # number of accounts
$numaccounts = shift(@ARGV);
next;
}
if ($arg =~ /^-o$/i) { # name output file
my $fname = shift || die "File name expected\n";
open OUTFILE, ">$fname" || die "Error opening file $@\n";
$outfile = OUTFILE;
next; # use msg4 user admin schema
}
if ($arg =~ /^-p$/i) { # password
$userpassword = shift(@ARGV);
next;
}
if ($arg =~ /^-s$/i) { # base name for above
$storebase = shift(@ARGV);
next;
}
if ($arg =~ /^-t$/i) { # postmaster address
$postmasteraddress = shift(@ARGV);
next;
}
if ($arg =~ /^-u$/i) { # user name base
$username = shift(@ARGV);
next;
}
if ($arg =~ /^-v$/i) { # be verbose
$verbose++;
next;
}
# do this when read, so that later switches can override
if ($arg =~ /^-w$/i) { # get a workload file
readWorkConfig (shift(@ARGV));
next;
}
if ($arg =~ /^-x$/i) { # number of partitions (0 to skip)
$maxstores = shift(@ARGV);
next;
}
if ($arg =~ /^-3$/) { # no msg4 schema
$usemsg4schema = 0;
next;
}
if ($arg =~ /^-4$/) { # use msg4 user admin schema
$usemsg4schema = 1;
next;
}
if ($arg =~ /^users$/i) {
$genusers++;
next;
}
if ($arg =~ /^broadcast$/i) {
$genbroadcast++;
next;
}
if ($arg =~ /^passwd$/i) {
$genpasswd++;
next;
}
if ($arg =~ /^postmaster$/i) {
$genpostmaster++;
next;
}
print STDERR "Unknown argument $arg. Use -h for help.\n";
exit 1;
}
unless (($genusers) || ($genbroadcast) || ($genpasswd) || ($genpostmaster)) {
print STDERR "Must specify mode [users] [broadcast] [postmaster] ...\n";
usage();
exit 0;
}
# specify number fields, if needed
unless ($username =~ /%ld/) {
$username .= '%ld';
}
if (($maxpass) && !($userpassword =~ /%ld/)) {
$userpassword .= '%ld';
}
if (($maxstores) && !($storename =~ /%ld/)) {
$storename .= '%ld';
}
if ($verbose) {
print STDERR "Here is the configuration:\n";
print STDERR "baseDN='$basedn' \t";
print STDERR (($usemsg4schema) ? "-4\n" : "-3\n");
print STDERR "mailHost='$mailhost' \tdomain='$domain'\n";
print STDERR "userName='$username' \tnumAccounts=$numaccounts \tfirstAccount=$firstaccount\n";
print STDERR "userPassword='$userpassword'\n";
print STDERR "allUsersAccount='$bcastacct'\n" if ($genbroadcast);
print STDERR "postmasterAddress='$postmasterAddress'\n" if ($genpostmaster);
}
if ($genusers) { # Create the user accounts
$storenum=0;
for ($i = $firstaccount; $i < $firstaccount+$numaccounts; $i++) {
# build user account name
my $acctname = $username;
$acctname =~ s/%ld/$i/; # insert user number
my $password = $userpassword;
$password =~ s/%ld/$i/; # insert user number
# MAKE SURE THERE ARE NO TRAILING SPACES IN THE LDIF
my $extradata = "";
if ($maxstores > 0) { # assign them to a store
my $storename = $storebase;
$storename =~ s/%ld/$storenum/;
$extradata .= "mailmessagestore: $storename\n";
$storenum++;
$storenum=0 if ($storenum >= $maxstores);
}
$extradata .= "objectclass: nsMessagingServerUser\n"
if ($usemsg4schema);
print $outfile <<END;
dn: uid=$acctname, $basedn
userpassword: $password
givenname: $acctname
sn: $acctname
cn: $acctname
uid: $acctname
mail: $acctname\@$domain
mailhost: $mailhost
maildeliveryoption: mailbox
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
objectclass: mailRecipient
$extradata
END
}
}
if ($genbroadcast) { # Create the broadcast account
# MAKE SURE THERE ARE NO TRAILING SPACES IN THE LDIF
my $password = $userpassword;
$password =~ s/%ld//; # strip user number
# initial part
print $outfile <<END;
dn: uid=$bcastacct, $basedn
userpassword: $password
givenname: $bcastacct
sn: $bcastacct
cn: $bcastacct
uid: $bcastacct
mail: $bcastacct\@$domain
mailhost: $mailhost
maildeliveryoption: forward
END
# now put in each address
for ($i = $firstaccount; $i < $firstaccount+$numaccounts; $i++) {
# build user account name
my $acctname = $username;
$acctname =~ s/%ld/$i/; # insert user number
print $outfile "mailforwardingaddress: $acctname\@$domain\n";
}
# final part
print $outfile <<END;
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
objectclass: mailRecipient
END
}
if ($genpostmaster) { # Create the postmaster account
# MAKE SURE THERE ARE NO TRAILING SPACES IN THE LDIF
print $outfile <<END;
dn: cn=postmaster, $basedn
cn: postmaster
mail: postmaster\@$domain
mailalternateaddress: postmaster\@$mailhost
mgrprfc822mailmember: $postmasterAddress
objectclass: top
objectclass: mailGroup
objectclass: groupOfUniqueNames
END
}
# mixing passwd output with the ldif output above would be quite silly
if ($genpasswd) { # Create passwd entries for makeusers
for ($i = $firstaccount; $i < $firstaccount+$numaccounts; $i++) {
# build user account name
my $acctname = $username;
$acctname =~ s/%ld/$i/; # insert user number
my $password = $userpassword;
$password =~ s/%ld/$i/; # insert user number
my $uid = $firstuid + $i;
print $outfile "$acctname:$password:$uid:$uid:Mail user $acctname:/home/$acctname:/bin/sh\n";
}
}
exit 0;

Просмотреть файл

@ -1,158 +0,0 @@
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Netscape Mailstone utility,
# released March 17, 2000.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1997-2000 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Dan Christian <robodan@netscape.com>
# Marcel DePaolis <marcel@netcape.com>
#
# Alternatively, the contents of this file may be used under the
# terms of the GNU Public License (the "GPL"), in which case the
# provisions of the GPL are applicable instead of those above.
# If you wish to allow use of your version of this file only
# under the terms of the GPL and not to allow others to use your
# version of this file under the NPL, indicate your decision by
# deleting the provisions above and replace them with the notice
# and other provisions required by the GPL. If you do not delete
# the provisions above, a recipient may use your version of this
# file under either the NPL or the GPL.
#####################################################
# This define the structures that hold summary, client, and graph data,
# This sets the names used for display. Can be internationalized.
# All top level names are here (both timers and scalars).
# Any unlisted names will map to themselves.
%timerNames
= (
#internal name, Printed name
"total", "total",
"conn", "connect",
"reconn", "reconnect",
"banner", "banner",
"login", "login",
"cmd", "command",
"submit", "submit",
"retrieve", "retrieve",
"logout", "logout",
"idle", "idle",
"connections", "connections",
"blocks", "blocks",
);
# This sets the names used for display. Can be internationalized.
%fieldNames
= (
#internal name, Printed name
"Try", "Try",
"Error", "Error",
"BytesR", "BytesR",
"BytesW", "BytesW",
"Time", "Time",
"TimeMin", "TMin",
"TimeMax", "TMax",
"Time2", "TStd",
);
# hold time graphs for each protocol
%graphs = ();
# Totals are done during plotting, if needed
%finals = (); # create base finals hash
# These are sections that dont get passed to mailclient (case insensitive)
@scriptWorkloadSections
= (
"Config", # special, references %params
"Client", # testbed client(s)
"Graph", # graph generation
"Setup", # things to run with ./setup
"Startup", # things to run before test
"Monitor", # other performance monitoring
"PreTest", # things to run before test
"PostTest", # things to run after test
);
# These are sections that arent protocols. Anything else must be.
@nonProtocolSections
= (@scriptWorkloadSections, ("Default"));
# These are the known workload parameters (as they will print)
# These are coerced to upper case internally (do NOT internationize)
@workloadParameters
= (
"addressFormat",
"arch",
"blockID",
"blockTime",
"chartHeight",
"chartPoints",
"chartWidth",
"clientCount",
"command",
"comments",
"file",
"firstAddress",
"firstLogin",
"frequency",
"gnuplot",
"group",
"idleTime",
"leaveMailOnServer",
"loginFormat",
"loopDelay",
"numAddresses",
"numLogins",
"numLoops",
"numRecips",
"mailClient",
"maxBlocks",
"maxClients",
"maxErrors",
"maxThreads",
"maxProcesses",
"passwdFormat",
"processes",
"rampTime",
"rcp",
"rsh",
"sequentialAddresses",
"sequentialLogins",
"server",
"smtpMailFrom",
"sysConfig",
"threads",
"telemetry",
"tempDir",
"time",
"title",
"TStamp",
"useAuthLogin",
"useEHLO",
"weight",
"wmapBannerCmds",
"wmapClientHeader",
"wmapInBoxCmds",
"wmapLoginCmd",
"wmapLoginData",
"wmapLogoutCmds",
"wmapMsgReadCmds",
"wmapMsgWriteCmds",
"workload",
);
return 1;

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,605 +0,0 @@
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Netscape Mailstone utility,
# released March 17, 2000.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1997-2000 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Dan Christian <robodan@netscape.com>
# Marcel DePaolis <marcel@netcape.com>
#
# Alternatively, the contents of this file may be used under the
# terms of the GNU Public License (the "GPL"), in which case the
# provisions of the GPL are applicable instead of those above.
# If you wish to allow use of your version of this file only
# under the terms of the GPL and not to allow others to use your
# version of this file under the NPL, indicate your decision by
# deleting the provisions above and replace them with the notice
# and other provisions required by the GPL. If you do not delete
# the provisions above, a recipient may use your version of this
# file under either the NPL or the GPL.
#####################################################
# This file deals with the summary data only
# Should be packages
do 'genplot.pl' || die "$@\n";
sub walkSetupTotals {
my $a = shift; my $f = shift; my $p = shift;
if ($p =~ /(\w+):(\w+):$/) {
my $tm = $2;
if (!($finals{Total}->{$tm}->{$f})) {
$finals{Total}->{$tm}->{$f} = $a;
} elsif ($f =~ /Min$/) {
$finals{Total}->{$tm}->{$f} = $a
if (($a > 0.0) && ($a < $finals{Total}->{$tm}->{$f}));
} elsif ($f =~ /Max$/) {
$finals{Total}->{$tm}->{$f} = $a if ($a > $finals{Total}->{$tm}->{$f});
} else {
$finals{Total}->{$tm}->{$f} += $a;}
}
elsif ($p =~ /(\w+):$/) {
$finals{Total}->{$f} += $a;
}
}
sub setupTotals {
# Figure out combined timers for "Total" protocol
# We might do a smarter merge here (look at context and try to match order)
# As long as the first protocol is a superset, it wont matter
my @tnames;
foreach $proto (@protocols) {
foreach $n (@{$protocolFields{$proto}}) {
my $t = $n;
$t =~ s/([][{}*+?^.\/])/\\$1/g; # quote regex syntax
my $found = 0;
foreach $tn (@tnames) { # see if it is in the list already
next unless ($tn =~ /$t/);
$found = 1;
last;
}
#print "proto $proto: Found $n\n" if ($found > 0);
next if ($found > 0);
#print "proto $proto: Add $n\n";
push @tnames, $n; # add to list
}
}
#print "'Total' timers @tnames\n";
$protocolFields{"Total"} = \@tnames;
# Create "Total" hashes
$finals{Total} = ArrayInstance->new();
foreach $n (@{$protocolFields{"Total"}}) { # all timers
my $t = $n; # dont modify original list
if ($t =~ /^\[(\w+)\]$/) { # Timer case, strip off brackets
$finals{Total}->{$1} = ArrayInstance->new();
#print "Creating Total timer field $1\n";
} else { # scalar
$finals{Total}->{$n} = 0;
#print "Creating Total scalar field $n\n";
}
}
# Total finals array
foreach $proto (@protocols) {
foreach $t (@{$protocolFields{$proto}}) {
if ($t =~ /^\[(\w+)\]$/) { # Timer case, strip off brackets
my $tm = $1;
foreach $f (@timerFieldsAll) {
my $a = $finals{$proto}->{$tm}->{$f};
if (!($finals{Total}->{$tm}->{$f})) { # never touched
$finals{Total}->{$tm}->{$f} = $a;
} elsif ($f =~ /Min$/) {
$finals{Total}->{$tm}->{$f} = $a
if (($a > 0.0)
&& ($a < $finals{Total}->{$tm}->{$f}));
} elsif ($f =~ /Max$/) {
$finals{Total}->{$tm}->{$f} = $a
if ($a > $finals{Total}->{$tm}->{$f});
} else {
$finals{Total}->{$tm}->{$f} += $a;
}
}
} else {
$finals{Total}->{$t} += $finals{$proto}->{$t};
}
}
}
# Convert Time2 to standard deviation
foreach $proto (@protocolsAll) {
foreach $n (@{$protocolFields{$proto}}) {
my $t = $n; # dont modify original list
if ($t =~ /^\[(\w+)\]$/) { $t = $1; } # strip off brackets
next unless ($finals{$proto}->{$t}); # proto doesnt have timer
next unless ($finals{$proto}->{$t}->{Try});
next unless ($finals{$proto}->{$t}->{Time2} > 0);
my $ss = $finals{$proto}->{$t}->{Time2};
my $tot = $finals{$proto}->{$t}->{Time};
my $n = $finals{$proto}->{$t}->{Try};
next unless ($n > 0); # skip if this is 0
my $var = ($ss - (($tot * $tot) / $n)) / $n;
print "$proto->$t var < 0: Time2=$ss Time=$tot n=$n\n"
if ($var < 0);
$finals{$proto}->{$t}->{Time2} = ($var > 0) ? sqrt ($var) : 0.0;
}
}
# Divide total times by trys to get averate time
foreach $proto (@protocolsAll) {
foreach $n (@{$protocolFields{$proto}}) {
my $t = $n; # dont modify original list
if ($t =~ /^\[(\w+)\]$/) { $t = $1; } # strip off brackets
next unless ($finals{$proto}->{$t}); # proto doesnt have timer
($finals{$proto}->{$t}->{Try}) || next;
$finals{$proto}->{$t}->{Time} /= $finals{$proto}->{$t}->{Try}
}
}
}
# The text version is designed to be machine processable
# commify and kformat are not used
sub genTextReport {
fileBackup ($resultstxt); # if processing as we go, backup old file
# Open a text file to hold the results
open(RESULTSTXT, ">$resultstxt") ||
die "Couldn't open $resultstxt: $!";
# Store results as text
printf RESULTSTXT "---- Netscape MailStone Results $params{TSTAMP} ----\n";
printf RESULTSTXT "\t\t%s\n", $params{TITLE};
printf RESULTSTXT "\t\t%s\n", $params{COMMENTS};
printf RESULTSTXT "\n";
printf RESULTSTXT "Test duration: %d %s. Rampup: %d %s. Reported duration %s seconds\n",
figureTimeNumber ($params{TIME}),
figureTimeUnits ($params{TIME}, "minutes"),
figureTimeNumber ($params{RAMPTIME}),
figureTimeUnits ($params{RAMPTIME}, "seconds"), $realTestSecs;
printf RESULTSTXT "Number of reporting clients: %s of %s\n",
$reportingClients, $totalProcs;
foreach $proto (@protocolsAll) {
# do op counters
printf RESULTSTXT "\n%-15s ", $proto;
foreach $f (@timerFieldsAll) {
#($f =~ m/^Time2$/o) && next;
printf RESULTSTXT "%13s",
($fieldNames{$f}) ? $fieldNames{$f} : $f;
}
foreach $n (@{$protocolFields{$proto}}) {
my $t = $n; # dont modify original list
unless ($t =~ /^\[(\w+)\]$/) { # scalar case
#next; # skip scalars for now
# do scalar counters. Column should line up with "Try"
printf RESULTSTXT "\n%-15s ",
$proto . ":" . (($timerNames{$t}) ? $timerNames{$t} : $t);
printf RESULTSTXT
"%13s", $finals{$proto}->{$t};
next;
} else { # strip off brackets
$t = $1;
}
printf RESULTSTXT "\n%-15s ",
$proto . ":" . (($timerNames{$t}) ? $timerNames{$t} : $t);
foreach $f (@timerFieldsAll) {
#($f =~ m/^Time2$/o) && next;
if ($f =~ m/Time/o) {
printf RESULTSTXT
"%13.3f", $finals{$proto}->{$t}->{$f};
} elsif ($f =~ m/Bytes/o) {
printf RESULTSTXT
"%13d", $finals{$proto}->{$t}->{$f};
} else {
printf RESULTSTXT
"%13s", $finals{$proto}->{$t}->{$f};
}
}
}
# do ops/sec
printf RESULTSTXT "\n\n%-15s ", $proto;
foreach $f (@timerFieldsAll) {
($f =~ m/^Time/o) && next;
printf RESULTSTXT "%9s/sec",
($fieldNames{$f}) ? $fieldNames{$f} : $f;
}
foreach $n (@{$protocolFields{$proto}}) {
my $t = $n; # dont modify original list
unless ($t =~ /^\[(\w+)\]$/) { # scalar case
#next; # skip scalars for now
# do scalar counter/sec. Column should line up with "Try"
printf RESULTSTXT "\n%-15s ",
$proto . ":" . (($timerNames{$t}) ? $timerNames{$t} : $t) . "/s";
printf RESULTSTXT
"%13.3f", $finals{$proto}->{$t} / $realTestSecs;
next;
} else {
$t = $1;
}
printf RESULTSTXT "\n%-15s ",
$proto . ":" . (($timerNames{$t}) ? $timerNames{$t} : $t) . "/s";
foreach $f (@timerFieldsAll) {
($f =~ m/^Time/o) && next;
if ($f =~ m/Bytes/o) {
printf RESULTSTXT
"%13d",
$finals{$proto}->{$t}->{$f} / $realTestSecs;
} else {
printf RESULTSTXT
"%13.3f",
$finals{$proto}->{$t}->{$f} / $realTestSecs;
}
}
}
printf RESULTSTXT "\n\n";
}
if ($params{SYSCONFIG}) {
print RESULTSTXT "\nSytem config details\n";
if (($params{SYSCONFIG} =~ m/^\S+$/o)
&& (open(SCFILE, "<$params{SYSCONFIG}"))) {
while (<SCFILE>) {
(m/^<\S+>\s*$/o) && next; # skip HTML only on them
s/<\S+>//g; # trim out obvious HTML commands
s/<!--.*-->//g; # trim out HTML comments
print RESULTSTXT $_;
}
close(SCFILE);
} else {
my $l = $params{SYSCONFIG}; # filter similar to above
$l =~ s/<\S+>//g; # trim out obvious HTML commands
$l =~ s/<!--.*-->//g; # trim out HTML comments
$l =~ s/\\\n/\n/g; # turn quoted newline to plain newline
print RESULTSTXT $l;
}
}
close(RESULTSTXT);
}
# Write the main part of the HTML page
sub genHTMLReportStart {
fileBackup ($resultshtml); # if processing as we go, backup old file
# Open an html file to hold the results
open(RESULTSHTML, ">$resultshtml") ||
die "Couldn't open $resultshtml: $!";
print RESULTSHTML <<END;
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<A NAME=TitleSection>
<TITLE>
Netscape MailStone Results $params{TSTAMP}
</TITLE>
</A>
<HEAD>
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000FF" VLINK="#FF0000" ALINK="#000088">
<CENTER>
<HR NOSHADE WIDTH="100%">
<H1>Netscape MailStone Results $params{TSTAMP}</H1>
<H2>$params{TITLE}</H2>
<I>$params{COMMENTS}</I>
<HR WIDTH="100%">
</CENTER>
END
printf RESULTSHTML "<BR><B>Test duration:</B> %d %s. ",
figureTimeNumber ($params{TIME}),
figureTimeUnits ($params{TIME}, "minutes");
printf RESULTSHTML "<B>Rampup:</B> %d %s. ",
figureTimeNumber ($params{RAMPTIME}),
figureTimeUnits ($params{RAMPTIME}, "seconds");
printf RESULTSHTML "<B>Reported duration:</B> %s seconds\n",
commify ($realTestSecs);
printf RESULTSHTML "<BR><B>Reporting clients:</B> %s of %s\n",
commify ($reportingClients), commify ($totalProcs);
print RESULTSHTML <<END;
<BR>
Test <A HREF="all.wld">complete workload</a> description.
Filtered <A HREF="work.wld">workload</a> description.
<BR>
Plain <A HREF="results.txt">text version</a> of results.
Log of <A HREF="stderr">stderr</a> and debugging output.
<BR>
<A NAME=MonitoringSection></A>
END
{ # list user requested logging
my @logfiles = <$resultdir/*-pre.log>;
if (@logfiles) {
foreach $f (@logfiles) {
$f =~ s/$resultdir\///o; # strip directory out
$f =~ s/-pre\.log$//o; # strip extension off
print RESULTSHTML "Pre test log: <A HREF=\"$f-pre.log\">$f</a><BR>\n";
}
}
@logfiles = <$resultdir/*-run.log>;
if (@logfiles) {
foreach $f (@logfiles) {
$f =~ s/$resultdir\///o; # strip directory out
$f =~ s/-run\.log$//o; # strip extension off
print RESULTSHTML "Monitoring log: <A HREF=\"$f-run.log\">$f</a><BR>\n";
}
}
@logfiles = <$resultdir/*-post.log>;
if (@logfiles) {
foreach $f (@logfiles) {
$f =~ s/$resultdir\///o; # strip directory out
$f =~ s/-post\.log$//o; # strip extension off
print RESULTSHTML "Post test log: <A HREF=\"$f-post.log\">$f</a><BR>\n";
}
}
}
#print RESULTSHTML
#"<CENTER><H2>Results per protocol</H2></CENTER>\n";
foreach $proto (@protocolsAll) {
printf RESULTSHTML "<A NAME=%sTable></A>\n", $proto;
printf RESULTSHTML
"<TABLE BORDER=2 CELLSPACING=2 CELLPADDING=2 COLS=%d WIDTH=\"95%%\">",
2+$#{@{$protocolFields{$proto}}};
print RESULTSHTML
"<CAPTION>$proto Counters</CAPTION>\n";
# do op counters
print RESULTSHTML
"<TR><TH>$proto</TH>\n";
foreach $f (@timerFieldsAll) {
#($f =~ m/^Time2$/o) && next;
printf RESULTSHTML "<TH>%s</TH> ",
($fieldNames{$f}) ? $fieldNames{$f} : $f;
}
print RESULTSHTML
"</TR>\n";
foreach $n (@{$protocolFields{$proto}}) {
my $t = $n; # dont modify original list
unless ($t =~ /^\[(\w+)\]$/) { # scalar case
next; # skip scalars for now
# do scalar counters. Column should line up with "Try"
printf RESULTSHTML "<TR ALIGN=RIGHT><TH>%s</TH>\n",
($timerNames{$t}) ? $timerNames{$t} : $t;
printf RESULTSHTML
"<TD>%s</TD> ",
commify ($finals{$proto}->{$t});
next;
} else {
$t = $1;
}
printf RESULTSHTML "<TR ALIGN=RIGHT><TH>%s</TH>\n",
($timerNames{$t}) ? $timerNames{$t} : $t;
foreach $f (@timerFieldsAll) {
#($f =~ m/^Time2$/o) && next;
if ($f =~ m/Time/o) {
printf RESULTSHTML
"<TD>%s</TD> ",
tformat ($finals{$proto}->{$t}->{$f});
} elsif ($f =~ m/Bytes/o) {
printf RESULTSHTML
"<TD>%s</TD> ",
kformat ($finals{$proto}->{$t}->{$f});
} else {
printf RESULTSHTML
"<TD>%s</TD> ",
commify ($finals{$proto}->{$t}->{$f});
}
}
print RESULTSHTML "</TR>\n";
}
# do ops/sec
print RESULTSHTML
"<TR><TH>$proto</TH>\n";
foreach $f (@timerFieldsAll) {
($f =~ m/^Time/o) && next;
printf RESULTSHTML "<TH>%s/sec</TH> ",
($fieldNames{$f}) ? $fieldNames{$f} : $f;
}
print RESULTSHTML
"</TR>\n";
foreach $n (@{$protocolFields{$proto}}) {
my $t = $n; # dont modify original list
unless ($t =~ /^\[(\w+)\]$/) { # scalar case
next; # skip scalars for now
# do scalar counters. Column should line up with "Try"
printf RESULTSHTML "<TR ALIGN=RIGHT><TH>%s</TH>\n",
($timerNames{$t}) ? $timerNames{$t} : $t;
printf RESULTSHTML
"<TD>%.3f</TD> ",
$finals{$proto}->{$t} / $realTestSecs;
next;
} else {
$t = $1;
}
printf RESULTSHTML "<TR ALIGN=RIGHT><TH>%s</TH>\n",
($timerNames{$t}) ? $timerNames{$t} : $t;
foreach $f (@timerFieldsAll) {
($f =~ m/^Time/o) && next;
if ($f =~ m/Bytes/o) {
printf RESULTSHTML
"<TD>%s</TD> ",
kformat ($finals{$proto}->{$t}->{$f} / $realTestSecs);
} else {
printf RESULTSHTML
"<TD>%.3f</TD> ",
$finals{$proto}->{$t}->{$f} / $realTestSecs;
}
}
print RESULTSHTML "</TR>\n";
}
printf RESULTSHTML "</TABLE> <BR>\n\n";
}
print RESULTSHTML <<END;
<BR>
<CENTER>
<A NAME=GraphSection></A>
END
}
%genplotGraphs = ();
# Call genplot; and, if a graph is generated, insert the HTML reference to it
sub genHTMLReportGraph {
my $name = shift;
my $title = shift;
my $label = shift;
my $protos = shift || die "genHTMLReportGraph: '$name' missing protocols";
my $field = shift;
my $vars = shift || die "genHTMLReportGraph: '$name' missing vars";
if ($genplotGraphs{$name}) {
print "Graph $name has already been generated.\n";
return;
}
$genplotGraphs{$name} = $title;
# Delineate and tag each graph
print RESULTSHTML "<A NAME=$name><HR SIZE=4 WIDTH=\"90%\"></A>\n";
if (genPlot ($name, $title, $label, $protos, $field, $vars) > 0) {
print RESULTSHTML <<END;
<P><H3>$title</H3>
<IMG SRC=$name.$params{IMAGETYPE} ALT="$label"></P>
END
} else {
print RESULTSHTML "<BR>Graph \"$name\" contained no data (@{$vars}).<BR>\n";
}
}
# Write the final parts of the HTML page
sub genHTMLReportEnd {
print RESULTSHTML <<END;
<!-- INSERT IMAGES HERE - DO NOT DELETE THIS LINE -->
</CENTER>
<A NAME=EndSection></A>
END
if ($params{SYSCONFIG}) {
print RESULTSHTML "<HR WIDTH=\"100%\">";
print RESULTSHTML "<CENTER><H2>Details</H2></CENTER>\n";
if (($params{SYSCONFIG} =~ m/^\S+$/o)
&& (open(SCFILE, "<$params{SYSCONFIG}"))) { # see if its a file
while (<SCFILE>) {
print RESULTSHTML $_;
}
close(SCFILE);
} else { # output text directly
my $l = $params{SYSCONFIG};
$l =~ s/\\\n/\n/g; # turn quoted newline to plain newline
print RESULTSHTML $l;
}
}
print RESULTSHTML <<END;
<HR NOSHADE WIDTH="100%">
</BODY>
</HTML>
END
close(RESULTSHTML);
}
# Actually generate the standard stuff
setupTotals();
genTextReport();
genHTMLReportStart();
my $graphCount = 0;
foreach $section (@workload) {
next unless ($section->{sectionTitle} =~ /GRAPH/o);
my $name = $section->{sectionParams};
$name =~ s/name=\s*//; # strip off initial bit
my @varlist = split (/[\s,]+/, $section->{VARIABLES});
$graphCount++;
genHTMLReportGraph ($name, $section->{TITLE}, $section->{LABEL},
($section->{FIELD} =~ /Time/o)
? \@protocols : \@protocolsAll,
$section->{FIELD}, \@varlist);
}
if ($graphCount <= 0) { # use built ins
# generate the graphs we want
# NOTE: the first argument (name), must be unique; sets file name
genHTMLReportGraph ("connects",
"Number of connections attempted", "Connections/sec",
\@protocolsAll, "Try", ["conn" ]);
genHTMLReportGraph ("connections",
"Total connections", "Connections",
\@protocolsAll, "", ["connections" ]);
genHTMLReportGraph ("errors",
"Number of connection errors", "Errors/sec",
\@protocolsAll, "Error", ["conn", "banner", "login", "logout" ]);
genHTMLReportGraph ("retrieves",
"Number of messages read", "Messages/sec",
\@protocolsAll, "Try", ["retrieve" ]);
genHTMLReportGraph ("submits",
"Number of messages written", "Messages/sec",
\@protocolsAll, "Try", ["submit" ]);
genHTMLReportGraph ("commands",
"Protocol commands", "Commands/sec",
\@protocolsAll, "Try", ["cmd" ]);
genHTMLReportGraph ("readBytes",
"Bytes read", "Bytes/sec",
\@protocolsAll, "BytesR", ["login", "banner", "cmd", "retrieve", "submit", "logout" ]);
genHTMLReportGraph ("writeBytes",
"Bytes written", "Bytes/sec",
\@protocolsAll, "BytesW", ["login", "banner", "cmd", "retrieve", "submit", "logout" ]);
genHTMLReportGraph ("msgTime",
"Message transfer time", "Seconds per message",
\@protocols, "Time", ["cmd", "submit", "retrieve" ]);
genHTMLReportGraph ("setupTime",
"Connection setup time", "Seconds per connection",
\@protocols, "Time", ["conn", "banner", "login" ]);
genHTMLReportGraph ("blocks",
"Number of mailstone blocks executed", "Blocks/sec",
\@protocolsAll, "", ["blocks" ]);
}
if ($params{ADDGRAPHS}) { # pick up additional graphs
my @graphs = ();
readWorkloadFile ($params{ADDGRAPHS}, \@graphs);
foreach $section (@graphs) {
next unless ($section->{sectionTitle} =~ /GRAPH/o);
my $name = $section->{sectionParams};
$name =~ s/name=\s*//; # strip off initial bit
my @varlist = split (/[\s,]+/, $section->{VARIABLES});
$graphCount++;
genHTMLReportGraph ($name, $section->{TITLE}, $section->{LABEL},
($section->{FIELD} =~ /Time/o)
? \@protocols : \@protocolsAll,
$section->{FIELD}, \@varlist);
}
}
genHTMLReportEnd();
return 1;

Просмотреть файл

@ -1,205 +0,0 @@
#!/bin/ksh
# global configuration parameters.
# Fill in defaults for anything that is not already set
# Look for testname$test_form, first
export test_form=${test_form:-""}
# string appended to every description
export desc_conf=${desc_conf:-""}
# extra arguments common to all tests
export extra_args=${extra_args:-""}
# error limit to abort sequence
export error_limit=${error_limit:-100}
# set this to only show what it will do
export only_show_it=${only_show_it:-0}
# time to allow the server to calm down after each run
export sleep_time=${sleep_time:-5}
# This is where we store the important runs
export save_dir=${save_dir:-"results.save"}
# Basic sanity test
if [[ ! -x /usr/bin/perl || ! -f .license ]] ; then # see if setup was ever run
echo "Critical files are missing. Run setup."
exit 2;
fi
find_timestamp () { # find the timestamp string from latest run
#OLD timestamp=`ls -d results/[0-9]*.[0-9][0-9][0-9][0-9]?(a-z) | tail -1`
# list all directories with the timestamp pattern
timestamp=`echo results/[0-9]*.[0-9][0-9][0-9][0-9]?([a-z])`
# strip all but the last one
timestamp=${timestamp##* }
# strip the top directory name out
timestamp=${timestamp#results/}
# return it
echo $timestamp
return 0
}
# copy last mailstone run from the current directory to good results directory
save_run () {
[[ -d $save_dir ]] || \
mkdir $save_dir
[[ $only_show_it -gt 0 ]] && return 0 # dont do anything important
if [[ -n "$last_timestamp" && -d "results/$last_timestamp/" ]] ; then
cp -pR results/$last_timestamp $save_dir/
# index probably has lots of extra junk, but its better than nothing
cp -pf results/index.html $save_dir/
fi
}
# Display and run a command. Skip if in only_show mode.
run () {
if [[ $only_show_it -gt 0 ]] ; then
echo "Would run:" "$@"
return 0
fi
echo "Running: " "$@"
"$@"
}
# Sleep. Skip if in only_show mode.
run_sleep () {
if [[ $only_show_it -gt 0 ]] ; then
echo "Would sleep:" "$@"
return 0
fi
echo "Sleeping: " "$@"
sleep "$@"
}
# for readability, just use sleep
alias sleep=run_sleep
# This runs the actual mstone run and check for errors
# compress tmp files
# Usage: run_test testname description [args...]
run_test () {
testname="$1"; shift;
desc="$1"; shift;
# see if a special version of this test exists
if [[ -f conf/$testname$test_form.wld ]] ; then
testname=$testname$test_form
fi
#oldtimestamp=`find_timestamp`
if [[ $only_show_it -gt 0 ]] ; then
echo "Would run:" mstone $testname -b "$desc $desc_conf" $extra_args "$@"
if [[ ! -f conf/$testname.wld ]] ; then
echo "Configuration Error: No such test $testname"
fi
return 0
fi
echo "\n##########################################################"
if [[ ! -f conf/$testname.wld ]] ; then
echo "CONFIGURATION ERROR: No such test $testname"
exit 2
fi
echo "\nRunning:" mstone $testname -b "$desc $desc_conf" $extra_args "$@"
# We actually bypass the mstone script
/usr/bin/perl -Ibin -- bin/mailmaster.pl -w conf/$testname.wld -b "$desc $desc_conf" $extra_args "$@"
stat=$?
# BUG if another test is running at the same time, this is wrong
timestamp="`find_timestamp`"
# test failed to even run
if [[ $stat -ne 0 ]]
then
echo "ABORT! Test failed to start"
[[ -n "$mail_list" ]] && \
mail_series "DotCom Failed run: `date`" "$mail_list"
exit 2
fi
# compress tmp files. get the csv files, too.
gzip tmp/$timestamp/* results/$timestamp/*.csv
# stick the timestamp someplace global for a save_run
export last_timestamp=$timestamp
export all_timestamps="$all_timestamps $timestamp"
# save the results
save_run
# see how many errors we hit
totline=`grep 'Total:total ' results/$timestamp/results.txt`
# strip label and first field
errors=${totline##+([+-z])+( )+([+-9])+( )}
# strip trailing fields
errors=${errors%% *}
echo "" # space things out
if [[ $errors -gt $error_limit ]] ; then
echo "ABORT! Errors ($errors) exceed error limit ($error_limit)"
[[ -n "$mail_list" ]] && \
mail_series "DotCom Aborted run: `date`" "$mail_list"
exit 1
fi
echo "Run completed OK ($errors errors). Timestamp $timestamp"
sleep $sleep_time
return 0
}
# Usage: mail_series subject "address,address,..."
mail_series () {
subject=$1; shift
file=/tmp/series$$.tar
if [[ $only_show_it -gt 0 ]] ; then
echo "Would mail results about $subject" to "$@"
return 0
fi
echo "Mailing results about $subject" to "$@"
tar cf $file $save_dir/index.html
for f in $all_timestamps ; do
tar rf $file $save_dir/$f
done
gzip $file
echo "$all_timestamps" | uuenview -b -30000 -s "$subject" -m "$@" $file.gz
rm -f $file.gz
}
# parse command line arguments
while [[ -n "$1" ]]
do
case $1 in
# -n mode, do not execute, just show
-n) only_show_it=1; shift;;
# set test form
-f) shift; test_form=$1; shift;;
# set test extra description
-d) shift; desc_conf=$1; shift;;
# Rest are to be passed in exactly
--) shift; break;;
#default, pick up as an extra arg
*) extra_args="$extra_args $1"; shift;;
esac
done

Просмотреть файл

@ -1,417 +0,0 @@
#!/usr/bin/perl
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Netscape Mailstone utility,
# released March 17, 2000.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1999-2000 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Dan Christian <robodan@netscape.com>
# Marcel DePaolis <marcel@netcape.com>
# Jim Salter <jsalter@netscape.com>
#
# Alternatively, the contents of this file may be used under the
# terms of the GNU Public License (the "GPL"), in which case the
# provisions of the GPL are applicable instead of those above.
# If you wish to allow use of your version of this file only
# under the terms of the GPL and not to allow others to use your
# version of this file under the NPL, indicate your decision by
# deleting the provisions above and replace them with the notice
# and other provisions required by the GPL. If you do not delete
# the provisions above, a recipient may use your version of this
# file under either the NPL or the GPL.
#####################################################
# usage: setup.pl setup|cleanup|checktime|timesync -m machine_file
# message files are expected to be in ./data/ and end with ".msg"
print "Netscape Mailstone.\nCopyright (c) 1997-2000 Netscape Communications Corp.\n";
$mode = shift; # mode must be first
# this parses the command line for -m machinefile
# also sets many defaults
do 'args.pl'|| die $@;
parseArgs(); # parse command line
setConfigDefaults(); # setup RSH and RCP
$cpcmd = "cp"; # copy files... dir
$rmcmd = "rm -f"; # remove files...
die "Must specify workload file" unless (@workload);
# Add or change client machines
sub configClients {
print "\n You can enter multiple machines like this: host1,host2\n";
my @d = <bin/*/bin>;
if (@d) {
my @d2;
foreach (@d2 = @d) { s/^bin\/// }
foreach (@d = @d2) { s/\/bin$// }
print " These OS versions are available:\n@d\n";
}
foreach $section (@workload) {
next unless ($section->{sectionTitle} =~ /CLIENT/o);
my $slist = $section->{sectionParams};
$slist =~ s/HOSTS=\s*//; # strip off initial bit
my $arch = "default OS";
$arch = $section->{ARCH} if ($section->{ARCH});
print "\nWhat is the name of the client(s) for $arch [$slist]: ";
my $ans = <STDIN>; chomp $ans;
if ($ans) {
$ans =~ s/\s//g; # strip any whitespace
fileReplaceText ($params{WORKLOAD}, "<CLIENT", $slist, $ans);
}
}
while (1) {
print "\nWhat additional client(s) [none]: ";
my $ans = <STDIN>; chomp $ans;
last unless ($ans); # done
last if ($ans =~ /^none$/i);
$ans =~ s/\s//g; # strip any whitespace
my $block = "\n<CLIENT HOSTS=$ans>\n";
print "What OS type [default]: ";
my $ans = <STDIN>; chomp $ans;
$block .= " Arch\t$ans\n" if ($ans && !($ans =~ /^default$/i));
$block .= "</CLIENT>\n";
fileInsertAfter ($params{WORKLOAD}, "^</CLIENT>", $block);
}
}
# Create a user ldif file
sub configUserLdif {
my $name = "conf/$defaultSection->{SERVER}.ldif";
print "\nWhat file to you want to create [$name]? ";
$ans = <STDIN>; chomp $ans;
$name = $ans if ($ans);
my $mode = "users";
print "\nDo you want to create a broadcast account [y]? ";
$ans = <STDIN>;
$mode .= " broadcast" unless ($ans =~ /^n/i);
my $basedn = $defaultSection->{SERVER}; # pick a default
$basedn =~ s/^.*?\.//; # strip off before first dot
$basedn = "o=$basedn";
print "\nWhat is LDAP base DN [$basedn]? ";
$ans = <STDIN>; chomp $ans;
$basedn = $ans if ($ans);
my $args = $params{MAKEUSERSARGS};
print "\n Common additional makeusers arguments:\n";
print "\t-s storeName -x storeCount \tMultiple store partitions\n";
print "\t[-3|-4] \tConfigure for NSMS 3.x or 4.x\n";
print "Any extra arguments to makeusers [$args]? ";
$ans = <STDIN>; chomp $ans;
$args = $ans if ($ans);
my $perlbin = "/usr/bin/perl";
$params{DEBUG} &&
print "$perlbin -Ibin -- bin/makeusers.pl $mode -w $params{WORKLOAD} -b '$basedn' -o $name $args\n";
print "\nGenerating $name (this can take a while)\n";
system "$perlbin -Ibin -- bin/makeusers.pl $mode -w $params{WORKLOAD} -b '$basedn' -o $name $args"
|| warn "$@";
print "LDIF generation complete. See $name\n";
print "\tSee the manual or INSTALL to create users using the LDIF file.\n";
}
# This uses a match pattern plus text to text replacements.
# Could make all changes and then write out new workload
# You would have to be carefull about sections with multi-line support.
sub configWorkload {
my $ans;
print "\nWhat is the name of the mail host [$defaultSection->{SERVER}]: ";
$ans = <STDIN>; chomp $ans;
if ($ans) {
fileReplaceText ($params{WORKLOAD},
"(SERVER|SMTPMAILFROM|ADDRESSFORMAT)",
$defaultSection->{SERVER}, $ans);
$defaultSection->{SERVER} = $ans; # needed for ldif generation
}
print "\nWhat is the user name pattern [$defaultSection->{LOGINFORMAT}]: ";
$ans = <STDIN>; chomp $ans;
if ($ans) {
fileReplaceText ($params{WORKLOAD},
"(LOGINFORMAT|ADDRESSFORMAT)",
$defaultSection->{LOGINFORMAT}, $ans);
$ans =~ s/%ld/0/; # create smtpMailFrom user
my $olduser = $defaultSection->{SMTPMAILFROM};
$olduser =~ s/@.*$//; # strip off after @
fileReplaceText ($params{WORKLOAD},
"SMTPMAILFROM",
$olduser, $ans);
}
print "\nWhat is the password pattern [$defaultSection->{PASSWDFORMAT}]: ";
$ans = <STDIN>; chomp $ans;
fileReplaceText ($params{WORKLOAD}, "PASSWDFORMAT",
$defaultSection->{PASSWDFORMAT}, $ans);
$defaultSection->{NUMLOGINS} = 100 unless ($defaultSection->{NUMLOGINS});
print "\nHow many users [$defaultSection->{NUMLOGINS}]: ";
$ans = <STDIN>; chomp $ans;
fileReplaceText ($params{WORKLOAD}, "(NUMADDRESSES|NUMLOGINS)",
$defaultSection->{NUMLOGINS}, $ans);
$defaultSection->{FIRSTLOGIN} = 0 unless ($defaultSection->{FIRSTLOGIN});
print "\nWhat is the first user number [$defaultSection->{FIRSTLOGIN}]: ";
$ans = <STDIN>; chomp $ans;
fileReplaceText ($params{WORKLOAD}, "(FIRSTADDRESS|FIRSTLOGIN)",
$defaultSection->{FIRSTLOGIN}, $ans);
unless ($params{NT}) {
configClients ();
}
print "\nDo you want to view the edited $params{WORKLOAD} [y]? ";
$ans = <STDIN>;
unless ($ans =~ /^n/i) {
print "Here is the edited $params{WORKLOAD}:\n\n";
fileShow ($params{WORKLOAD});
print "\n";
}
print "\nDo you want to generate a user LDIF file [y]? ";
$ans = <STDIN>;
unless ($ans =~ /^n/i) {
configUserLdif ();
}
}
# See if license file has been displayed
if (($mode ne "cleanup") && (! -f ".license" )) {
fileShow ("LICENSE");
print "\nDo you agree to the terms of the license? (yes/no) ";
my $ans = <STDIN>;
print "\n";
unless ($ans =~ /^yes$/i) {
print "License not agreed to.\n";
exit 0;
}
my ($sec, $min, $hour, $mday, $mon, $year) = localtime;
open (LIC, ">.license");
printf LIC "%04d$mon$mday$hour$min\n", $year+1900;
close (LIC);
}
if ($mode eq "config") { # re-run config
configWorkload ();
print "\nMake any additional changes to $params{WORKLOAD} and then re-run 'setup'\n";
exit 0;
} elsif ($mode ne "cleanup") { # check if configured
my $unconf = 0; # see if default values are in use
foreach $section (@workload) {
($section->{SERVER})
&& ($section->{SERVER} =~ /example\.com$/)
&& $unconf++;
($section->{SMTPMAILFROM})
&& ($section->{SMTPMAILFROM} =~ /example\.com$/)
&& $unconf++;
($section->{ADDRESSFORMAT})
&& ($section->{ADDRESSFORMAT} =~ /example\.com$/)
&& $unconf++;
last if ($unconf > 0);
}
if ($unconf > 0) {
print "Server has not been configured (example.com is an invalid address).\n";
print "Do you want to setup a simple configuration now [y]?";
my $ans = <STDIN>;
if ($ans =~ /^n/i) {
print "Re-run setup when you have edited the configuration.\n";
exit 0;
}
configWorkload ();
print "\nMake any additional changes to $params{WORKLOAD} and then re-run 'setup'\n";
exit 0;
}
}
if ($mode eq "timesync") {
if ($params{NT}) {
print "Timesync has no effect on NT\n";
exit 0;
}
my ($sec, $min, $hour, $mday, $mon, $year) = localtime;
$mon += 1; # adjust from 0 based to std
$systime = sprintf ("%02d%02d%02d%02d%04d.%02d",
$mon, $mday, $hour, $min, 1900+$year, $sec);
} elsif ($mode eq "checktime") {
if ($params{NT}) { # if running on NT, then only single client
print "Checktime not needed on NT\n";
exit 0;
}
mkdir ("$resultbase", 0775);
mkdir ("$tmpbase", 0775);
foreach $section (@workload) {
next unless ($section->{sectionTitle} =~ /CLIENT/o);
my $slist = $section->{sectionParams};
$slist =~ s/HOSTS=\s*//; # strip off initial bit
foreach $cli (split /[\s,]/, $slist) {
open MAKEIT, ">$tmpbase/$cli.tim";
close MAKEIT;
}
}
} elsif (($mode eq "setup") || ($mode eq "cleanup")) {
@msgs = <data/*.msg>;
foreach (@files = @msgs) { s/data\/// }
print "Found these message files:\n@files\n\n";
if ($params{NT}) { # handle NT localhost here
exit 0 if ($mode =~ /cleanup$/);
my $clipath = "bin/WINNT4.0/bin/mailclient.exe";
print "Copying $clipath and message files to $cli\n";
system "copy $clipath $params{TEMPDIR}";
foreach $f (@files) {
system "copy $f $params{TEMPDIR}";
}
exit 0; # without perl:fork, no more to do
}
}
# iterate over every client in the testbed, complete the cmd and rsh
foreach $section (@workload) {
next unless ($section->{sectionTitle} =~ /CLIENT/o);
my $slist = $section->{sectionParams};
$slist =~ s/HOSTS=\s*//; # strip off initial bit
foreach $cli (split /[\s,]/, $slist) {
my $rsh = ($section->{RSH}) ? $section->{RSH} : $params{RSH};
my $rcp = ($section->{RCP}) ? $section->{RCP} : $params{RCP};
my $tempdir;
if ($section->{TEMPDIR}) {
$tempdir = $section->{TEMPDIR};
} elsif ($params{TEMPDIR}) {
$tempdir = $params{TEMPDIR};
}
# most time critical first
if ($mode eq "timesync") {
next if ($cli =~ /^localhost$/i); # dont reset our own time
# run all these in parallel to minimize skew
next if ($section->{ARCH} eq "NT4.0");
forkproc ($rsh, $cli, "date $systime");
}
elsif ($mode eq "checktime") {
# run all these in parallel to minimize skew
forkproc ($rsh, $cli, ($section->{ARCH} eq "NT4.0")
? "time" : "date",
"/dev/null", "$tmpbase/$cli.tim");
}
elsif ($mode eq "setup") {
my ($clibin) = split /\s/, (($section->{COMMAND})
? $section->{COMMAND}
: $params{CLIENTCOMMAND});
my $clipath = "bin/$clibin";
if ($section->{ARCH}) {
if (-x "bin/$section->{ARCH}/bin/$clibin") {
$clipath="bin/$section->{ARCH}/bin/$clibin";
} else {
print "Requested OS $section->{ARCH} $cli not found. Using default.\n";
}
}
my $rdir = ($tempdir) ? "$tempdir/" : ".";
# chmod so that the remote files can be easily cleaned up
my $rcmd = "chmod g+w @files $clibin; uname -a";
$rcmd = "cd $tempdir; " . $rcmd if ($tempdir);
$rdir =~ s!/!\\!g if ($section->{ARCH} eq "NT4.0");
if ($cli =~ /^localhost$/i) {
die "TEMPDIR must be set for 'localhost'\n"
unless ($tempdir);
die "Invalid local NT copy. Should never get here.\n"
if ($section->{ARCH} eq "NT4.0"); # should never happen
print "Copying $clipath and message files to $rdir\n";
system ("$cpcmd @msgs $clipath $rdir");
system ($rcmd);
} else {
print "$rcp $clipath @msgs $cli:$rdir\n" if ($params{DEBUG});
print "Copying $clipath and message files to $cli:$rdir\n";
system (split (/\s+/, $rcp), $clipath, @msgs, "$cli:$rdir");
next if ($section->{ARCH} eq "NT4.0"); # chmod not valid
print "rcmd='$rcmd'\n" if ($params{DEBUG});
system (split (/\s+/, $rsh), $cli, $rcmd);
}
print "\n";
}
elsif ($mode eq "cleanup") {
if ($params{DEBUG}) { # get debug files
print "Cleaning up debug files on $cli\n";
my $rcmd = ($section->{ARCH} eq "NT4.0") ? "DEL" : "$rmcmd";
$rmcmd .= " mstone-debug.[0-9]*";
$rcmd = "cd $tempdir; " . $rcmd if ($tempdir);
$rcmd =~ s/;/&&/g if ($section->{ARCH} eq "NT4.0");
if ($cli =~ /^localhost$/i) {
die "TEMPDIR must be set for 'localhost'\n"
unless ($tempdir);
system ($rcmd);
} else {
system (split (/\s+/, $rsh), $cli, $rcmd);
}
} else {
print "Cleaning $cli\n";
my $rcmd = ($section->{ARCH} eq "NT4.0") ? "DEL" : "$rmcmd";
$rcmd .= " $clibin @files";
$rcmd = "cd $tempdir; " . $rcmd if ($tempdir);
$rcmd =~ s/;/&&/g if ($section->{ARCH} eq "NT4.0");
if ($cli =~ /^localhost$/i) {
die "TEMPDIR must be set for 'localhost'\n"
unless ($tempdir);
system ($rcmd);
} else {
system (split (/\s+/, $rsh), $cli, $rcmd);
}
}
}
else {
die "Couldn't recognize mode $mode!\n";
}
}
}
# wait for children to finish
if (($mode eq "timesync") || ($mode eq "checktime")) {
$pid = wait();
while ($pid != -1) {
$pid = wait();
}
}
# Print the results of the time checks
if ($mode eq "checktime") {
print "Time from each client:\n";
foreach $section (@workload) {
next unless ($section->{sectionTitle} =~ /CLIENT/o);
my $slist = $section->{sectionParams};
$slist =~ s/HOSTS=\s*//; # strip off initial bit
foreach $cli (split /[\s,]/, $slist) {
open TIMEFILE, "$tmpbase/$cli.tim"
|| warn "Counldn't open $tmpbase/$cli.tim\n";
printf "%32s: ", $cli;
while (<TIMEFILE>) { print; last;} # single line (2 on NT)
close(TIMEFILE);
unlink "$tmpbase/$cli.tim";
}
}
}

Просмотреть файл

@ -1,74 +0,0 @@
#!/bin/ksh
# fire off the series of Mailstone IMAP tests
# To test series setup, do: go_imap -n
# Look for testname$test_form, first. Override with: go_series -f <string>.
export test_form="_mail02"
export test_host="mail02"
# string appended to every description. Override with: go_series -d <string>.
export desc_conf="12 CPUs"
# Extra arguments common to all tests. Any other args go here.
# Note that arguments with embedded spaces wont work here.
# Instead use: go_series -- <args...>
export extra_args=""
# error limit to abort sequence
export error_limit=500
# time to allow the server to calm down after each run (seconds)
export sleep_time=120
# who to mail results to
#export mail_list="me@example.com,you@example.com"
export mail_list=""
# Get all the helper functions
. test_utils.ksh
### This is where the series of tests is defined
# clean and re-start server
if [[ $only_show_it -gt 0 ]] ; then
echo "Would run:" "$@"
return 0
else
# BUG: rsh never returns.
# individual commands in clean work fine, but fail as a whole
rsh -n $test_host /bin/ksh /iplanet/bin/clean$test_form &
sleep 300 && kill -9 $!
wait
fi
# check our setup
run timesync
###echo "DEBUG exit" && exit 0
run_test popdel 'Create mailboxes (random order)' -t 60m maxblocks=100000 "$@"
run_test allpop 'Create mailboxes (exhaustive)' "$@"
run_test imaplogin 'IMAP login rate' "$@"
run_test smtp10k-5-5k 'Deliver 5, 5k messages to 10k users' "$@"
sleep 200 # let queue drain (2000/(10 msg/sec))
run_test imapread10k 'IMAP Message downloads 5k from 10k users' "$@"
run_test smtp10k-5-5k 'Deliver 5, 5k messages to 10k users' "$@"
sleep 200 # let queue drain (2000/(10 msg/sec))
run_test imapread 'IMAP Message downloads 5k' "$@"
run_test imapsmtp-throttle 'Combined IMAP-SMTP load (1 of 3)' "$@"
run_test imapsmtp-throttle 'Combined IMAP-SMTP load (2 of 3)' "$@"
run_test imapsmtp-throttle 'Combined IMAP-SMTP load (3 of 3)' "$@"
# Some messages will be left from previous test
run_test imapmaxusers 'IMAP 30K simultaneous users' "$@"
# e-mail the whole batch
[[ -n "$mail_list" ]] && \
mail_series "DotCom IMAP: `date`" "$mail_list"

Просмотреть файл

@ -1,84 +0,0 @@
#!/bin/ksh
# fire off the series of Mailstone tests
# To test series, do: go_series -n
# Look for testname$test_form, first. Override with: go_series -f <string>.
export test_form="_mail02"
export test_host="mail02"
# string appended to every description. Override with: go_series -d <string>.
export desc_conf="12 CPUs"
# Extra arguments common to all tests. Any other args go here.
# Note that arguments with embedded spaces wont work here.
# Instead use: go_series -- <args...>
export extra_args=""
# error limit to abort sequence
export error_limit=500
# time to allow the server to calm down after each run (seconds)
export sleep_time=120
# who to mail results to
#export mail_list="me@example.com,you@example.com"
export mail_list=""
# Get all the helper functions
. test_utils.ksh
### This is where the series of tests is defined
# clean and re-start server
if [[ $only_show_it -gt 0 ]] ; then
echo "Would run:" "$@"
return 0
else
# BUG: this never returns. rsh never returns
# individual commands in clean work fine, but fail as a whole
rsh -n $test_host /bin/ksh /iplanet/bin/clean$test_form &
sleep 300 && kill -9 $!
wait
fi
# check our setup
run timesync
###echo "DEBUG exit" && exit 0
run_test popdel 'Create mailboxes (random order)' -t 60m maxblocks=100000 "$@"
run_test allpop 'Create mailboxes (exhaustive)' "$@"
run_test popdel 'Empty checks: never used (1 of 3)' "$@"
run_test popdel 'Empty checks: never used (2 of 3)' "$@"
run_test popdel 'Empty checks: never used (3 of 3)' "$@"
run_test smtp10k-5-5k 'Deliver 5, 5k messages to 10k users' "$@"
sleep 200 # let queue drain (2000/(10 msg/sec))
run_test popsave10k 'Message downloads 5k from 10k users (1 of 3)' "$@"
run_test popsave10k 'Message downloads 5k from 10k users (2 of 3)' "$@"
run_test popsave10k 'Message downloads 5k from 10k users (3 of 3)' "$@"
run_test popsave 'Message downloads 5k (1 of 3)' "$@"
run_test popsave 'Message downloads 5k (2 of 3)' "$@"
run_test popsave 'Message downloads 5k (3 of 3)' "$@"
run_test popsmtp-throttle 'Combined load (1 of 3)' "$@"
run_test popsmtp-throttle 'Combined load (2 of 3)' "$@"
run_test popsmtp-throttle 'Combined load (3 of 3)' "$@"
run_test smtp100k 'SMTP delivery rate' "$@"
run_test popclean 'Message downloads/delete 5k ' "$@"
run_test popdel 'Empty checks (1 of 3)' "$@"
run_test popdel 'Empty checks (2 of 3)' "$@"
run_test popdel 'Empty checks (3 of 3)' "$@"
# e-mail the whole batch
[[ -n "$mail_list" ]] && \
mail_series "DotCom POP: `date`" "$mail_list"

Просмотреть файл

@ -1,281 +0,0 @@
# MailStone workload configuration file
#
# Include other workload files like this:
# <include conf/morework.wld>
#
# If you want a workload included ONLY ONCE in the test, use this
# <includeOnce conf/morework.wld>
#
# See Also:
# smtp.wld - typical SMTP delivery test
# pop.wld - typical POP3 check/download test
# imap.wld - typical IMAP4 check/download test
######################################################################
# These sections discribe how the test is run:
# CONFIG, CLIENT, MONITOR, PRETEST, POSTTEST
# The <CONFIG> section defines test setup and report parameters
# Multiple <CONFIG> sections will be merged into a one.
# The equivalent command line switch is shown in parenthesis.
<CONFIG>
title POP reads # title for report and index (-b)
comments Netscape MSG4.1 # additional info at top of report (-n)
time 3m # test time (-t)
rampTime 20s # portion of test to start things (-r)
clientCount 12 # number of client connections (-l)
maxErrors 10000 # set an error abort limit
maxBlocks 50000 # stop after this many blocks
#sysConfig conf/mailhost.txt # Pull in config file (-s)
sysConfig \ # Inline config text
<PRE>\
<B> mailhost.example.com </B>\
Netscape Messaging Server 4.11\
Linux 2.2.5\
4x400Mhz Xeon (1Mb)\
2Gb RAM\
</PRE>
useGroups 1 # use group names instead of host names
telemetry 1 # log telemetry (for debugging)
# These usually dont need to be set. These are the defaults
GnuPlot gnuplot/gnuplot
RSH ssh
# RSH /usr/bin/remsh # HP-UX uses this path
RCP scp
# RCP /usr/bin/rcp
tempDir /var/tmp # client machine directory
chartWidth 640
chartHeight 480
clientCommand mailclient # CLIENT command to run
monitorCommand vmstat %f # MONITOR command to run
makeUsersArgs -4 # args to makeusers
imageType png # gnuplot image type: png, gif, ...
</CONFIG>
# Each <Client> section defines one or more client machines
# Every machine in the section will run the same number of connections
# Note that there cannot be whitespace between the client hostnames
<CLIENT HOSTS=client1,client2>
arch Linux2.2_x86
maxClients 200
maxThreads 50
# the group is only used if "useGroups" is set
group A
command mailclient -m 100 # override the command to run
</CLIENT>
# Set a specific number of processes and threads
<CLIENT HOSTS=client3,client4>
arch SunOS5.6
processes 2
threads 10
# the group is only used if "useGroups" is set
group B
</CLIENT>
# Here is how to configure a WinNT client from a Unix mail master
# The NT rshd must interoperate with Unix rsh; allow redirection of
# stdin, stdout, and stderr; and must support binary file copies.
# Denicomp's wrshdnt has been used sucessfully. www.denicomp.com
<CLIENT HOSTS=winnt01>
Arch WINNT4.0
command mailclient.exe
tempDir c:\temp
</CLIENT>
# The PreTest sections will run before the test starts
<PRETEST HOSTS=mailhost.example.com>
# RSH rsh -l mailuser
command cd /usr/netscape/msg-mailhost; ./getconf
</PRETEST>
# Each <Monitor> section defines remote monitoring commands
# for one or more machines.
# Commands containing '%c' run to completion.
# Otherwise the command will be shutdown down
<MONITOR HOSTS=mailhost.example.com>
command vmstat,%f,%c
</MONITOR>
# The PostTest sections will run after the test completes
<POSTTEST HOSTS=mailhost.example.com>
command df
</POSTTEST>
######################################################################
# available protcols: SMTP, POP3, IMAP4
# (command names are not case sensitive)
#
# Time formats use suffixes of 's', 'm', 'h', 'd'
# for seconds, minutes, hours, days
# In account formats, "%ld" is replaced by user number
# These parameters apply to the protocol sections
# Command parameter applicable command Example
#-------------------------------------------------------------------
# server <ALL> mail.example.com
# portNum <ALL> 25
# (if no value is given, the default port for that service is used)
#
# weight <ALL> 20
#
# loginFormat <ALL> test%ld
# %ld=address %ld=domain
# firstLogin <ALL> 0
# numLogins <ALL> 2000
# sequentialLogins <ALL> 1
# passwdFormat <ALL> netscape
#
# addressFormat <ALL> test%ld@mail.example%ld.com
# %ld=address %ld=domain
# firstAddress <ALL> 0
# numAddresses <ALL> 2000
# sequentialAddresses <ALL> 1
#
# numDomains <ALL> 3
# firstDomain <ALL> 0
# sequentialDomains <ALL> 1
#
# idleTime <ALL> 5m
# numLoops <ALL> 200
# loopDelay <ALL> 1m
# blockTime <ALL> 5m
#
# numRecips SMTP 3
# smtpMailFrom SMTP mailstone@mail.example.com
# file SMTP en-3k.msg
# useEHLO SMTP 1 (default is HELO)
# useAUTHLOGIN SMTP 1 (no AUTHLOGIN by default)
#
# leaveMailOnServer POP3,IMAP4 1
# leaveMailUnSeen IMAP4 1
# The <Default> section sets command block defaults
# Multiple <Default> sections will be merged into one
<DEFAULT>
server mailhost.example.com
smtpMailFrom mailhost0@mailhost.example.com
addressFormat mailhost%ld@mailhost.example.com
loginFormat mailhost%ld
passwdFormat netscape
numLogins 1000
numAddresses 1000
</DEFAULT>
# Note: empty host list means all hosts
<SMTP>
file en-1k.msg
weight 10
numAddresses 200
</SMTP>
<include conf/smtp17.wld>
# Note: the host name must be the same as specified in the CLIENT section
<POP3 HOSTS=client1,client2>
weight 10
#leaveMailOnServer 1
</POP3>
<IMAP4 HOSTS=client3>
idleTime 300
#weight 15
</IMAP4>
######################################################################
# These sections are used to generate the right graphs for the test
# This is the built in defaults
<GRAPH name=connects>
title Number of connections attempted
label Connections/sec
variables conn
field Try
</GRAPH>
<GRAPH name=connections>
title Total connections
label Connections
variables connections
</GRAPH>
<GRAPH name=connErrors>
title Number of connection errors
label Errors/sec
variables conn, banner, login, logout
field Error
</GRAPH>
<GRAPH name=msgErrors>
title Number of command/message errors
label Errors/sec
variables cmd, submit, retrieve
field Error
</GRAPH>
<GRAPH name=retrieves>
Title Number of messages read
label Messages/sec
variables retrieve
field Try
</GRAPH>
<GRAPH name=submits>
title Number of messages written
label Messages/sec
variables submit
field Try
</GRAPH>
<GRAPH name=commands>
title Number of commands sent
label Commands/sec
variables cmd
field Try
</GRAPH>
<GRAPH name=readBytes>
title Bytes read
label Bytes/sec
variables login, banner, cmd, retrieve, submit, logout
field BytesR
</GRAPH>
<GRAPH name=writeBytes>
title Bytes written
label Bytes/sec
variables login, banner, cmd, retrieve, submit, logout
field BytesW
</GRAPH>
<GRAPH name=msgTime>
title Message transfer time
label Seconds per message
variables cmd, submit, retrieve
field Time
</GRAPH>
<GRAPH name=setupTime>
Title Connection setup time
label Seconds per connection
variables conn, banner, login
field Time
</GRAPH>
<GRAPH name=blocks>
title Number of mailstone blocks executed
label Blocks/sec
variables blocks
# this is a scalar. No "field" needed/allowed
</GRAPH>

Просмотреть файл

@ -1,74 +0,0 @@
#!/bin/ksh
# fire off the series of Mailstone WEBMAIL tests
# To test series setup, do: go_webmail -n
# Look for testname$test_form, first. Override with: go_series -f <string>.
export test_form="_mail02"
export test_host="mail02"
# string appended to every description. Override with: go_series -d <string>.
export desc_conf="12 CPUs"
# Extra arguments common to all tests. Any other args go here.
# Note that arguments with embedded spaces wont work here.
# Instead use: go_series -- <args...>
export extra_args=""
# error limit to abort sequence
export error_limit=500
# time to allow the server to calm down after each run (seconds)
export sleep_time=120
# who to mail results to
#export mail_list="me@example.com,you@example.com"
export mail_list=""
# Get all the helper functions
. test_utils.ksh
### This is where the series of tests is defined
# clean and re-start server
if [[ $only_show_it -gt 0 ]] ; then
echo "Would run:" "$@"
return 0
else
# BUG: rsh never returns.
# individual commands in clean work fine, but fail as a whole
rsh -n $test_host /bin/ksh /iplanet/bin/clean$test_form &
sleep 300 && kill -9 $!
wait
fi
# check our setup
run timesync
###echo "DEBUG exit" && exit 0
run_test popdel 'Create mailboxes (random order)' -t 60m maxblocks=100000 "$@"
run_test allpop 'Create mailboxes (exhaustive)' "$@"
run_test webmaillogin 'WebMail login rate' "$@"
run_test smtp10k-5-5k 'Deliver 5, 5k messages to 10k users' "$@"
sleep 200 # let queue drain (2000/(10 msg/sec))
run_test webmailread10k 'WebMail Message downloads 5k from 10k users' "$@"
run_test smtp10k-5-5k 'Deliver 5, 5k messages to 10k users' "$@"
sleep 200 # let queue drain (2000/(10 msg/sec))
run_test webmailread 'WebMail Message downloads 5k' "$@"
run_test webmailsmtp-throttle 'Combined WebMail-SMTP load (1 of 3)' "$@"
run_test webmailsmtp-throttle 'Combined WebMail-SMTP load (2 of 3)' "$@"
run_test webmailsmtp-throttle 'Combined WebMail-SMTP load (3 of 3)' "$@"
# Some messages will be left from previous test
run_test webmailmaxusers 'WebMail 30K simultaneous users' "$@"
# e-mail the whole batch
[[ -n "$mail_list" ]] && \
mail_series "DotCom WebMail: `date`" "$mail_list"

Просмотреть файл

@ -1,72 +0,0 @@
#!/bin/sh
# package an OS into a multi-OS tree
# usage ospkg.sh targetOS os...
target=$1; shift
pkgdir=./build/package/$target/mstone
errors=0
for obj
do
srcdir=./build/package/$obj/mstone
if [ ! -d $srcdir ] ; then
echo "Error! Source directory $srcdir is missing."
errors=1
continue;
fi
arch=`echo $obj | sed -e 's/_OPT.OBJ//' | sed -e 's/_DBG.OBJ//'`
echo "===== adding $arch packaging to $pkgdir"
echo "Installing mailclient"
[ -d $pkgdir/bin/$arch/bin ] || mkdir -p $pkgdir/bin/$arch/bin
cp -p $srcdir/bin/mailclient $pkgdir/bin/$arch/bin/
if [ -d $srcdir/gd ] ; then
echo "Installing gd"
[ -d $pkgdir/bin/$arch/gd ] || mkdir -p $pkgdir/bin/$arch/gd
cp -p $srcdir/gd/* $pkgdir/bin/$arch/gd/
fi
if [ -d $srcdir/gnuplot ] ; then
echo "Installing gnuplot"
[ -d $pkgdir/bin/$arch/gnuplot ] || mkdir -p $pkgdir/bin/$arch/gnuplot
cp -p $srcdir/gnuplot/* $pkgdir/bin/$arch/gnuplot/
fi
if [ -d $srcdir/perl ] ; then
perlver=`cd $srcdir/perl/lib; ls -d 5.* | head -1`
perlarch=`cd $srcdir/perl/lib/$perlver; ls -d */Config.pm | cut -f1 -d/`
echo "Installing perl $perlver for $perlarch"
[ -d $pkgdir/perl ] || mkdir -p $pkgdir/perl
cp -pf $srcdir/perl/Artistic $pkgdir/perl/
# we dont pull everything in, just the potentially useful parts
for subdir in man/man1 \
lib/$perlver lib/$perlver/$perlarch \
lib/$perlver/Time lib/$perlver/Term lib/$perlver/Class \
lib/$perlver/Sys lib/$perlver/Data lib/$perlver/Getopt \
lib/$perlver/Test lib/$perlver/Text \
lib/$perlver/File lib/$perlver/File/Spec \
lib/$perlver/CGI lib/$perlver/Net \
lib/$perlver/$perlarch/auto/DynaLoader \
lib/$perlver/$perlarch/auto/Socket \
lib/$perlver/$perlarch/auto/re \
lib/$perlver/$perlarch/auto/attrs
do
[ -d $srcdir/perl/$subdir ] || continue;
[ -d $pkgdir/perl/$subdir ] || mkdir -p $pkgdir/perl/$subdir
# HACK: all the files have dots in them, directories dont
cp -pf $srcdir/perl/$subdir/*.* $pkgdir/perl/$subdir
done
# where we put multi-os perl binaries
perlbin=$pkgdir/perl/arch/$arch
[ -d $perlbin ] || mkdir -p $perlbin
cp -p $srcdir/perl/bin/* $perlbin/
fi
done
exit $errors

Просмотреть файл

@ -1,514 +0,0 @@
/* -*- Mode: C; c-file-style: "stroustrup"; comment-column: 40 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape Mailstone utility,
* released March 17, 2000.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1997-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s): Dan Christian <robodan@netscape.com>
* Marcel DePaolis <marcel@netcape.com>
* Mike Blakely
* David Shak
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License Version 2 or later (the "GPL"), in
* which case the provisions of the GPL are applicable instead of
* those above. If you wish to allow use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the NPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the NPL or the GPL.
*/
#ifndef __BENCH_H__
#define __BENCH_H__
#include <stdio.h>
#include <stdarg.h>
#include <limits.h>
#include <float.h>
#include <sys/stat.h>
#include <assert.h>
#ifdef _WIN32
#include <windows.h>
#include <winsock.h>
#include <time.h>
#include <process.h>
#include <io.h>
#define NT_STACKSIZE 50*1024
#endif /* _WIN32 */
#include <errno.h>
#include <signal.h>
#ifdef USE_PTHREADS
#include <sys/signal.h>
#include <pthread.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <sys/types.h>
#include <ctype.h>
#include <fcntl.h>
#ifndef _WIN32
#include <sys/poll.h>
#include <sys/param.h>
#include <sys/ipc.h>
#include <sys/errno.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <sys/resource.h> /* for struct rlimit, RLIMIT_NOFILE */
#ifdef HAVE_SELECT_H
#include <sys/select.h>
#endif
#ifdef HAVE_WAIT_H
#include <wait.h>
#endif
#endif /* _WIN32 */
#include "sysdep.h"
#define USECINSEC 1000000
#define MSECINSEC 1000
#define MAX_ACCEPT_SECS 180 /* maximum time master will wait for listen() */
#define SECS_2_USECS(x) ((x) * USECINSEC)
#define USECS_2_SECS(x) ((x) / USECINSEC)
#define LINE_BUFSIZE 4096
#define MAXPROCSPERNODE 4096 /* max # of procs/node */
#define SMTP_PORT 25 /* standard port numbers */
#define POP3_PORT 110
#define IMAP4_PORT 143
#define HTTP_PORT 80
#define WMAP_PORT 80
#define CRLF "\r\n"
#define MAX_USERNAME_LEN 32
#define MAX_MAILADDR_LEN 64
#define MAX_COMMAND_LEN (2*1024)
#define MAX_RESPONSE_LEN (2*1024)
#define MAX_ERRORMSG_LEN 256
#define DATESTAMP_LEN 40
#define MAX_IMAP_FOLDERNAME_LEN 256
#define MAX_SEARCH_PATTERN_LEN 256
#define MAX_HTTP_COMMAND_LEN 1024
/* TODO make these dynamic. For now just use big buffers */
#define SIZEOF_EVENTTEXT 150 /* report text from a single timer */
#define SIZEOF_RQSTSTATSTEXT 2048 /* report text from all timers */
#define SIZEOF_SUMMARYTEXT 8192 /* report text from all protocols */
/* levels for timeexpired */
#define EXIT_SOON 1 /* do a clean shutdown ASAP */
#define EXIT_FAST 20 /* shutdown now, dont block */
#define EXIT_FASTEST 50 /* close sockets unconnditionally */
/* Debug macros */
#define D_PRINTF if (gn_debug > 0) d_printf
#define T_PRINTF if (gn_record_telemetry) t_printf
/*
Simple keyword indexed string storage
This kind of thing has been invented many times. Once more with gusto!
*/
typedef struct param_list {
struct param_list *next;
char * name;
char * value;
} param_list_t;
/*
Simple keyword indexed string storage
This kind of thing has been invented many times. Once more with gusto!
*/
typedef struct string_list {
struct string_list *next;
char * value;
} string_list_t;
/* Numeric range (Shared). Previous value must be stored seperately */
typedef struct range {
unsigned long first; /* first valid value */
unsigned long last; /* last valid value */
unsigned long span; /* last-first */
int sequential; /* 0=random, +=sequential up, -=down */
} range_t;
/* basic timing structure */
typedef struct event_timer {
unsigned long trys;
unsigned long errs;
double bytesread;
double byteswritten;
double elapsedtime;
double elapsedtimesq;
double maxtime;
double mintime;
} event_timer_t;
/* command stats kept for every block and for every thread */
typedef struct cmd_stats {
/* This is protocol independent */
unsigned long totalerrs;
unsigned long totalcommands;
event_timer_t combined; /* AKA total */
event_timer_t idle;
void * data; /* protocol dependent data */
} cmd_stats_t;
typedef struct stats { /* used for throttling ??? */
struct timeval starttime;
struct timeval endtime;
unsigned int total_num_of_commands;
} stats_t;
typedef struct resolved_addr {
char * hostName; /* name of server */
NETPORT portNum; /* port ot use */
int resolved;
struct hostent host_phe;
struct protoent host_ppe;
unsigned long host_addr;
short host_type;
} resolved_addr_t;
typedef struct thread_context *ptcx_t;
typedef struct mail_command *pmail_command_t;
typedef struct protocol *p_protocol_t;
typedef int (*parseStartPtr_t)(pmail_command_t, char *, param_list_t *);
typedef int (*parseEndPtr_t)(pmail_command_t, string_list_t *, param_list_t *);
typedef void *(*commStartPtr_t)(ptcx_t , pmail_command_t , cmd_stats_t *);
typedef int (*commLoopPtr_t)(ptcx_t , pmail_command_t , cmd_stats_t *, void *);
typedef void (*commEndPtr_t)(ptcx_t , pmail_command_t , cmd_stats_t *, void *);
typedef void (*statsFormatPtr_t)(p_protocol_t, const char *extra, char *buf);
typedef void (*statsInitPtr_t)(pmail_command_t, cmd_stats_t *, int, int);
typedef void (*statsUpdatePtr_t)(p_protocol_t, cmd_stats_t *, cmd_stats_t *);
typedef void (*statsOutputPtr_t)(p_protocol_t, cmd_stats_t *, char *);
typedef struct protocol {
const char * name; /* text name */
parseStartPtr_t parseStart; /* section start parse routine */
parseEndPtr_t parseEnd; /* section end parse routine */
commStartPtr_t cmdStart; /* command start routine */
commLoopPtr_t cmdLoop; /* command loop routine */
commEndPtr_t cmdEnd; /* command end routine */
statsFormatPtr_t statsFormat; /* output format information */
statsInitPtr_t statsInit; /* init and zero stats structure */
statsUpdatePtr_t statsUpdate; /* sum commands */
statsOutputPtr_t statsOutput; /* output stats */
int cmdCount; /* commands using this protocol */
cmd_stats_t stats; /* total stats for this protocol */
} protocol_t;
/* This structure defines a mail command */
typedef struct mail_command {
/* Required fields */
protocol_t * proto;
int weight;
/* These are protocol independent (client.c) */
int blockID; /* ID number for each block */
int numLoops; /* typically messages per connection */
int idleTime; /* time to idle before loops */
int loopDelay; /* time to idle after each loop */
int blockTime; /* time to idle after block */
int throttle; /* to simulate ops/sec (BROKEN) */
void *data; /* protocol specific data */
} mail_command_t;
typedef struct child_context { /* forked sub processes */
int pid;
SOCKET socket;
} ccx_t, *pccx_t;
typedef struct thread_context {
/* initialized by parent thread */
THREAD_ID tid; /* thread id */
int processnum; /* ordinal process number */
int threadnum; /* ordinal thread number */
int random_seed; /* seed for srandom */
/* local thread context, also read by parent */
int blockCount; /* how many command blocks */
int connectCount; /* how many connections */
stats_t timestat; /* throttle info */
cmd_stats_t *cmd_stats; /* stats for each command */
/* temporary storage (event_start, event_stop) */
struct timeval starttime; /* a starting timestamp */
int bytesread; /* num bytes read in per event */
int byteswritten; /* num bytes written per event */
int ofd; /* connection to master */
FILE *dfile; /* debug file */
int logfile; /* telemetry log file */
SOCKET sock; /* network connection */
char errMsg[MAX_ERRORMSG_LEN]; /* low level error string */
} tcx_t;
/* About errMsg:
This should store what was being attempted when a IO error occurs.
From errMsg and errno (or its NT equivalent) you should be able
to understand what went wrong.
No message is printed by the common functions (since some errors are
recoverable).
The protocol handlers combine errMsg with neterrstr() to generate
the message that the user sees (if not handled by the protocol).
Note that this is a small buffer (since it is replicated with every
thread). Don't try to stuff the read/written data into it.
The routine getting the system error sets errMsg (strcpy, or sprintf).
Calling routines append a "call trace" with additional info (strcat).
The "call trace" starts with '<' as a seperator.
*/
#define debugfile (ptcx->dfile)
#ifndef MIN
#define MIN(x,y) (((x) < (y)) ? (x) : (y))
#endif
#ifndef MAX
#define MAX(x,y) (((x) >= (y)) ? (x) : (y))
#endif
/* routines in bench.c */
extern void event_start(ptcx_t ptcx, event_timer_t *pevent);
extern void event_stop(ptcx_t ptcx, event_timer_t *pevent);
extern void event_reset(event_timer_t *pevent);
extern void event_sum(event_timer_t *psum, event_timer_t *pincr);
extern char *event_to_text(event_timer_t *pevent, char *ebuf);
extern void stats_init(stats_t *);
extern char * double_to_text(const double the_double, char *textbuf);
#if 0
extern cmd_stats_t *text_to_cmd_stats(ptcx_t ptcx, char *cmd_stats_as_text, cmd_stats_t *the_cmd_stats);
extern cmd_stats_t * text_to_cmd_stats(ptcx_t ptcx, char *, cmd_stats_t *the_cmd_stats);
extern stats_t * text_to_stats(ptcx_t ptcx, char *, stats_t *the_stats);
extern char * stats_to_text(ptcx_t ptcx, const stats_t *, char *statstextbuf);
#endif
/* shared variables */
extern int gn_debug;
extern int gn_record_telemetry;
extern int gn_total_weight;
extern int gn_client_throttle;
extern int gn_maxerrorcnt;
extern int gn_maxBlockCnt;
extern int gn_numprocs;
extern int gn_numthreads;
extern int gn_feedback_secs;
extern time_t gt_testtime;
extern time_t gt_startedtime;
extern volatile time_t gt_shutdowntime;
extern volatile int gf_timeexpired;
extern time_t gt_stopinterval; /* MAX (ramptime/5, 10) */
extern time_t gt_aborttime; /* startedtime + testtime + ramptime*/
extern int gn_number_of_commands;
extern int gf_abortive_close;
extern int gf_imapForceUniqueness;
extern char gs_dateStamp[DATESTAMP_LEN];
extern char gs_thishostname[];
extern char *gs_parsename;
extern pid_t gn_myPID;
extern mail_command_t *g_loaded_comm_list; /* actually a dynamic array */
extern protocol_t g_protocols[];
extern const char *gs_eventToTextFormat;
/* more routines in bench.c */
extern void *mymalloc(size_t size);
extern void *mycalloc(size_t size);
extern void *myrealloc(void *ptr, size_t size);
extern void myfree(void *ptr);
extern char *mystrdup(const char *cp);
extern int timeval_clear(struct timeval *tv);
extern int timeval_stamp(struct timeval *tv);
extern int waitReadWrite(int fd, int flags);
extern int retryRead(ptcx_t ptcx, SOCKET sock, char *buf, int count);
extern int retryWrite(ptcx_t ptcx, SOCKET sock, char *buf, int count);
extern int recvdata(ptcx_t ptcx, SOCKET sock, char *ptr, int nbytes);
extern int senddata(ptcx_t ptcx, SOCKET sock, char *ptr, int nbytes);
extern void rqstat_times(cmd_stats_t *rs, cmd_stats_t *rt);
extern void rqstat_to_buffer(char *buf, char *comm, cmd_stats_t *stats);
extern int readResponse(ptcx_t ptcx, SOCKET sock, char *buffer, int buflen);
extern int sendCommand(ptcx_t ptcx, SOCKET sock, char *command);
extern int doCommandResponse(ptcx_t ptcx, SOCKET sock, char *command, char *response, int resplen);
extern int sendOutput(int fd, char *command);
extern int retrMsg(ptcx_t ptcx, char *buffer, int maxBytes, SOCKET sock);
extern void trimEndWhite (char *buff);
unsigned long rangeNext (range_t *, unsigned long );
void rangeSetFirstLast (range_t *, unsigned long , unsigned long , int );
void rangeSetFirstCount (range_t *, unsigned long , unsigned long , int );
void rangeSplit (range_t *whole, range_t *sub, int pnum, int tnum);
extern void cmdStatsInit (cmd_stats_t *p);
/* routines in sysdep.c */
extern void MS_usleep(unsigned int microsecs);
extern void MS_sleep(unsigned int secs);
/* routines in errexit.c */
extern void errexit(FILE *dfile, const char *, ...);
extern int returnerr(FILE *dfile, const char *, ...);
extern int d_printf(FILE *dfile, const char *, ...);
extern int t_printf(int fd, const char *buffer, size_t count, const char *format, ...);
extern char *neterrstr(void);
/* routines in smtp.c */
/* TRANSITION functions */
extern void pishStatsFormat (protocol_t *pp, const char *extra, char *buf);
extern void pishStatsInit(pmail_command_t, cmd_stats_t *, int pN, int tN);
extern void pishStatsUpdate(protocol_t *, cmd_stats_t *, cmd_stats_t *);
extern void pishStatsOutput(protocol_t *, cmd_stats_t *, char *);
extern int SmtpParseStart (pmail_command_t , char *, param_list_t *);
extern int SmtpParseEnd (pmail_command_t , string_list_t *, param_list_t *);
extern void *sendSMTPStart(ptcx_t ptcx, pmail_command_t, cmd_stats_t *);
extern int sendSMTPLoop(ptcx_t ptcx, pmail_command_t, cmd_stats_t *, void *);
extern void sendSMTPEnd(ptcx_t ptcx, pmail_command_t, cmd_stats_t *, void *);
/* routines in pop3.c */
extern int Pop3ParseStart (pmail_command_t , char *, param_list_t *);
extern int Pop3ParseEnd (pmail_command_t , string_list_t *, param_list_t *);
extern void *doPop3Start(ptcx_t ptcx, pmail_command_t, cmd_stats_t *);
extern int doPop3Loop(ptcx_t ptcx, pmail_command_t, cmd_stats_t *, void *);
extern void doPop3End(ptcx_t ptcx, pmail_command_t, cmd_stats_t *, void *);
/* routines in imap4.c */
extern int Imap4ParseStart (pmail_command_t , char *, param_list_t *);
extern int Imap4ParseEnd (pmail_command_t , string_list_t *, param_list_t *);
extern void *doImap4Start(ptcx_t ptcx, pmail_command_t, cmd_stats_t *);
extern int doImap4Loop(ptcx_t ptcx, pmail_command_t, cmd_stats_t *, void *);
extern void doImap4End(ptcx_t ptcx, pmail_command_t, cmd_stats_t *, void *);
/* routines in http.c */
extern int HttpParseStart (pmail_command_t , char *, param_list_t *);
extern int HttpParseEnd (pmail_command_t , string_list_t *, param_list_t *);
extern void HttpStatsFormat (protocol_t *pp, const char *extra, char *buf);
extern void HttpStatsInit(pmail_command_t, cmd_stats_t *, int pN, int tN);
extern void HttpStatsUpdate(protocol_t *, cmd_stats_t *, cmd_stats_t *);
extern void HttpStatsOutput(protocol_t *, cmd_stats_t *, char *);
extern void *doHttpStart(ptcx_t ptcx, pmail_command_t, cmd_stats_t *);
extern int doHttpLoop(ptcx_t ptcx, pmail_command_t, cmd_stats_t *, void *);
extern void doHttpEnd(ptcx_t ptcx, pmail_command_t, cmd_stats_t *, void *);
/* routines in wmap.c */
extern int WmapParseStart (pmail_command_t , char *, param_list_t *);
extern int WmapParseEnd (pmail_command_t , string_list_t *, param_list_t *);
extern void WmapStatsFormat (protocol_t *pp, const char *extra, char *buf);
extern void WmapStatsInit(pmail_command_t, cmd_stats_t *, int pN, int tN);
extern void WmapStatsUpdate(protocol_t *, cmd_stats_t *, cmd_stats_t *);
extern void WmapStatsOutput(protocol_t *, cmd_stats_t *, char *);
extern void *doWmapStart(ptcx_t ptcx, pmail_command_t, cmd_stats_t *);
extern int doWmapLoop(ptcx_t ptcx, pmail_command_t, cmd_stats_t *, void *);
extern void doWmapEnd(ptcx_t ptcx, pmail_command_t, cmd_stats_t *, void *);
/* routines in parse.c */
extern char *string_tolower(char *string);
extern char *string_unquote(char *string);
extern int cmdParseNameValue (pmail_command_t cmd, char *name, char *tok);
extern int time_atoi(const char *pstr);
extern int load_commands(char *commands);
extern param_list_t *paramListInit (void);
/* paramListAdd returns: 1 update existing value, 0 new, -1 out of memory */
extern int paramListAdd (param_list_t *list, const char *name, const char *value);
/* paramListGet returns value or NULL */
extern char *paramListGet (param_list_t *list, const char *name);
extern param_list_t *g_default_params; /* default section params */
extern string_list_t *stringListInit (const char *value);
extern int stringListAdd (string_list_t *list, const char *value);
extern void stringListFree (string_list_t *list);
/* routines in timefunc.c */
extern double timevaldouble(struct timeval *);
extern void doubletimeval(const double, struct timeval *);
extern double compdifftime_double(struct timeval *End, struct timeval *Strt);
/* routines in main.c */
extern char *safe_inet_ntoa(struct in_addr ina, char *psz);
extern SOCKET connectSocket(ptcx_t ptcx, resolved_addr_t *, char *protocol);
extern int set_abortive_close(SOCKET sock);
extern void throttle(ptcx_t ptcx, mail_command_t *comm, cmd_stats_t *timer);
/* routines in client.c */
extern void beginShutdown (void);
extern int clientInit(ptcx_t ptcx);
extern int clientLoop(ptcx_t ptcx);
extern THREAD_RET clientThread(void *);
extern void clientSummary(ptcx_t ptcxs, int ntcxs, int ii, int outfd);
extern THREAD_RET summaryThread(void *);
extern int clientProc(int pnum, SOCKET outfd, unsigned int timeleft, unsigned int thread_stagger_usec);
extern void MS_idle(ptcx_t ptcx, int idleSecs);
extern int resolve_addrs(char *host, char *protocol, struct hostent *host_phe,
struct protoent *proto_ppe, unsigned long *addr,
short *type);
#if 0
extern void dumpevent(ptcx_t ptcx, event_timer_t *pevent);
extern void dumptimer(ptcx_t ptcx, cmd_stats_t *rqsttimer);
extern int clientStats(ptcx_t ptcx);
unsigned long get_next_login(ptcx_t ptcx, mail_command_t *comm, cmd_stats_t *ptimer);
unsigned long get_next_address(ptcx_t ptcx, mail_command_t *comm, cmd_stats_t *ptimer);
#endif
#undef VERSION
#define VERSION "4.2"
#ifdef _DEBUG
#define MAILCLIENT_VERSION "mailclient (" VERSION " DEBUG built " __DATE__ " " __TIME__ ")"
#else
#define MAILCLIENT_VERSION "mailclient (" VERSION " built " __DATE__ " " __TIME__ ")"
#endif
FILE *fdopen(int fildes, const char *mode);
#ifndef _WIN32
extern int getopt(int, char *const *, const char *);
#endif
#ifndef __OSF1__
#ifndef __LINUX__
extern long random(void);
#endif
extern void srandom(unsigned);
#endif
#endif /* !__BENCH_H__ */

Просмотреть файл

@ -1,908 +0,0 @@
/* -*- Mode: C; c-file-style: "stroustrup"; comment-column: 40 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape Mailstone utility,
* released March 17, 2000.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s): Dan Christian <robodan@netscape.com>
* Marcel DePaolis <marcel@netcape.com>
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License Version 2 or later (the "GPL"), in
* which case the provisions of the GPL are applicable instead of
* those above. If you wish to allow use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the NPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the NPL or the GPL.
*/
/*
client.c handles thread creation
login, loop, logout
status report generation
throttling (not supported yet)
thread joining
*/
#include "bench.h"
static int StartedThreads = 0; /* counter semaphore for children */
static int FinishedThreads = 0; /* counter semaphore for children */
#ifdef _WIN32
#define DEBUG_FILE "mstone-debug"
#define LOG_FILE "mstone-log"
#else
#define DEBUG_FILE "mstone-debug"
#define LOG_FILE "mstone-log"
#endif /* _WIN32 */
/*
This is a sleep that knows about test end.
Should also do throttling.
We dont check for signals because the only signal expected is test end
*/
void
MS_idle(ptcx_t ptcx, int idleSecs)
{
int secsLeft = 0;
secsLeft = gt_shutdowntime - time(0L);
D_PRINTF(debugfile, "secsLeft=%d, idleSecs=%d\n", secsLeft, idleSecs);
if (secsLeft <= 0) { /* time is up, start exiting */
if (gf_timeexpired < EXIT_SOON)
gf_timeexpired = EXIT_SOON;
return;
}
if (idleSecs > secsLeft) idleSecs = secsLeft;
if (idleSecs <= 0) return;
MS_sleep(idleSecs);
}
/* used by POP, SMTP, IMAP4 methods */
void
throttle(ptcx_t ptcx, mail_command_t *comm, cmd_stats_t *timer )
{
int chokeSecs = 0;
struct timeval exittime;
/* check if we need to throttle this puppy */
if (comm->throttle <= 0)
return;
/* we probably have not reached NETCLOSE yet, so we do not
know what timer->exittime is */
timeval_stamp(&exittime);
/* time to sleep = throttle - (exittime - entertime) */
chokeSecs = comm->throttle - ( exittime.tv_sec - ptcx->starttime.tv_sec );
/* if chokeSecs is negative, don't bother sleeping */
if (chokeSecs > 0) {
d_printf(debugfile, "throttle=%d, chokeSecs=%d\n",
comm->throttle, chokeSecs);
MS_idle(ptcx, chokeSecs);
}
} /* end throttle */
/*
* Perform the given command block
*
* commNum = the number of the comm (offset in loaded_comm_list[])
*
* returns 1
*/
static int
do_command(ptcx_t ptcx, /* thread state */
int commNum) /* command block number */
{
mail_command_t *comm = &g_loaded_comm_list[commNum];
cmd_stats_t *cmd_stats = &(ptcx->cmd_stats[commNum]);
int cnt, cntEnd; /* loop counters */
void *state = NULL;
cntEnd = comm->numLoops+1; /* transfer count +1 */
D_PRINTF(debugfile, "do_command start t=%lu commNum=%d cntEnd=%d\n",
time(0L), commNum, cntEnd);
/* Start and End are special loop cases to make summations easier */
for (cnt = 0; cnt <= cntEnd; cnt++) {
if (gf_timeexpired >= EXIT_FAST) /* no more calls */
break;
if (gf_timeexpired >= EXIT_SOON) {
if (!state) break; /* no shutdown to do */
cnt = cntEnd; /* go to shutdown */
}
D_PRINTF(debugfile, "do_command t=%lu count=%d of %d\n",
time(0L), cnt, cntEnd);
if (0 == cnt) { /* first time */
cmd_stats->totalcommands++; /* track command blocks trys */
state = (*(comm->proto->cmdStart)) (ptcx, comm, cmd_stats);
if (NULL == state) {
D_PRINTF(debugfile, "do_command Start returned NULL\n");
break;
}
if (comm->idleTime && (gf_timeexpired < EXIT_SOON)) {
D_PRINTF(debugfile,"do_command delay %d after Setup\n",
comm->idleTime);
event_start(ptcx, &cmd_stats->idle);
MS_idle(ptcx, comm->idleTime);
event_stop(ptcx, &cmd_stats->idle);
}
}
else if ((cntEnd == cnt) && comm->proto->cmdEnd) { /* last */
(*(comm->proto->cmdEnd)) (ptcx, comm, cmd_stats, state);
break; /* done with loop */
}
else if (comm->proto->cmdLoop) { /* do transfers */
int rc;
rc = (*(comm->proto->cmdLoop)) (ptcx, comm, cmd_stats, state);
if (rc < 0) {
D_PRINTF(debugfile, "do_command Loop returned error/done\n");
cnt = cntEnd -1; /* end loop */
}
/* do loopDelay even if error/done */
if (comm->loopDelay && (gf_timeexpired < EXIT_SOON)) {
D_PRINTF(debugfile,"do_command delay %d in loop\n",
comm->loopDelay);
event_start(ptcx, &cmd_stats->idle);
MS_idle(ptcx, comm->loopDelay);
event_stop(ptcx, &cmd_stats->idle);
}
}
}
/* do blockTime even if we hit an error connecting */
if (comm->blockTime && (gf_timeexpired < EXIT_SOON)) {
D_PRINTF(debugfile,"do_command delay %d after Block\n",
comm->blockTime);
event_start(ptcx, &cmd_stats->idle);
MS_idle(ptcx, comm->blockTime);
event_stop(ptcx, &cmd_stats->idle);
}
D_PRINTF(debugfile, "do_command end t=%lu commNum=%d cntEdn=%d\n",
time(0L), commNum, cntEnd);
return 1; /* return connections */
} /* END do_command() */
/*
Initialize sub process context
*/
int
clientInit(ptcx_t ptcx)
{
ptcx->dfile = stderr;
if (gn_debug) {
/* open a debug log file */
char debug_file_name[255];
fflush(stderr);
if (ptcx->threadnum >= 0) {
sprintf(debug_file_name, "%s.%d.%d",
DEBUG_FILE, ptcx->processnum, ptcx->threadnum);
} else {
sprintf(debug_file_name, "%s.%d",
DEBUG_FILE, ptcx->processnum);
}
ptcx->dfile = fopen(debug_file_name, "w+");
if (ptcx->dfile == NULL) {
/*returnerr(stderr, "Can't open debug file\n");
return -1;*/
gn_debug = 0;
d_printf (stderr, "Can't open debug file. Debug mode disabled\n");
}
D_PRINTF(debugfile, "Running in debug mode\n");
}
if (gn_record_telemetry) {
/* open a transaction log file. */
char log_file_name[255];
sprintf(log_file_name, "%s.%d.%d",
LOG_FILE, ptcx->processnum, ptcx->threadnum);
ptcx->logfile = open(log_file_name,
O_CREAT | O_TRUNC | O_WRONLY, 0664);
returnerr(debugfile,"Log file is %s [%d]\n", log_file_name, ptcx->logfile);
} else {
ptcx->logfile = -1;
}
/* Initialize random number generator */
SRANDOM(ptcx->random_seed);
D_PRINTF(debugfile, "Random seed: 0x%08x\n", ptcx->random_seed );
stats_init(&ptcx->timestat);
ptcx->timestat.total_num_of_commands = gn_number_of_commands;
return 0;
}
/* Continuously handle command blocks until time is up
*/
int
clientLoop(ptcx_t ptcx)
{
for(ptcx->blockCount = 0; gf_timeexpired < EXIT_SOON; ) {
int comm_index = 0;
if (gn_number_of_commands > 1) {
int ran_number;
/* Handle the weighted distribution of commands */
/* HAVE FILELIST */
D_PRINTF(debugfile, "Total weight %d\n", gn_total_weight);
/* random number between 0 and totalweight-1 */
ran_number = (RANDOM() % gn_total_weight);
D_PRINTF(debugfile, "random %ld\n", ran_number );
/* loop through pages, find correct one
* while ran_number is positive, decrement it
* by the weight of the current page
* example: ran_number is 5, pages have weights of 10 and 10
* first iteration comm_index = 0, ran_number = -5
* iteration halted, comm_index = 0
*/
comm_index = -1;
while (ran_number >= 0) {
comm_index++;
D_PRINTF(debugfile, "Current command index %d: %ld - %d\n",
comm_index, ran_number,
g_loaded_comm_list[comm_index].weight
);
ran_number -= g_loaded_comm_list[comm_index].weight;
}
if (comm_index >= gn_number_of_commands) { /* shouldnt happen */
D_PRINTF(debugfile, "Command weight overrun %d %d\n",
ran_number, gn_total_weight);
comm_index--;
}
/*D_PRINTF(debugfile, "Final page index %d\n", comm_index );*/
}
/* run the command */
ptcx->connectCount += do_command(ptcx, comm_index);
++ptcx->blockCount;
if (gf_timeexpired >= EXIT_SOON) break; /* done, dont throttle */
/* For the single processes/thread case, this should be exact */
if ((gn_maxBlockCnt) /* check for max loops */
&& (ptcx->blockCount >= gn_maxBlockCnt)) {
D_PRINTF (debugfile, "Saw enough loops %d, exiting\n",
ptcx->blockCount);
beginShutdown (); /* indicate early exit */
break;
}
/* throttle code mikeb@netscape.com
* keeps client from going faster than client_throttle
* operations per minute
*/
if (gn_client_throttle &&
(ptcx->timestat.endtime.tv_sec > ptcx->timestat.starttime.tv_sec)) {
timeval_stamp(&(ptcx->timestat.endtime));
while ( 60 * ptcx->connectCount /
(ptcx->timestat.endtime.tv_sec - ptcx->timestat.starttime.tv_sec)
> gn_client_throttle ) {
D_PRINTF(debugfile, "%.2f > %d, throttling\n",
( 60 * ptcx->connectCount /
(ptcx->timestat.endtime.tv_sec - ptcx->timestat.starttime.tv_sec) ),
gn_client_throttle);
/* sleep a little */
MS_usleep( 100 );
} /* end while too fast */
}
} /* END while blockCount */
return 0;
}
/*
Thread of execution.
Also works in un-threaded case.
Initialize, do some system housekeeping, run test, housekeeping, clean up
*/
THREAD_RET
clientThread(void *targ)
{
time_t currentTime;
struct tm *tmptm;
char timeStamp[DATESTAMP_LEN];
int ret = 0;
tcx_t *ptcx = (ptcx_t)targ;
/*char buf[256];*/
if (clientInit(ptcx)) { /* should never fail */
#ifdef USE_PTHREADS
if (ptcx->threadnum >= 0)
pthread_exit((void *)((1 << 16) | ptcx->threadnum));
return NULL;
#else
return;
#endif
}
/*sprintf(buf, "NOTICE: client process=%d thread=%d started\n",
ptcx->processnum, ptcx->threadnum);
sendOutput(ptcx->ofd, buf);*/
if (gn_debug) {
/* write current time to debug file */
time(&currentTime);
tmptm = localtime(&currentTime);
strftime(timeStamp, DATESTAMP_LEN, "%Y%m%d%H%M%S", tmptm);
D_PRINTF(debugfile, "Time Stamp: %s\n", timeStamp);
D_PRINTF(debugfile, "mailstone run dateStamp=%s\n", gs_dateStamp);
}
#ifdef _WIN32
#define WAIT_INFINITY 100000000
/* Tell parent we're ready */
InterlockedIncrement(&StartedThreads);
#else
++StartedThreads; /* thread safe??? */
#endif /* _WIN32 */
timeval_stamp(&(ptcx->timestat.starttime));
D_PRINTF(debugfile, "entering clientLoop\n");
ret = clientLoop(ptcx); /* do the work */
timeval_stamp(&(ptcx->timestat.endtime));
D_PRINTF(debugfile, "Test run complete\n" );
/* write current time to debug file */
time(&currentTime);
tmptm = localtime(&currentTime);
strftime(timeStamp, DATESTAMP_LEN, "%Y%m%d%H%M%S", tmptm);
D_PRINTF(debugfile, "Time Stamp: %s\n", timeStamp);
if (gn_record_telemetry && (ptcx->logfile > 0)) {
close(ptcx->logfile);
ptcx->logfile = -1;
}
D_PRINTF(debugfile, "client exiting.\n" );
if (gn_debug && ptcx->dfile) {
fflush(ptcx->dfile);
if (ptcx->dfile != stderr) {
fclose(ptcx->dfile);
ptcx->dfile = stderr;
}
}
/*sprintf(buf, "NOTICE: client process=%d thread=%d ending\n",
ptcx->processnum, ptcx->threadnum);
sendOutput(ptcx->ofd, buf);*/
#ifdef _WIN32
/* tell parent we're done */
InterlockedIncrement(&FinishedThreads);
#else /* _WIN32 */
++FinishedThreads; /* thread safe??? */
#ifdef USE_PTHREADS
if (ptcx->threadnum >= 0)
pthread_exit((void *)((ret << 16) | ptcx->threadnum));
#endif
return NULL;
#endif /* _WIN32 */
} /* END clientThread() */
/*
The FORMAT format is:
FORMAT: client=<NUMBER> <TYPE>:<NAME>\t<VALUE>
TYPE is one of: TIMER, PROTOCOL, LINE
Everything breaks down to attribute=value pairs.
"attribute=" is literal, the listed value names the field
Attribute names must be unique with each timer.
The [] and {} indicate timers and protocols respectively.
everything else is a literal (including whitespace).
The protocols and timers will be expanded with simple text
substitutions.
The literal text is as high in the description as possible.
The processing splits out the values based on surrounding text.
*/
/*
Output the format that the summaries will be in.
This call the protocol specific formats, then outputs
the complete line formats
*/
void
clientSummaryFormat(int clientnum, int outfd)
{
char buf[SIZEOF_SUMMARYTEXT], *cp;
char extra[96];
protocol_t *pp;
sprintf (extra, "client=%d", clientnum); /* extra stuff on each line */
/* Define the contents of each protocol */
for (pp=g_protocols; pp->name != NULL; ++pp) {
if (!pp->cmdCount) continue; /* not used */
(pp->statsInit)(NULL, &(pp->stats), 0, 0); /* init stats (HERE?) */
(pp->statsFormat)(pp, extra, buf); /* output lines of format info */
sendOutput(outfd, buf);
}
/* Define the periodic update summaries */
/* This is the most common message, so keep is as short as practical */
cp = buf;
sprintf(cp,
"<FORMAT %s LINE=SUMMARY-TIME><TS %s>",
extra,
"client=client t=time blocks=blocks");
for (; *cp; ++cp); /* skip to the end of the string */
for (pp=g_protocols; pp->name != NULL; ++pp) {
if (!pp->cmdCount) continue; /* not used */
sprintf(cp, "\t<%s {%s}/>", pp->name, pp->name);
for (; *cp; ++cp); /* skip to the end of the string */
}
strcat (cp, "</TS></FORMAT>\n");
sendOutput(outfd, buf);
/* BLOCK-STATISTICS format */
for (pp=g_protocols; pp->name != NULL; ++pp) {
cp = buf;
sprintf(cp,
"<FORMAT %s LINE=BLOCK-STATISTICS-%s><BS-%s %s>",
extra, pp->name, pp->name,
"client=client thread=thread t=time blockID=blockID");
for (; *cp; ++cp); /* skip to the end of the string */
sprintf(cp, "\t<%s {%s}/>", pp->name, pp->name);
for (; *cp; ++cp); /* skip to the end of the string */
sprintf (cp, "</BS-%s></FORMAT>\n", pp->name);
sendOutput(outfd, buf);
}
/* Notice Format */
sprintf(buf,
"<FORMAT %s LINE=NOTICE-1>%s</FORMAT>\n",
extra,
"<NOTICE client=client ... ");
sendOutput(outfd, buf);
/* Abort Format */
sprintf(buf,
"<FORMAT %s LINE=NOTICE-2>%s</FORMAT>\n",
extra,
"<ABORT client=client ... ");
sendOutput(outfd, buf);
}
/*
Output the block information for each thread
*/
void
clientBlockSummary(ptcx_t ptcxs, int ntcxs, int clientnum, int outfd)
{
time_t curtime;
protocol_t *pp;
int jj, kk;
char buf[SIZEOF_SUMMARYTEXT], *bp;
D_PRINTF(stderr, "clientSummaryBS starting.\n" );
curtime = time(0L);
for (kk = 0; kk < gn_number_of_commands; ++kk) { /* all commands */
for (jj = 0; jj < ntcxs; ++jj) { /* all threads */
if (0 == ptcxs[jj].cmd_stats[kk].totalcommands) /* nothing */
continue;
pp = g_loaded_comm_list[kk].proto;
/* output proto independent part */
bp = buf;
sprintf (bp,
"<BS-%s client=%d thread=%d t=%lu blockID=%d>",
pp->name, clientnum, jj, curtime,
g_loaded_comm_list[kk].blockID);
for (; *bp; ++bp); /* find end of buffer */
sprintf (bp,
"\t<%s blocks=%ld ",
pp->name,
ptcxs[jj].cmd_stats[kk].totalcommands);
for (; *bp; ++bp); /* find end of buffer */
(pp->statsOutput)(pp, &(ptcxs[jj].cmd_stats[kk]), bp);
for (; *bp; ++bp); /* find end of buffer */
sprintf (bp, "/></BS-%s>\n", pp->name); /* end it */
sendOutput(outfd, buf);
}
}
D_PRINTF(stderr, "clientSummaryBS done.\n");
}
/* Output the periodic activity summary */
void
clientTimeSummary(ptcx_t ptcxs, int ntcxs, int clientnum, int outfd)
{
time_t curtime;
int blockCount = 0, connectCount = 0;
protocol_t *pp;
int jj, kk;
char buf[SIZEOF_SUMMARYTEXT];
char rqsttextbuf[SIZEOF_RQSTSTATSTEXT+1];
static int oldThreadStarts= 0;
static int oldThreadEnds= 0;
D_PRINTF(stderr, "clientTimeSummary starting.\n" );
curtime = time(0L);
for (pp=g_protocols; pp->name != NULL; ++pp) { /* zero protocol stats */
if (!pp->cmdCount) continue; /* not used */
cmdStatsInit (&(pp->stats)); /* clear proto independent part */
(pp->statsInit)(NULL, &(pp->stats), 0, 0); /* clear proto part */
}
/* sum by protocol all commands, all threads */
for (jj = 0; jj < ntcxs; ++jj) {
blockCount += ptcxs[jj].blockCount;
connectCount += ptcxs[jj].connectCount;
for (kk = 0; kk < gn_number_of_commands; ++kk) {
pp = g_loaded_comm_list[kk].proto;
(pp->statsUpdate)(pp, &pp->stats, &(ptcxs[jj].cmd_stats[kk]));
}
}
/* output proto independent part */
sprintf(buf, "<TS client=%d t=%lu blocks=%d>",
clientnum, curtime, blockCount);
for (pp=g_protocols; pp->name != NULL; ++pp) { /* output proto parts */
if (!pp->cmdCount) continue; /* not used */
(pp->statsOutput)(pp, &pp->stats, rqsttextbuf);
/* The \t seperates sections for report parsing */
sprintf(&buf[strlen(buf)], "\t<%s blocks=%ld %s/>",
pp->name, pp->stats.totalcommands,
rqsttextbuf);
}
strcat(buf, "</TS>\n"); /* end it */
sendOutput(outfd, buf);
/* do additional status updates */
if (oldThreadStarts != StartedThreads) {
sprintf(buf, "<NOTICE client=%d threadStarts=%d/>\n",
clientnum, StartedThreads - oldThreadStarts);
sendOutput(outfd, buf);
oldThreadStarts = StartedThreads;
}
if (oldThreadEnds != FinishedThreads) {
sprintf(buf, "<NOTICE client=%d threadFinishes=%d/>\n",
clientnum, FinishedThreads - oldThreadEnds);
sendOutput(outfd, buf);
oldThreadEnds = FinishedThreads;
}
if (gn_maxerrorcnt) { /* check for max error count */
int errors = 0;
for (pp=g_protocols; pp->name != NULL; ++pp) { /* sum total */
if (!pp->cmdCount) continue; /* not used */
errors += pp->stats.combined.errs;
}
if (errors > gn_maxerrorcnt) {
returnerr (stderr,
"<ABORT client=%d errorCount=%ld errorLimit=%ld/>\n",
clientnum, errors, gn_maxerrorcnt);
beginShutdown ();
}
}
if ((gn_maxBlockCnt)
&& (blockCount >= gn_maxBlockCnt)) { /* check for max loops */
returnerr (stderr,
"<ABORT client=%d blockCount=%ld blockLimit=%ld/>\n",
clientnum, blockCount, gn_maxBlockCnt);
beginShutdown ();
}
D_PRINTF(stderr, "clientTimeSummary done.\n");
}
/*
Thread that calls clientTimeSummary at the right rate
*/
THREAD_RET
summaryThread(void *targ)
{
ptcx_t ptcxs = (ptcx_t)targ; /* thread contexts */
D_PRINTF(stderr, "summaryThread starting...\n");
/* client threads running...dump periodic stats */
while (gn_feedback_secs && (gf_timeexpired < EXIT_FAST)) {
D_PRINTF(stderr, "client %d: clientTimeSummary\n", ptcxs[0].processnum);
clientTimeSummary(ptcxs, gn_numthreads, ptcxs[0].processnum, ptcxs[0].ofd);
D_PRINTF(stderr, "client %d: waiting %d seconds before feedback\n",
ptcxs[0].processnum, gn_feedback_secs);
MS_sleep(gn_feedback_secs);
}
D_PRINTF(stderr, "summaryThread exiting...\n");
#ifdef USE_PTHREADS
pthread_exit(0);
#endif
#ifndef _WIN32
return NULL;
#endif
}
/*
Initialize per thread context
*/
void
initTcx(ptcx_t ptcx, int ofd, int pnum, int tnum)
{
int kk;
ptcx->processnum = pnum;
ptcx->threadnum = tnum;
ptcx->random_seed = (tnum << 16) + getpid();
ptcx->cmd_stats =
(cmd_stats_t *)mycalloc(sizeof(cmd_stats_t)*gn_number_of_commands);
/* do PROTO specific init */
for (kk = 0; kk < gn_number_of_commands; ++kk) {
(g_loaded_comm_list[kk].proto->statsInit)
(&g_loaded_comm_list[kk], &(ptcx->cmd_stats[kk]), pnum, tnum);
}
ptcx->ofd = ofd;
ptcx->sock = BADSOCKET_VALUE;
}
void
destroyTcx(ptcx_t ptcx)
{
if (ptcx->cmd_stats) {
free(ptcx->cmd_stats);
ptcx->cmd_stats = 0;
}
}
static time_t bailtime;
/* advance directly to shutdown phase. May be called from signal handlers */
void
beginShutdown (void)
{
if (gf_timeexpired >= EXIT_SOON) return; /* already shutting down */
gf_timeexpired = EXIT_SOON;
gt_shutdowntime = bailtime = time(0); /* advance end time to now */
/* Changing aborttime probably has no effect (wrong process) */
gt_aborttime = gt_shutdowntime + gt_stopinterval*2*EXIT_FASTEST;
}
/* This is the guts of each sub process.
The socket for data output has already be setup.
init context
start threads (if possible/needed) with proper rampup delays
wait for threads to end
*/
int
clientProc(int pnum, SOCKET outfd,
unsigned int testtime,
unsigned int thread_stagger_usec)
{
int tnum;
int ret;
ptcx_t ptcxs; /* thread contexts */
THREAD_ID summary_tid;
int status;
bailtime = gt_shutdowntime;
returnerr(stderr, "Child starting\n"); /* get our pid and time printed */
D_PRINTF(stderr, "clientProc(%d, %d, %d) starting\n",
pnum, testtime, thread_stagger_usec);
if (testtime <= 0) { /* never happens, checked in main.c */
D_PRINTF (stderr, "ABORTING testtime=%d\n", testtime);
return 0;
}
setup_signal_handlers ();
#ifndef _WIN32
alarm(testtime); /* promptly notice test end */
#endif
clientSummaryFormat (pnum, outfd);
#if defined(USE_PTHREADS) || defined(_WIN32)
if (gn_numthreads > 0) {
ptcxs = (ptcx_t)mycalloc(sizeof(tcx_t) * gn_numthreads);
for (tnum = 0; tnum < gn_numthreads; ++tnum) {
initTcx(&ptcxs[tnum], outfd, pnum, tnum);
}
/*fprintf(stderr, "launching summary\n");*/
if ((ret=sysdep_thread_create(&summary_tid, summaryThread,
(void *)ptcxs)) != 0) {
returnerr(stderr, "client %d: summary thread create failed ret=%d errno=%d: %s\n",
pnum, ret, errno, strerror(errno));
ptcxs[tnum].tid = 0;
}
/*fprintf(stderr, "summary should be running...\n");*/
for (tnum = 0; tnum < gn_numthreads; ++tnum) {
if (gf_timeexpired)
break;
/* sleep between each client thread we try to start */
if (tnum && thread_stagger_usec) {
MS_usleep(thread_stagger_usec);
if (gf_timeexpired)
break;
}
D_PRINTF(stderr, "client %d: thread %d testtime %d\n",
pnum, tnum, testtime);
if ((ret=sysdep_thread_create(&(ptcxs[tnum].tid), clientThread,
(void *)&ptcxs[tnum])) != 0) {
returnerr(stderr, "client %d: thread %d create() failed ret=%d errno=%d: %s\n",
pnum, tnum, ret, errno, strerror(errno));
ptcxs[tnum].tid = 0;
}
D_PRINTF(stderr, "client %d: thread %d created with ID %d\n",
pnum, tnum, ptcxs[tnum].tid);
}
/* threads are going, but wait for them to get through setup */
while (StartedThreads < gn_numthreads) {
int tm = time(0);
if (tm > bailtime) {
++gf_timeexpired;
bailtime += gt_stopinterval;
}
if (gf_timeexpired >= EXIT_SOON) /* failsafe if thread count bad */
break;
MS_sleep(2);
}
D_PRINTF(stderr, "client %d: started all threads.\n", pnum);
/* Wait for all threads to exit or overtime */
while (FinishedThreads < StartedThreads) {
int tm = time(0);
if (tm > bailtime) {
++gf_timeexpired;
bailtime += gt_stopinterval;
#ifndef _WIN32
if (gf_timeexpired >= EXIT_FAST) {
returnerr (stderr, "Client signaling exit, started=%d finished=%d timeexpired=%d\n",
StartedThreads, FinishedThreads, gf_timeexpired);
kill (0, SIGALRM); /* wake children */
}
#endif
}
if (gf_timeexpired >= EXIT_FASTEST) {
returnerr (stderr, "Forcing sockets closed.\n");
/* close all client sockets, to force calls to exit */
for (tnum = 0; tnum < gn_numthreads; ++tnum) {
if (BADSOCKET(ptcxs[tnum].sock)) continue;
D_PRINTF (stderr, "Closing sock=%d tnum=%d\n",
ptcxs[tnum].sock, tnum);
set_abortive_close(ptcxs[tnum].sock);
NETCLOSE(ptcxs[tnum].sock);
}
returnerr (stderr, "Forced socket close complete.\n");
break;
}
MS_sleep(1);
}
D_PRINTF (stderr, "Shutdown timeexpired=%d\n", gf_timeexpired);
if (gf_timeexpired < EXIT_FAST) {
gf_timeexpired = EXIT_FAST; /* signal summary thread to exit */
returnerr (stderr, "Clean child shutdown\n");
} else if (gf_timeexpired >= EXIT_FASTEST) {
returnerr (stderr, "Forced child shutdown\n");
} else {
returnerr (stderr, "Accellerated child shutdown\n");
}
D_PRINTF(stderr, "client %d: joining summary thread\n", pnum);
if ((ret=sysdep_thread_join(summary_tid, &status)) != 0) {
returnerr(stderr,
"client %d: summary thread join failed ret=%d errno=%d: %s\n",
pnum, ret, errno, strerror(errno));
}
#ifndef _WIN32
/* do a summary now in case we hang in joins (needed?) */
D_PRINTF(stderr, "client %d: pre-join clientTimeSummary\n", pnum);
clientTimeSummary(ptcxs, gn_numthreads, pnum, outfd);
for (tnum = 0; tnum < gn_numthreads; ++tnum) {
D_PRINTF(stderr, "client %d: joining thread %d ID %d\n",
pnum, tnum, ptcxs[tnum].tid);
if (ptcxs[tnum].tid) {
sysdep_thread_join(ptcxs[tnum].tid, &status);
D_PRINTF(stderr, "client %d: thread %d joined ID %d, ret=%d status=%d\n",
pnum, tnum, ptcxs[tnum].tid, ret, status);
ptcxs[tnum].tid = 0;
}
}
#endif /* _WIN32 */
} else
#endif /* USE_PTHREADS || _WIN32*/
{ /* thread un-available or 0 */
gn_numthreads = 1;
ptcxs = (ptcx_t)mycalloc(sizeof(tcx_t) * gn_numthreads);
initTcx(&ptcxs[0], outfd, pnum, -1);
D_PRINTF(stderr, "client %d: testtime: %d\n", pnum);
/* set initial data point */
D_PRINTF(stderr, "client %d: initial clientTimeSummary\n", 0);
clientTimeSummary(ptcxs, gn_numthreads, pnum, outfd);
clientThread(&ptcxs[0]);
}
/* final time summary feedback */
D_PRINTF(stderr, "client %d: final summaries\n", 0);
clientTimeSummary(ptcxs, gn_numthreads, pnum, outfd);
clientBlockSummary(ptcxs, gn_numthreads, pnum, outfd);
#if 0
for (tnum = 0; tnum < gn_numthreads; ++tnum) { /* extra reporting */
D_PRINTF(stderr, "client %d: thread %d stats\n", pnum, tnum);
clientStats(&ptcxs[tnum]);
}
#endif
for (tnum = 0; tnum < gn_numthreads; ++tnum) { /* clean up */
D_PRINTF(stderr, "client %d: thread %d destroyed\n", pnum, tnum);
destroyTcx(&ptcxs[tnum]);
}
D_PRINTF(stderr, "child: %d done\n", pnum);
return 0;
}

Просмотреть файл

@ -1,203 +0,0 @@
/* -*- Mode: C; c-file-style: "stroustrup"; comment-column: 40 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape Mailstone utility,
* released March 17, 2000.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1997-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s): Dan Christian <robodan@netscape.com>
* Marcel DePaolis <marcel@netcape.com>
* Mike Blakely
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License Version 2 or later (the "GPL"), in
* which case the provisions of the GPL are applicable instead of
* those above. If you wish to allow use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the NPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the NPL or the GPL.
*/
/* calls for general error handling */
#include "bench.h"
#ifdef HAVE_VPRINTF
#define VPRINTF(stderr, format, args) vfprintf((stderr), (format), (args))
#else
#ifdef HAVE_DOPRNT
#define VPRINTF(stderr, format, args) _doprnt((format), (args), (stderr))
#endif /* HAVE_DOPRNT */
#endif /* HAVE_VPRINTF */
/* print an error message and exit 1 */
void
errexit(FILE *dfile, const char *format, ...)
{
time_t t=time(0L) - gt_startedtime;
va_list args;
#if defined (HAVE_SNPRINTF) && defined (HAVE_VPRINTF)
char buff[1024];
int r;
#endif
va_start(args, format);
#if defined (HAVE_SNPRINTF) && defined (HAVE_VPRINTF)
/* puts as one chunk so that output doesnt get mixed up */
r = snprintf(buff, sizeof(buff),
"%s[%d]\tt=%lu EXITING: ", gs_thishostname, gn_myPID, t);
vsnprintf(buff+r, sizeof(buff) - r, format, args);
fputs (buff, stderr);
fflush(stderr);
if (gn_debug && dfile && (dfile != stderr)) {
fputs (buff, dfile);
fflush(dfile);
}
#else
fprintf(stderr,
"%s[%d]\tt=%lu EXITING: ", gs_thishostname, gn_myPID, t);
VPRINTF(stderr, format, args);
fflush(stderr);
if (gn_debug && dfile && (dfile != stderr)) {
fprintf(dfile,
"%s[%d]\tt=%lu EXITING: ", gs_thishostname, gn_myPID, t);
VPRINTF(dfile, format, args);
fflush(dfile);
}
#endif
va_end(args);
exit(1);
}
/* This is the main feedback path for errors and status */
/* print an error message and return -1 */
/* Also log to the debug file if available */
int
returnerr(FILE *dfile, const char *format, ...)
{
time_t t=time(0L) - gt_startedtime;
va_list args;
#if defined (HAVE_SNPRINTF) && defined (HAVE_VPRINTF)
char buff[1024];
int r;
#endif
va_start(args, format);
#if defined (HAVE_SNPRINTF) && defined (HAVE_VPRINTF)
/* puts as one chunk so that output doesnt get mixed up */
r = snprintf(buff, sizeof(buff),
"%s[%d]\tt=%lu: ", gs_thishostname, gn_myPID, t);
vsnprintf(buff+r, sizeof(buff) - r, format, args);
fputs (buff, stderr);
fflush(stderr);
if (gn_debug && dfile && (dfile != stderr)) {
fputs (buff, dfile);
fflush(dfile);
}
#else
fprintf(stderr,
"%s[%d]\tt=%lu: ", gs_thishostname, gn_myPID, t);
VPRINTF(stderr, format, args);
fflush(stderr);
if (gn_debug && dfile && (dfile != stderr)) {
fprintf(dfile,
"%s[%d]\tt=%lu: ", gs_thishostname, gn_myPID, t);
VPRINTF(dfile, format, args);
fflush(dfile);
}
#endif
va_end(args);
return(-1);
}
/* print a debug message and then flush */
int
d_printf(FILE *dfile, const char *format, ...)
{
va_list args;
va_start(args, format);
if (dfile) {
fprintf(dfile, "%s: ", gs_thishostname);
VPRINTF(dfile, format, args);
}
va_end(args);
if (dfile) fflush(dfile);
return 0;
}
/* that's it */
/*
Like d_printf, but for transaction logs.
*/
int
t_printf(int fd, const char *buffer, size_t count, const char *format, ...)
{
time_t t=time(0L) - gt_startedtime;
va_list args;
char buff[1024];
int r;
if (fd <= 0) return 0;
va_start(args, format);
#if defined (HAVE_SNPRINTF) && defined (HAVE_VPRINTF)
r = snprintf(buff, sizeof(buff), /* stick in standard info */
"<LOG t=%lu length=%d ", t, count);
snprintf(buff + r, sizeof(buff) - r, format, args);
strcat (buff, ">\n");
write (fd, buff, strlen(buff));
if (count)
write (fd, buffer, count); /* write the (possibly binary) data */
r = snprintf(buff, sizeof(buff), /* terminate entry cleanly */
"\n</LOG t=%lu length=%d>\n", t, count);
write (fd, buff, strlen(buff));
#else
if (count)
write (fd, buffer, count); /* write the (possibly binary) data */
#endif
va_end(args);
return 0;
}
/* that's it */
/* returns the last network error as a string */
char *
neterrstr(void) {
static char buf[200];
#ifdef _WIN32
sprintf(buf, "WSAGetLastError()=%d", WSAGetLastError());
WSASetLastError(0);
#else /* !_WIN32 */
sprintf(buf, "errno=%d: %s", errno, strerror(errno));
errno = 0;
#endif /* _WIN32 */
return buf;
}

Просмотреть файл

@ -1,405 +0,0 @@
/* -*- Mode: C; c-file-style: "stroustrup"; comment-column: 40 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape Mailstone utility,
* released March 17, 2000.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s): Dan Christian <robodan@netscape.com>
* Marcel DePaolis <marcel@netcape.com>
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License Version 2 or later (the "GPL"), in
* which case the provisions of the GPL are applicable instead of
* those above. If you wish to allow use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the NPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the NPL or the GPL.
*/
/* http.c: HTTP protocol test */
#include "bench.h"
#include "http-util.h"
#define MAX_HTTP_RESPONSE_LEN (2*1024) /* size of sliding buffer */
/*
these are protocol dependent timers for Pop, Imap, Smtp, Http
There is one of these for every command in every thread.
*/
typedef struct http_stats {
event_timer_t connect; /* initial connections */
event_timer_t reconnect; /* re-connections */
event_timer_t msgread; /* AKA retrieve */
event_timer_t logout; /* AKA dis-connect */
/* no local storage */
} http_stats_t;
/* These are common to POP, IMAP, SMTP, HTTP */
typedef struct http_command {
resolved_addr_t hostInfo; /* Host, port, and IP cache */
char * httpCommand; /* Old: single HTTP command */
#if 0
string_list_t getFirstCmds; /* GET commands after connect */
string_list_t getLoopCmds; /* GET commands, each loop */
string_list_t getLastCmds; /* GET commands before disconnect */
#endif
} http_command_t;
/*
State during command execution.
*/
typedef struct _doHTTP_state {
int nothingHere;
} doHTTP_state_t;
static void doHttpExit (ptcx_t ptcx, doHTTP_state_t *me);
static int HttpParseNameValue (pmail_command_t cmd, char *name, char *tok);
/*
Set defaults in command structure
*/
int
HttpParseStart (pmail_command_t cmd,
char *line,
param_list_t *defparm)
{
param_list_t *pp;
http_command_t *mycmd = (http_command_t *)mycalloc
(sizeof (http_command_t));
cmd->data = mycmd;
cmd->numLoops = 1; /* default 1 downloads */
mycmd->hostInfo.portNum = HTTP_PORT; /* get default port */
D_PRINTF(stderr, "Http Assign defaults\n");
/* Fill in defaults first, ignore defaults we dont use */
for (pp = defparm; pp; pp = pp->next) {
(void)HttpParseNameValue (cmd, pp->name, pp->value);
}
return 1;
}
/*
Fill in structure from a list of lines
*/
int
HttpParseEnd (pmail_command_t cmd,
string_list_t *section,
param_list_t *defparm)
{
http_command_t *mycmd = (http_command_t *)cmd->data;
string_list_t *sp;
/* Now parse section lines */
D_PRINTF(stderr, "Http Assign section lines\n");
/* skip first and last */
for (sp = section->next; sp->next; sp = sp->next) {
char *name = sp->value;
char *tok = name + strcspn(name, " \t=");
*tok++ = 0; /* split name off */
tok += strspn(tok, " \t=");
string_tolower(name);
tok = string_unquote(tok);
if (HttpParseNameValue (cmd, name, tok) < 0) {
/* not a known attr */
D_PRINTF(stderr,"unknown attribute '%s' '%s'\n", name, tok);
returnerr(stderr,"unknown attribute '%s' '%s'\n", name, tok);
}
}
/* check for some of the required command attrs */
if (!mycmd->hostInfo.hostName) {
D_PRINTF(stderr,"missing server for command");
return returnerr(stderr,"missing server for command\n");
}
if (!mycmd->httpCommand) {
D_PRINTF(stderr,"missing httpcommand for HTTP");
return returnerr(stderr,"missing httpcommand for HTTP\n");
}
/* see if we can resolve the mailserver addr */
if (resolve_addrs(mycmd->hostInfo.hostName, "tcp",
&(mycmd->hostInfo.host_phe),
&(mycmd->hostInfo.host_ppe),
&(mycmd->hostInfo.host_addr),
&(mycmd->hostInfo.host_type))) {
return returnerr (stderr, "Error resolving hostname '%s'\n",
mycmd->hostInfo.hostName);
} else {
mycmd->hostInfo.resolved = 1; /* mark the hostInfo resolved */
}
return 1;
}
/*
Parse arguments for http command
*/
static int
HttpParseNameValue (pmail_command_t cmd,
char *name,
char *tok)
{
http_command_t *mycmd = (http_command_t *)cmd->data;
D_PRINTF (stderr, "HttpParseNameValue(name='%s' value='%s')\n", name, tok);
/* find a home for the attr/value */
if (cmdParseNameValue(cmd, name, tok))
; /* done */
else if (strcmp(name, "server") == 0)
mycmd->hostInfo.hostName = mystrdup (tok);
else if (strcmp(name, "portnum") == 0)
mycmd->hostInfo.portNum = atoi(tok);
else if (strcmp(name, "httpcommand") == 0)
mycmd->httpCommand = mystrdup (tok);
/*stringListAdd(&mycmd->getFirstCmds, tok);*/
else {
return -1;
}
return 0;
}
/* PROTOCOL specific */
void
HttpStatsInit(mail_command_t *cmd, cmd_stats_t *p, int procNum, int threadNum)
{
assert (NULL != p);
if (!p->data) { /* create it */
p->data = mycalloc (sizeof (http_stats_t));
} else { /* zero it */
memset (p->data, 0, sizeof (http_stats_t));
}
if (cmd) { /* do sub-range calulations */
/*http_command_t *mycmd = (http_command_t *)cmd->data;
http_stats_t *stats = (http_stats_t *)p->data;*/
}
}
/* PROTOCOL specific */
void
HttpStatsUpdate(protocol_t *proto,
cmd_stats_t *sum,
cmd_stats_t *incr)
{
http_stats_t *ss = (http_stats_t *)sum->data;
http_stats_t *is = (http_stats_t *)incr->data;
event_sum(&sum->idle, &incr->idle);
event_sum(&ss->connect, &is->connect);
event_sum(&ss->msgread, &is->msgread);
event_sum(&ss->logout, &is->logout);
event_reset(&incr->combined); /* figure out total */
event_sum(&incr->combined, &incr->idle);
event_sum(&incr->combined, &is->connect);
event_sum(&incr->combined, &is->msgread);
event_sum(&incr->combined, &is->logout);
event_sum(&sum->combined, &incr->combined); /* add our total to sum-total*/
sum->totalerrs += incr->totalerrs;
sum->totalcommands += incr->totalcommands;
}
/* PROTOCOL specific */
void
HttpStatsOutput(protocol_t *proto,
cmd_stats_t *ptimer,
char *buf)
{
char eventtextbuf[SIZEOF_EVENTTEXT];
http_stats_t *stats = (http_stats_t *)ptimer->data;
*buf = 0;
/* BUG blocks done in clientSummary */
event_to_text(&ptimer->combined, eventtextbuf);
sprintf(&buf[strlen(buf)], "total=%s ", eventtextbuf);
event_to_text(&stats->connect, eventtextbuf);
sprintf(&buf[strlen(buf)], "conn=%s ", eventtextbuf);
event_to_text(&stats->msgread, eventtextbuf);
sprintf(&buf[strlen(buf)], "retrieve=%s ", eventtextbuf);
event_to_text(&stats->logout, eventtextbuf);
sprintf(&buf[strlen(buf)], "logout=%s ", eventtextbuf);
event_to_text(&ptimer->idle, eventtextbuf);
sprintf(&buf[strlen(buf)], "idle=%s ", eventtextbuf);
}
/* PROTOCOL specific */
void
HttpStatsFormat (protocol_t *pp,
const char *extra, /* extra text to insert (client=) */
char *buf)
{
static char *timerList[] = { /* must match order of StatsOutput */
"total",
"conn", "retrieve", "logout",
"idle" };
char **tp;
char *cp = buf;
int ii;
/* Define the contents of each timer
These must all the same, to that the core time functions
can be qualified. We specify each one for reduce.pl to work right.
*/
for (ii=0, tp=timerList;
ii < (sizeof (timerList)/sizeof (timerList[0]));
++ii, ++tp) {
sprintf(cp, "<FORMAT %s TIMER=[%s]>%s</FORMAT>\n",
extra, *tp,
gs_eventToTextFormat); /* match event_to_text*/
for (; *cp; ++cp); /* skip to the end of the string */
}
/* BUG blocks matches clientSummary */
sprintf(cp, "<FORMAT %s PROTOCOL={%s}>blocks=blocks ",
extra, pp->name);
for (; *cp; ++cp); /* skip to the end of the string */
for (ii=0, tp=timerList; /* same as above list (for now) */
ii < (sizeof (timerList)/sizeof (timerList[0]));
++ii, ++tp) {
sprintf (cp, "%s=[%s] ", *tp, *tp);
for (; *cp; ++cp); /* skip to the end of the string */
}
strcat (cp, "</FORMAT>\n");
}
void *
doHttpStart(ptcx_t ptcx, mail_command_t *cmd, cmd_stats_t *ptimer)
{
doHTTP_state_t *me = (doHTTP_state_t *)mycalloc (sizeof (doHTTP_state_t));
http_stats_t *stats = (http_stats_t *)ptimer->data;
http_command_t *mycmd = (http_command_t *)cmd->data;
if (!me) return NULL;
if (HttpConnect(ptcx, &mycmd->hostInfo, &stats->connect) == -1) {
return NULL;
}
/* there is no banner or login state for HTTP */
return me;
}
int
doHttpLoop (
ptcx_t ptcx,
mail_command_t *cmd,
cmd_stats_t *ptimer,
void *mystate)
{
doHTTP_state_t *me = (doHTTP_state_t *)mystate;
char command[MAX_COMMAND_LEN];
char respBuffer[MAX_HTTP_RESPONSE_LEN];
int rc;
http_stats_t *stats = (http_stats_t *)ptimer->data;
http_command_t *mycmd = (http_command_t *)cmd->data;
if (BADSOCKET(ptcx->sock)) { /* re-connect if needed */
rc = HttpConnect(ptcx, &mycmd->hostInfo, &stats->connect);
if (rc == -1) {
return -1;
}
}
/* send the HTTP command */
strcpy (command, mycmd->httpCommand);
strcat (command, " HTTP/1.0\r\n");
/* other headers go here... */
strcat(command, "\r\n");
rc = HttpCommandResponse(ptcx, cmd, mystate,
&mycmd->hostInfo, &stats->connect,
&stats->msgread,
command, respBuffer,
sizeof(respBuffer), NULL);
if (rc == 0) {
doHttpExit (ptcx, me);
return -1;
}
if (rc == -1) {
if (gf_timeexpired < EXIT_FAST) {
stats->msgread.errs++;
}
doHttpExit (ptcx, me);
return -1;
}
return 0;
}
void
doHttpEnd(ptcx_t ptcx, mail_command_t *cmd, cmd_stats_t *ptimer, void *mystate)
{
doHTTP_state_t *me = (doHTTP_state_t *)mystate;
http_stats_t *stats = (http_stats_t *)ptimer->data;
if (BADSOCKET(ptcx->sock)) return; /* closed by previous error */
#if 0
int rc;
char command[MAX_COMMAND_LEN];
char respBuffer[MAX_RESPONSE_LEN];
/* send HTTP QUIT equivalent */
sprintf(command, "QUIT%s", CRLF);
event_start(ptcx, &stats->logout);
rc = doHttpCommandResponse(ptcx, ptcx->sock, command, respBuffer);
event_stop(ptcx, &stats->logout);
if (rc == -1) {
if (gf_timeexpired < EXIT_FAST) {
stats->logout.errs++;
}
}
#else
event_start(ptcx, &stats->logout);
NETCLOSE(ptcx->sock); ptcx->sock = BADSOCKET_VALUE;
event_stop(ptcx, &stats->logout);
#endif
doHttpExit (ptcx, me);
}
void
doHttpExit (ptcx_t ptcx, doHTTP_state_t *me)
{
if (!BADSOCKET(ptcx->sock))
NETCLOSE(ptcx->sock);
ptcx->sock = BADSOCKET_VALUE;
myfree (me);
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,974 +0,0 @@
/* -*- Mode: C; c-file-style: "stroustrup"; comment-column: 40 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape Mailstone utility,
* released March 17, 2000.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s): Dan Christian <robodan@netscape.com>
* Marcel DePaolis <marcel@netcape.com>
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License Version 2 or later (the "GPL"), in
* which case the provisions of the GPL are applicable instead of
* those above. If you wish to allow use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the NPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the NPL or the GPL.
*/
/*
main.c handles all the initialization and then forks off sub processes.
*/
#include "bench.h"
/* really globalize variables */
volatile int gf_timeexpired = 0;
time_t gt_testtime = 0; /* time of test, in seconds */
time_t gt_startedtime = 0; /* when we started */
volatile time_t gt_shutdowntime = 0; /* startedtime + testtime */
time_t gt_stopinterval = 0; /* MAX (ramptime/5, 10) */
time_t gt_aborttime = 0; /* startedtime + testtime + ramptime*/
int gn_record_telemetry = 0;
int gn_total_weight = 0;
int gn_client_throttle = 0;
int gn_maxerrorcnt = 0;
int gn_maxBlockCnt = 0;
int gn_numprocs = 0;
int gn_numthreads = 0;
int gn_debug = 0;
int gn_feedback_secs = 5;
int gf_abortive_close = 0;
int gn_number_of_commands = 0;
int gf_imapForceUniqueness = 0;
char gs_dateStamp[DATESTAMP_LEN];
char gs_thishostname[MAXHOSTNAMELEN+10] = "";
char *gs_parsename = gs_thishostname; /* name used during parsing */
pid_t gn_myPID = 0;
mail_command_t *g_loaded_comm_list; /* actually a dynamic array */
protocol_t g_protocols[] = { /* array of protocol information */
{
"SMTP",
SmtpParseStart,
SmtpParseEnd,
sendSMTPStart,
sendSMTPLoop,
sendSMTPEnd,
pishStatsFormat,
pishStatsInit,
pishStatsUpdate,
pishStatsOutput,
},
{
"POP3",
Pop3ParseStart,
Pop3ParseEnd,
doPop3Start,
doPop3Loop,
doPop3End,
pishStatsFormat,
pishStatsInit,
pishStatsUpdate,
pishStatsOutput,
},
{
"IMAP4",
Imap4ParseStart,
Imap4ParseEnd,
doImap4Start,
doImap4Loop,
doImap4End,
pishStatsFormat,
pishStatsInit,
pishStatsUpdate,
pishStatsOutput,
},
{
"HTTP",
HttpParseStart,
HttpParseEnd,
doHttpStart,
doHttpLoop,
doHttpEnd,
HttpStatsFormat,
HttpStatsInit,
HttpStatsUpdate,
HttpStatsOutput,
},
{
"WMAP",
WmapParseStart,
WmapParseEnd,
doWmapStart,
doWmapLoop,
doWmapEnd,
WmapStatsFormat,
WmapStatsInit,
WmapStatsUpdate,
WmapStatsOutput,
},
{
NULL, /* terminate the list */
},
};
/* End of globals */
static time_t ramptime = 0;
static char mailmaster[MAXHOSTNAMELEN];
static NETPORT listenport = 0;
static char *commandsfilename = NULL;
static int f_usestdin = 0;
#if 0
static struct hostent mailserv_phe, mailmast_phe;
static struct protoent mailserv_ppe, mailmast_ppe;
static unsigned long mailserv_addr, mailmast_addr;
static short mailserv_type, mailmast_type; /* socket type */
#endif
static void
usage(const char *progname)
{
fprintf(stderr, "Usage: %s [options] -n <clients> -t <time> <-s | -u <commandFile>>\n\n",
progname);
fprintf(stderr, " required parameters:\n");
fprintf(stderr, " -n numprocs number of clients processes to run [1-%d]\n",
MAXPROCSPERNODE);
fprintf(stderr, " -t testtime test duration (mins) or #[hmsd]\n");
fprintf(stderr, " -s use stdin for commands\n");
fprintf(stderr, " -u commandlist file for commands\n\n");
fprintf(stderr, " options:\n");
fprintf(stderr, " -h help - this message\n\n");
fprintf(stderr, " -H name hostname for parsing HOSTS=\n");
fprintf(stderr, " -A use abortive close\n");
fprintf(stderr, " -T opsperhour client throttle\n");
fprintf(stderr, " -f summpersec frequency to send summary results\n");
fprintf(stderr, " -d debug\n");
fprintf(stderr, " -D datestamp assign a datestamp\n");
fprintf(stderr, " -N numthreads number of clients threads per process\n");
fprintf(stderr, " -m maxErrorCnt threshold to force test abort\n");
fprintf(stderr, " -M maxBlockCnt number of blocks to run\n");
fprintf(stderr, " -R ramptime test rampup time (secs)\n");
fprintf(stderr, " -v print version\n");
fprintf(stderr, " -r record all transactions\n\n");
exit(1);
} /* END usage() */
void
parseArgs(int argc, char **argv)
{
int getoptch;
extern char *optarg;
extern int optind;
/*
* PARSE THE COMMAND LINE OPTIONS
*/
while((getoptch =
getopt(argc,argv,"hf:H:T:t:u:c:m:M:n:N:R:D:Adrsv")) != EOF)
{
switch(getoptch)
{
case 'h':
usage(argv[0]);
break;
case 'H': /* name for parsing */
gs_parsename = mystrdup(optarg);
break;
case 'A':
gf_abortive_close = 1;
break;
case 'T':
/* client throttles to ops/hour */
gn_client_throttle = atoi(optarg);
break;
case 'f':
/* feedback frequency in seconds */
gn_feedback_secs = atoi(optarg);
break;
case 'd':
gn_debug = 1;
break;
case 'D':
strcpy(gs_dateStamp, optarg);
break;
case 'm':
gn_maxerrorcnt = atoi(optarg);
break;
case 'M':
gn_maxBlockCnt = atoi(optarg);
break;
case 'n':
gn_numprocs = atoi(optarg);
break;
case 'N':
gn_numthreads = atoi(optarg);
break;
case 'u':
commandsfilename = mystrdup(optarg);
break;
case 's':
f_usestdin = 1;
break;
case 't':
gt_testtime = time_atoi(optarg);
break;
case 'R':
ramptime = time_atoi(optarg);
break;
case 'v':
fprintf(stderr, "Netscape " MAILCLIENT_VERSION "\n");
fprintf(stderr, "Copyright (c) Netscape Communications Corporation 1997, 1998, 1999\n");
exit(1);
break;
case 'r':
gn_record_telemetry = 1;
break;
default:
usage(argv[0]);
}
}
}
#define SIZEOF_NTOABUF ((3+1)*4)
char *
safe_inet_ntoa(struct in_addr ina, char *psz)
{
sprintf(psz,"%d.%d.%d.%d",
((unsigned char *)&ina.s_addr)[0],
((unsigned char *)&ina.s_addr)[1],
((unsigned char *)&ina.s_addr)[2],
((unsigned char *)&ina.s_addr)[3]);
return psz;
}
/* look up the host name and protocol
* called from each protocol (via connectSocket)
*/
int
resolve_addrs(char *host,
char *protocol,
struct hostent *host_phe,
struct protoent *proto_ppe,
unsigned long *addr,
short *type)
{
struct hostent *phe;
struct protoent *ppe;
#ifdef USE_PTHREADS
#ifdef USE_GETHOSTBYNAME_R
struct hostent he;
struct protoent pe;
char buf[512];
int h_err;
#endif
#endif
/* if IP address given, convert to internal form */
if (host[0] >= '0' && host[0] <= '9') {
*addr = inet_addr(host);
if (*addr == INADDR_NONE)
return(returnerr(stderr,"Invalid IP address %s\n", host));
} else {
/* look up by name */
#ifdef USE_GETHOSTBYNAME_R
phe = gethostbyname_r(host, &he, buf, sizeof(buf), &h_err);
errno = h_err;
#else
phe = gethostbyname(host);
#endif
if (phe == NULL)
{
D_PRINTF(stderr, "Gethostbyname failed: %s", neterrstr() );
return(returnerr(stderr,"Can't get %s host entry\n", host));
}
memcpy(host_phe, phe, sizeof(struct hostent));
memcpy((char *)addr, phe->h_addr, sizeof(*addr));
}
/* Map protocol name to protocol number */
#ifdef USE_GETPROTOBYNAME_R
ppe = getprotobyname_r(protocol, &pe, buf, sizeof(buf));
#else
ppe = getprotobyname(protocol);
#endif
if (ppe == 0)
{
D_PRINTF(stderr, "protobyname returned %d\n", ppe );
return(returnerr(stderr,"Can't get %s protocol entry\n",protocol));
}
memcpy(proto_ppe, ppe, sizeof(struct protoent));
/* D_PRINTF(stderr, "Protocol number %d\n", ppe->p_proto ); */
/* Use protocol to choose a socket type */
if (strcmp(protocol,"udp") == 0)
{
*type = SOCK_DGRAM;
}
else
{
*type = SOCK_STREAM;
/* D_PRINTF(stderr, "Choosing SOCK_STREAM %d type %d %s\n",
SOCK_STREAM, *type, neterrstr() ); */
}
return 0;
}
/* connect to a socket given the hostname and protocol */
SOCKET
connectSocket(ptcx_t ptcx,
resolved_addr_t *hostInfo,
char *protocol)
{
struct sockaddr_in sin; /* an Internet endpoint address */
SOCKET s; /* socket descriptor */
int type; /* socket type */
short proto;
int returnval; /* temporary return value */
char ntoa_buf[SIZEOF_NTOABUF];
D_PRINTF(debugfile, "Beginning connectSocket; host=%s port=%d proto=%s\n",
hostInfo->hostName, hostInfo->portNum, protocol );
sin.sin_family = AF_INET;
memset((char *)&sin, 0, sizeof(sin));
D_PRINTF(debugfile, "Zeroed address structure\n" );
sin.sin_port = htons(hostInfo->portNum);
D_PRINTF(debugfile, "Set port number %d\n", hostInfo->portNum);
/* check if we've resolved this already */
if ((hostInfo) && (hostInfo->resolved)) {
sin.sin_addr.S_ADDR = hostInfo->host_addr;
sin.sin_family = PF_INET;
proto = hostInfo->host_ppe.p_proto;
type = hostInfo->host_type;
} else {
struct hostent host_phe;
struct protoent host_ppe;
unsigned long host_addr;
short host_type; /* socket type */
if (resolve_addrs(hostInfo->hostName, "tcp",
&host_phe, &host_ppe, &host_addr, &host_type)) {
return returnerr(debugfile,"Can't resolve hostname %s in get()\n",
hostInfo->hostName);
}
sin.sin_addr.S_ADDR = host_addr;
sin.sin_family = PF_INET;
proto = host_ppe.p_proto;
type = host_type;
}
/* Allocate a socket */
s = socket(PF_INET, type, proto);
if (BADSOCKET(s))
{
D_PRINTF(debugfile, "Can't create socket: %s\n",neterrstr() );
return BADSOCKET_VALUE;
}
/* Connect the socket */
D_PRINTF(debugfile, "Trying to connect %d with size %d\n",
s, sizeof(sin));
D_PRINTF(debugfile, "Address is family %d, port %d, addr %s\n",
sin.sin_family, ntohs(sin.sin_port),
safe_inet_ntoa(sin.sin_addr, ntoa_buf) );
returnval = connect(s, (struct sockaddr *)&sin, sizeof(sin));
if (returnval < 0) {
int err = GET_ERROR; /* preserve the error code */
D_PRINTF(debugfile, "Can't connect: %s\n", neterrstr() );
NETCLOSE(s);
SET_ERROR(err);
return BADSOCKET_VALUE;
}
/* all done, returning socket descriptor */
D_PRINTF(debugfile, "Returning %d from connectSocket call\n", s );
return(s);
} /* END connectSocket() */
int
set_abortive_close(SOCKET sock)
{
struct linger linger_opt;
linger_opt.l_onoff = 1;
linger_opt.l_linger = 0;
if (setsockopt(sock, SOL_SOCKET, SO_LINGER,
(char *) &linger_opt, sizeof(linger_opt)) < 0) {
returnerr(stderr, "Couldn't set SO_LINGER = 0\n");
return -1;
}
return 0;
}
void
initializeCommands(char *cfilename)
{
char *cbuf = NULL;
int cbuflen = 0;
int cbufalloced = 0;
int ret;
FILE *cfile;
D_PRINTF(stderr, "initializeCommands(%s)\n",
cfilename ? cfilename : "STDIN");
if (cfilename == NULL || strlen(cfilename) == 0) {
cfile = stdin;
cfilename = "stdin";
} else {
if ((cfile = fopen(cfilename, "r")) == NULL) {
D_PRINTF(stderr, "Cannot open commands file %s: errno=%d: %s\n",
cfilename, errno, strerror(errno));
errexit(stderr, "Cannot open commands file %s: errno=%d: %s\n",
cfilename, errno, strerror(errno));
}
}
#define CMDBUF_INCR 4096 /* longest allowed line */
while (!feof(cfile)) { /* read file in to char array */
if ((cbuflen + CMDBUF_INCR + 1) > cbufalloced) { /* grow array */
cbufalloced += CMDBUF_INCR;
cbuf = (char *)myrealloc(cbuf, cbufalloced+1);
cbuf[cbuflen] = '\0';
}
ret = fread(cbuf+cbuflen, 1, CMDBUF_INCR, cfile);
if (ret < 0) {
D_PRINTF(stderr, "Error reading commands file %s: errno=%d: %s\n",
cfilename, errno, strerror(errno));
errexit(stderr, "Error reading commands file %s: errno=%d: %s\n",
cfilename, errno, strerror(errno));
}
if (ret == 0)
break;
cbuflen += ret;
cbuf[cbuflen] = '\0';
}
if (cfile != stdin)
fclose(cfile);
/* D_PRINTF(stderr, "Got commands len=%d:\n%s\n", cbuflen, cbuf); */
/* Read commands into structure, make sure we have all req arguments */
if ((gn_total_weight = load_commands(cbuf)) < 0) {
D_PRINTF(stderr, "could not load %s\n", cfilename);
errexit(stderr, "Could not load command file\n");
}
if (0 == gn_total_weight) {
D_PRINTF(stderr, "No commands found for this host in %s\n", cfilename);
errexit(stderr, "No command for current host in command file\n");
}
}
int
readwriteStream(int ii, int fdin, int fdout)
{
char buf[MAX (8192, 2*SIZEOF_SUMMARYTEXT+1)], *cp;
int res;
int toread = sizeof(buf)-1;
int towrite;
D_PRINTF(stderr, "readwriteStream(%d,%d,%d)\n", ii, fdin, fdout);
/* structured as a while() for future nonblocking style */
while (toread) {
errno = 0;
res = NETREAD(fdin, buf, sizeof(buf)-1);
D_PRINTF(stderr, "read %d bytes from client %d\n", res, ii);
if (res == 0) {
return -1; /* EOF unless O_NDELAY */
} else if (res < 0) {
if (errno == EINTR || errno == EINTR) {
return 0; /* go back to the poll loop to service others */
}
fprintf(stderr, "readwriteStream(%d,%d,%d) error reading: errno=%d: %s\n",
ii, fdin, fdout, errno, strerror(errno));
return -1;
} else {
/* TODO: ...can do more data reduction here... */
toread -= res;
cp = buf;
towrite = res;
buf[towrite] = '\0';
/*D_PRINTF(stderr, "writing %d bytes to %d [%s]\n", towrite, fdout, buf);*/
D_PRINTF(stderr, "writing %d bytes to %d\n", towrite, fdout);
while (towrite) {
res = write(fdout, cp, towrite);
D_PRINTF(stderr, "wrote %d bytes to %d\n", res, fdout);
if (res <= 0) {
D_PRINTF(stderr, "error writing to %d: errno=%d: %s\n", fdout, errno, strerror(errno));
} else {
towrite -= res;
cp += res;
}
}
}
toread = 0; /* just read one chunk at a time for now... */
}
return 0;
}
#ifdef _WIN32
#define DIRECT_OUT /* report directly to stdout */
int
readwriteChildren(pccx_t pccxs)
{
while (readwriteStream(0, pccxs[0].socket, 1) >= 0)
;
return 0;
}
#else /* !_WIN32 */
/* This is where the master process merges output and waits for
the spawned processes to exit.
Note that no alarm has been set. We never wait very long in poll.
*/
int
readwriteChildren(pccx_t pccxs)
{
struct pollfd *pfds;
int nfds;
int ii;
/*
* Wait for all children to exit.
*/
nfds=0;
pfds = (struct pollfd *)mycalloc(sizeof(struct pollfd)*gn_numprocs);
for (ii=0; ii < gn_numprocs; ++ii) {
if (pccxs[ii].socket != -1) {
pfds[nfds].fd = pccxs[ii].socket;
++nfds;
}
}
fflush(stdout);
while (nfds > 0) {
int ret, closethisfd;
if (time(0L) >= gt_aborttime) {
D_PRINTF (stderr, "Time is up. Signalling exit %d\n",
gf_timeexpired);
gf_timeexpired = EXIT_FASTEST; /* signal clean up and exit */
break; /* just get out of here */
}
for (ii=0; ii < nfds; ++ii) {
pfds[ii].events = POLLIN;
pfds[ii].revents = 0;
}
D_PRINTF(stderr, "entering poll(nfds=%d)\n", nfds);
ret = poll(pfds, nfds, 5*1000);
D_PRINTF(stderr, "back from poll, ret=%d\n", ret);
if (ret == 0)
continue;
if (ret < 0) {
if (errno == EAGAIN || errno == EINTR)
continue;
fprintf(stderr, "poll error: errno=%d: %s\n", errno, strerror(errno));
break;
}
for (ii = 0; ii < nfds; ++ii) {
closethisfd = 0;
if (pfds[ii].revents) {
D_PRINTF(stderr, "poll says stdout fd=%d for client=%d is 0x%02x\n",
pfds[ii].fd, ii, pfds[ii].revents);
}
if (pfds[ii].revents & POLLIN) {
if (readwriteStream(ii, pfds[ii].fd, 1) == -1) {
closethisfd = 1;
}
} else if (pfds[ii].revents & (POLLHUP | POLLERR | POLLNVAL)) {
if (pfds[ii].revents & POLLHUP)
D_PRINTF(stderr, "POLLHUP for stdout fd=%d for client=%d!\n",
pfds[ii].fd, ii);
closethisfd = 1;
}
if (closethisfd) {
D_PRINTF(stderr, "closing for slot=%d fd=%d nfds=%d\n",
ii, pfds[ii].fd, nfds);
NETCLOSE(pfds[ii].fd);
--nfds; /* shrink poll array */
/* NOTE: this re-orders the array */
if (ii != nfds) { /* move last one into old spot */
pfds[ii].fd = pfds[nfds].fd;
pfds[ii].events = pfds[nfds].events;
pfds[ii].revents = pfds[nfds].revents;
--ii; /* check moved entry on the next loop */
}
}
}
}
if (nfds > 0) {
d_printf (stderr,
"WARNING: Exiting with open clients nfds=%d time=%lu shutdowntime=%lu\n",
nfds, time(0L), gt_shutdowntime);
for (ii = 0; ii < nfds; ++ii) { /* close socket to make clients die */
D_PRINTF(stderr, "closing for slot=%d fd=%d\n", ii, pfds[ii].fd);
NETCLOSE(pfds[ii].fd);
}
}
return 0;
}
#endif /* _WIN32 */
/* This is where each sub process starts */
THREAD_RET
launchChild(void *targ)
{
SOCKET clientsock;
struct sockaddr_in saddr; /* server address */
struct linger linger_opt;
unsigned int testtimeleft;
int ret;
unsigned int thread_stagger_usec = 1000; /* 1000/sec */
int pnum = (int)targ;
gn_myPID = getpid();
if (ramptime) {
/* comvert to microseconds */
if (gn_numthreads > 0) {
/* force intermediate result to double to avoid overflow */
thread_stagger_usec = (unsigned int)((ramptime * (double)USECINSEC) / gn_numthreads);
} else {
thread_stagger_usec = 0;
}
}
if ((clientsock=socket(AF_INET, SOCK_STREAM, 0)) == -1) {
errexit(stderr, "child socket(): %s\n", neterrstr());
}
memset(&saddr, 0, sizeof(saddr));
saddr.sin_addr.S_ADDR = inet_addr("127.0.0.1");
saddr.sin_family = AF_INET;
saddr.sin_port = listenport;
if (connect(clientsock, (struct sockaddr *)&saddr, sizeof(saddr)) == -1) {
NETCLOSE(clientsock);
errexit(stderr, "child connect(): %s\n", neterrstr());
}
#if 1
linger_opt.l_onoff = 1;
linger_opt.l_linger = 60;
if (setsockopt(clientsock, SOL_SOCKET, SO_LINGER, (char *) &linger_opt, sizeof(linger_opt)) < 0) {
NETCLOSE(clientsock);
errexit(stderr, "child setsockopt(): %s\n", neterrstr());
}
#endif
D_PRINTF(stderr, "child %d: using socket %d\n", pnum, clientsock);
#if 0
unsigned int fork_stagger_usec = 10000; /* 100/sec */
if (pnum) {
D_PRINTF(stderr, "child %d: delaying %d secs\n",
pnum, USECS_2_SECS(pnum * fork_stagger_usec));
MS_usleep(pnum * fork_stagger_usec);
}
#endif
testtimeleft = gt_shutdowntime - time(0L);
D_PRINTF(stderr, "child %d: proceeding for %d remaining seconds\n",
pnum, testtimeleft);
if (testtimeleft > 0) {
/* This is where the test gets run */
#ifndef DIRECT_OUT
ret = clientProc(pnum, clientsock,
testtimeleft, thread_stagger_usec);
#else
ret = clientProc(pnum, fileno(stdout),
testtimeleft, thread_stagger_usec);
#endif
} else {
D_PRINTF(stderr, "child %d: Too late to start! shudowntime=%lu now=%lu\n",
pnum, testtimeleft, time(0L));
ret = -1;
}
D_PRINTF(stderr, "child %d: closing logging socket\n", pnum);
NETCLOSE(clientsock);
#ifndef _WIN32
return((void *)ret);
#endif
}
/* Wait for childred to exit (after readwritechildren returns).
*/
int
waitChildren(void)
{
#ifndef _WIN32
int pid;
int status;
for (;;) {
errno = 0;
alarm(gt_stopinterval); /* dont wait forever */
pid = wait(&status);
if (pid == -1) {
if (errno == ECHILD) {
break; /* none left. finished */
}
if (errno == EINTR) { /* alarm went off */
if (time(0L) > (gt_aborttime+(EXIT_FAST*gt_stopinterval))) {
d_printf (stderr,
"WARNING: Aborting wait for children!\n");
break;
}
}
}
if (WIFSIGNALED (status)) { /* show error exits */
d_printf (stderr, "Client pid %d died with signal %d\n",
pid, WTERMSIG(status));
} else {
D_PRINTF(stderr, "Client pid %d: status: %d errno=%d: %s\n",
pid, status, errno, strerror(errno));
}
}
#endif /* !_WIN32 */
return 0;
}
int
main(int argc, char *argv[])
{
int ii;
struct tm *tmptm;
time_t currentTime;
#ifdef _WIN32
int err;
WSADATA WSAData;
#endif
int ret;
int pid=0;
pccx_t pccxs; /* client process contexts */
SOCKET serversock;
struct sockaddr_in saddr; /* server address */
struct sockaddr_in caddr; /* client address */
int addr_len;
char ntoabuf[SIZEOF_NTOABUF];
#ifdef _WIN32
//MessageBeep(~0U); /* announce our existence */
err = WSAStartup(MAKEWORD(1,1), &WSAData);
if (err != 0) {
errexit(stderr, "Error in WSAStartup()\n");
}
atexit(sock_cleanup);
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
#endif /* _WIN32 */
gn_myPID = getpid();
gethostname(gs_thishostname, sizeof(gs_thishostname)-1);
memset(mailmaster, 0, sizeof(mailmaster));
memset(gs_dateStamp, 0, DATESTAMP_LEN*sizeof(char));
parseArgs(argc, argv);
returnerr(stderr, MAILCLIENT_VERSION "\n");
returnerr(stderr, "procs=%d threads=%d seconds=%d ramptime=%d...\n",
gn_numprocs, gn_numthreads , gt_testtime, ramptime);
if (ramptime > gt_testtime) {
returnerr (stderr, "RampTime %d longer than TestTime %d. Adjusting.\n",
ramptime, gt_testtime);
ramptime = gt_testtime;
}
D_PRINTF(stderr, "Running in debug mode\n\n" );
/* print the command line */
if (gn_debug) {
for (ii = 0; ii < argc; ii++)
fprintf(stderr, "%s ", argv[ii] );
fprintf(stderr, "\n\n" );
}
if (commandsfilename == NULL && f_usestdin == 0) {
/* Must specify a message list */
returnerr(stderr, "No mail message list specified (use <-s | -u commandsfilename>)\n");
usage(argv[0]);
}
if (gt_testtime == 0) { /* NO TEST TIME */
usage(argv[0]);
}
if (gn_numprocs > MAXPROCSPERNODE || gn_numprocs < 1) {
returnerr(stderr, "Number of clients must be between 1 and %d\n", MAXPROCSPERNODE);
usage(argv[0]);
}
crank_limits();
if (!gs_dateStamp[0]) {
time(&currentTime);
tmptm = localtime(&currentTime);
strftime(gs_dateStamp, DATESTAMP_LEN, "%Y%m%d%H%M%S", tmptm);
}
initializeCommands(commandsfilename); /* read command block */
gt_startedtime = time(0L);
gt_shutdowntime = gt_startedtime + gt_testtime; /* start clean shutdown */
gt_stopinterval = MAX ((ramptime/EXIT_FASTEST), 1); /* signal period */
/* this is when the master gives up on the children */
gt_aborttime = gt_shutdowntime + gt_stopinterval*2*EXIT_FASTEST;
if ((pccxs = (pccx_t)mycalloc(sizeof(ccx_t) * gn_numprocs)) == NULL) {
errexit(stderr, "error mycalloc() pccxs\n");
}
D_PRINTF(stderr, "preparing serversock\n");
if ((serversock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
errexit(stderr, "socket() error: %s\n", neterrstr());
}
memset(&saddr, 0, sizeof(saddr));
/*saddr.sin_addr.S_ADDR = htonl(INADDR_ANY);*/
saddr.sin_addr.S_ADDR = inet_addr("127.0.0.1");
saddr.sin_family = AF_INET;
saddr.sin_port = 0;
if (bind(serversock, (struct sockaddr *)&saddr, sizeof(saddr)) == -1) {
NETCLOSE(serversock);
errexit(stderr, "bind() error: %s\n", neterrstr());
}
if (listen(serversock, 512) == -1) {
NETCLOSE(serversock);
errexit(stderr, "listen() error: %s\n", neterrstr());
}
addr_len = sizeof(saddr);
if (getsockname(serversock, (struct sockaddr *)&saddr, &addr_len) == -1) {
NETCLOSE(serversock);
errexit(stderr, "getsockname() error: %s\n", neterrstr());
}
listenport = saddr.sin_port;
D_PRINTF(stderr, "listening on [%s:%d]\n",
safe_inet_ntoa(saddr.sin_addr, ntoabuf), ntohs(listenport));
setup_signal_handlers (); /* trap signals */
for(ii = 0; ii < gn_numprocs; ++ii) {
D_PRINTF(stderr, "parent: forking client %d\n", ii);
#ifdef _WIN32
if (_beginthread(launchChild, NT_STACKSIZE, (void *)ii) == -1) {
errexit(stderr, "_beginthread failed: %d", GetLastError());
}
#else
#ifdef DIRECT_OUT /* for Unix, only if debugging */
if (1 == gn_numprocs) {
fprintf (stderr, "Single process, NOT forking.\n");
launchChild (0); /* DEBUG */
return 0;
}
#endif
switch(pid=fork()) {
case 0: /* CHILD */
launchChild((void *)ii);
exit(ii);
break;
case -1: /* ERROR */
fprintf(stderr, "parent: error forking child %d, errno=%d: %s\n", ii, errno, strerror(errno));
errexit(stderr, "Error forking child processes\n");
exit(1);
default: /* PARENT */
break;
}
#endif
pccxs[ii].pid = pid;
D_PRINTF(stderr, "parent: Accepting child %d pid=%d\n", ii, pid);
/* Maybe fork everything before accepting */
addr_len = sizeof(caddr);
/* If the the child dies immediately, we hang here */
if ((ret = accept(serversock, (struct sockaddr *)&caddr, &addr_len)) == -1) {
errexit(stderr, "accept() error: %s\n", neterrstr());
}
D_PRINTF(stderr, "parent: child %d using socket %d\n", ii, ret);
pccxs[ii].socket = ret;
}
readwriteChildren(pccxs);
D_PRINTF(stderr, "done polling, now just wait\n");
waitChildren();
returnerr(stderr, "Master process done.\n");
fflush(stdout);
return 0;
} /* end main() */

Просмотреть файл

@ -1,425 +0,0 @@
/* -*- Mode: C; c-file-style: "stroustrup"; comment-column: 40 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape Mailstone utility,
* released March 17, 2000.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1997-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s): Dan Christian <robodan@netscape.com>
* Marcel DePaolis <marcel@netcape.com>
* Mike Blakely
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License Version 2 or later (the "GPL"), in
* which case the provisions of the GPL are applicable instead of
* those above. If you wish to allow use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the NPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the NPL or the GPL.
*/
/* pop3.c: POP3 protocol test */
#include "bench.h"
#include "pish.h"
typedef struct _doPOP3_state {
int numMsgs; /* messages in folder */
int totalMsgLength; /* total msg length */
int msgCounter; /* count in download */
} doPOP3_state_t;
/* POP3 flags definitions */
#define leaveMailOnServer 0x01
static void doPop3Exit (ptcx_t ptcx, doPOP3_state_t *me);
static int
PopParseNameValue (pmail_command_t cmd,
char *name,
char *tok)
{
pish_command_t *pish = (pish_command_t *)cmd->data;
/* find a home for the attr/value */
if (pishParseNameValue(cmd, name, tok) == 0)
; /* done */
else if (strcmp(name, "leavemailonserver") == 0)
if (atoi(tok) > 0) {
pish->flags |= leaveMailOnServer;
} else {
pish->flags &= ~leaveMailOnServer;
}
else {
return -1;
}
return 0;
}
/*
Set defaults in command structure
*/
int
Pop3ParseStart (pmail_command_t cmd,
char *line,
param_list_t *defparm)
{
param_list_t *pp;
pish_command_t *pish = (pish_command_t *)mycalloc
(sizeof (pish_command_t));
cmd->data = pish;
cmd->numLoops = 9999; /* default 9999 downloads */
pish->hostInfo.portNum = POP3_PORT; /* default port */
D_PRINTF(stderr, "Pop3 Assign defaults\n");
/* Fill in defaults first, ignore defaults we dont use */
for (pp = defparm; pp; pp = pp->next) {
(void)PopParseNameValue (cmd, pp->name, pp->value);
}
return 1;
}
/*
Fill in command structure from a list of lines
*/
int
Pop3ParseEnd (pmail_command_t cmd,
string_list_t *section,
param_list_t *defparm)
{
string_list_t *sp;
pish_command_t *pish = (pish_command_t *)cmd->data;
/* Now parse section lines */
D_PRINTF(stderr, "Pop3 Assign section lines\n");
/* skip first and last */
for (sp = section->next; sp->next; sp = sp->next) {
char *name = sp->value;
char *tok = name + strcspn(name, " \t=");
*tok++ = 0; /* split name off */
tok += strspn(tok, " \t=");
string_tolower(name);
tok = string_unquote(tok);
if (PopParseNameValue (cmd, name, tok) < 0) {
/* not a known attr */
D_PRINTF(stderr,"unknown attribute '%s' '%s'\n", name, tok);
returnerr(stderr,"unknown attribute '%s' '%s'\n", name, tok);
}
}
/* check for some of the required command attrs */
if (!pish->hostInfo.hostName) {
D_PRINTF(stderr,"missing server for command");
return returnerr(stderr,"missing server for command\n");
}
if (!pish->loginFormat) {
D_PRINTF(stderr,"missing loginFormat for command");
return returnerr(stderr,"missing loginFormat for command\n");
}
if (!pish->passwdFormat) {
D_PRINTF(stderr,"missing passwdFormat for command");
return returnerr(stderr,"missing passwdFormat for command\n");
}
/* see if we can resolve the mailserver addr */
if (resolve_addrs(pish->hostInfo.hostName, "tcp",
&(pish->hostInfo.host_phe),
&(pish->hostInfo.host_ppe),
&(pish->hostInfo.host_addr),
&(pish->hostInfo.host_type))) {
return returnerr (stderr, "Error resolving hostname '%s'\n",
pish->hostInfo.hostName);
} else {
pish->hostInfo.resolved = 1; /* mark the hostInfo resolved */
}
rangeSetFirstCount (&pish->loginRange, pish->loginRange.first,
pish->loginRange.span, pish->loginRange.sequential);
rangeSetFirstCount (&pish->domainRange, pish->domainRange.first,
pish->domainRange.span, pish->domainRange.sequential);
return 1;
}
int
doPopCommandResponse(ptcx_t ptcx, SOCKET sock, char *command, char *response, int resplen)
{
int rc;
T_PRINTF(ptcx->logfile, command, strlen (command), "POP3 SendCommand");
rc = doCommandResponse(ptcx, sock, command, response, resplen);
if (rc == -1)
return rc;
T_PRINTF(ptcx->logfile, response, strlen(response),
"POP3 ReadResponse"); /* telemetry log. should be lower level */
/* D_PRINTF(stderr, "POP command=[%s] response=[%s]\n", command, response); */
if (strncmp(response, "+OK", 3) != 0) {
if (gf_timeexpired < EXIT_FAST) {
trimEndWhite (command);
trimEndWhite (response);
returnerr(debugfile,"POP3 error command=[%s] response=[%s]\n",
command, response);
}
return -1;
}
return 0;
}
int
popLogin(ptcx_t ptcx, mail_command_t *cmd, cmd_stats_t *ptimer, SOCKET sock)
{
char command[MAX_COMMAND_LEN];
char respBuffer[MAX_RESPONSE_LEN];
char mailUser[MAX_MAILADDR_LEN];
char userPasswd[MAX_MAILADDR_LEN];
unsigned long loginNum;
unsigned long domainNum;
int rc;
pish_stats_t *stats = (pish_stats_t *)ptimer->data;
pish_command_t *pish = (pish_command_t *)cmd->data;
/* generate a random username and domainname(with a mailbox on the server) */
domainNum = rangeNext (&stats->domainRange, stats->lastDomain);
stats->lastDomain = domainNum;
loginNum = rangeNext (&stats->loginRange, stats->lastLogin);
stats->lastLogin = loginNum;
sprintf(mailUser, pish->loginFormat, loginNum, domainNum);
D_PRINTF(debugfile,"mailUser=%s\n", mailUser);
sprintf(command, "USER %s%s", mailUser, CRLF);
event_start(ptcx, &stats->cmd);
rc = doPopCommandResponse(ptcx, sock, command, respBuffer, sizeof(respBuffer));
event_stop(ptcx, &stats->cmd);
if (rc == -1) {
if (gf_timeexpired < EXIT_FAST) {
stats->login.errs++;
/* error already displayed */
}
return -1;
}
/* send Password */
sprintf(userPasswd, pish->passwdFormat, loginNum);
sprintf(command, "PASS %s%s", userPasswd, CRLF);
event_start(ptcx, &stats->login);
rc = doPopCommandResponse(ptcx, sock, command, respBuffer, sizeof(respBuffer));
event_stop(ptcx, &stats->login);
if (rc == -1) {
if (gf_timeexpired < EXIT_FAST) {
stats->login.errs++;
returnerr(debugfile,"POP3 cannot login user=%s pass=%s\n",
mailUser, userPasswd);
}
return -1;
}
return 0;
}
void *
doPop3Start(ptcx_t ptcx, mail_command_t *cmd, cmd_stats_t *ptimer)
{
doPOP3_state_t *me = (doPOP3_state_t *)mycalloc (sizeof (doPOP3_state_t));
char respBuffer[MAX_RESPONSE_LEN];
int rc;
int numBytes;
char command[MAX_COMMAND_LEN];
pish_stats_t *stats = (pish_stats_t *)ptimer->data;
pish_command_t *pish = (pish_command_t *)cmd->data;
if (!me) return NULL;
me->numMsgs = 0;
me->totalMsgLength = 0;
me->msgCounter = 0;
event_start(ptcx, &stats->connect);
ptcx->sock = connectSocket(ptcx, &pish->hostInfo, "tcp");
event_stop(ptcx, &stats->connect);
if (BADSOCKET(ptcx->sock)) {
if (gf_timeexpired < EXIT_FAST) {
stats->connect.errs++;
returnerr(debugfile, "POP3 Couldn't connect to %s: %s\n",
pish->hostInfo.hostName, neterrstr());
}
myfree (me);
return NULL;
}
if (gf_abortive_close) {
if (set_abortive_close(ptcx->sock) != 0) {
returnerr (debugfile, "POP3: WARNING: Could not set abortive close\n");
}
}
/* READ connect response from server */
event_start(ptcx, &stats->banner);
numBytes = readResponse(ptcx, ptcx->sock, respBuffer, sizeof(respBuffer));
event_stop(ptcx, &stats->banner);
if (numBytes <= 0) {
if (gf_timeexpired < EXIT_FAST) {
stats->banner.errs++;
returnerr(debugfile,"POP3 Error reading banner: %s\n",
neterrstr());
}
doPop3Exit (ptcx, me);
return NULL;
}
/*
* LOGIN
*/
rc = popLogin(ptcx, cmd, ptimer, ptcx->sock);
if (rc != 0) {
doPop3Exit (ptcx, me);
return NULL;
}
/* send a STAT */
sprintf(command, "STAT%s", CRLF);
event_start(ptcx, &stats->cmd);
rc = doPopCommandResponse(ptcx, ptcx->sock, command, respBuffer, sizeof(respBuffer));
event_stop(ptcx, &stats->cmd);
if (rc == -1) {
if (gf_timeexpired < EXIT_FAST) {
stats->cmd.errs++;
}
doPop3Exit (ptcx, me);
return NULL;
}
/* parse number of msgs out of buffer */
if (!sscanf(respBuffer, "+OK %d %d", &me->numMsgs, &me->totalMsgLength)) {
if (gf_timeexpired < EXIT_FAST) {
stats->cmd.errs++;
returnerr(debugfile,"POP3 Error parsing STAT response, %s: %s\n",
respBuffer, neterrstr());
}
doPop3Exit (ptcx, me);
return NULL;
}
D_PRINTF(debugfile,"STAT shows %d msgs of %d total bytes\n",
me->numMsgs, me->totalMsgLength);
return me;
}
int
doPop3Loop(ptcx_t ptcx, mail_command_t *cmd, cmd_stats_t *ptimer, void *mystate)
{
doPOP3_state_t *me = (doPOP3_state_t *)mystate;
char command[MAX_COMMAND_LEN];
char respBuffer[MAX_RESPONSE_LEN];
int rc, numBytes;
pish_stats_t *stats = (pish_stats_t *)ptimer->data;
pish_command_t *pish = (pish_command_t *)cmd->data;
if (me->msgCounter >= me->numMsgs) return -1; /* done, close */
/* retr the msgs */
/* send the RETR command */
sprintf(command, "RETR %d%s", ++me->msgCounter, CRLF);
event_start(ptcx, &stats->msgread);
rc = sendCommand(ptcx, ptcx->sock, command);
if (rc == -1) {
event_stop(ptcx, &stats->msgread);
if (gf_timeexpired < EXIT_FAST) {
stats->msgread.errs++;
returnerr(debugfile,"POP3 Error sending RETR %d command: %s\n",
me->msgCounter, neterrstr());
}
doPop3Exit (ptcx, me);
return -1;
}
/* read msg */
numBytes = retrMsg(ptcx, NULL, 0 , ptcx->sock);
event_stop(ptcx, &stats->msgread);
if (numBytes <= 0) {
if (gf_timeexpired < EXIT_FAST) {
stats->msgread.errs++;
returnerr(debugfile,"POP3 Error retrieving msg %d: %s\n",
me->msgCounter, neterrstr());
}
doPop3Exit (ptcx, me);
return -1;
}
/* if we're not told to leave mail on server, delete the message */
if (!(pish->flags & leaveMailOnServer)) {
/* send the DELE command */
sprintf(command, "DELE %d%s", me->msgCounter, CRLF);
event_start(ptcx, &stats->cmd);
rc = doPopCommandResponse(ptcx, ptcx->sock, command, respBuffer, sizeof(respBuffer));
event_stop(ptcx, &stats->cmd);
if (rc == -1) {
if (gf_timeexpired < EXIT_FAST) {
stats->cmd.errs++;
}
doPop3Exit (ptcx, me);
return -1;
}
}
return 0;
}
void
doPop3End(ptcx_t ptcx, mail_command_t *cmd, cmd_stats_t *ptimer, void *mystate)
{
doPOP3_state_t *me = (doPOP3_state_t *)mystate;
char command[MAX_COMMAND_LEN];
char respBuffer[MAX_RESPONSE_LEN];
int rc;
pish_stats_t *stats = (pish_stats_t *)ptimer->data;
if (BADSOCKET(ptcx->sock)) return; /* closed by previous error */
/* send QUIT */
sprintf(command, "QUIT%s", CRLF);
event_start(ptcx, &stats->logout);
rc = doPopCommandResponse(ptcx, ptcx->sock, command, respBuffer, sizeof(respBuffer));
event_stop(ptcx, &stats->logout);
if (rc == -1) {
if (gf_timeexpired < EXIT_FAST) {
stats->logout.errs++; /* counted twice? */
}
}
doPop3Exit (ptcx, me);
}
void
doPop3Exit (ptcx_t ptcx, doPOP3_state_t *me)
{
if (!BADSOCKET(ptcx->sock))
NETCLOSE(ptcx->sock);
ptcx->sock = BADSOCKET_VALUE;
myfree (me);
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,397 +0,0 @@
/* -*- Mode: C; c-file-style: "stroustrup"; comment-column: 40 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape Mailstone utility,
* released March 17, 2000.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1997-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s): Dan Christian <robodan@netscape.com>
* Marcel DePaolis <marcel@netcape.com>
* Mike Blakely
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License Version 2 or later (the "GPL"), in
* which case the provisions of the GPL are applicable instead of
* those above. If you wish to allow use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the NPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the NPL or the GPL.
*/
#include "bench.h"
#ifdef USE_LRAND48_R /* also AIX (only when using threads)*/
struct drand48_data drand48data;
/* should verify that the struct drand48_data can be shared between threads */
void
osf_srand48_r(unsigned int seed)
{
srand48_r(seed, &drand48data);
}
long
osf_lrand48_r(void)
{
long ret;
lrand48_r(&drand48data, &ret);
return ret;
}
#endif /* __OSF1__ */
#ifdef _WIN32
/* close socket library at exit() time */
void sock_cleanup(void) {
WSACleanup();
}
#endif /* _WIN32 */
/* neither sleep or usleep re-start if interrupted */
void
MS_sleep(unsigned int secs)
{
#ifdef _WIN32
Sleep(secs * 1000);
#else
struct timeval sleeptime;
/*D_PRINTF(stderr, "MS_sleep(%d)\n", secs);*/
sleeptime.tv_sec = secs;
sleeptime.tv_usec = 0;
if (select( (int)NULL, (fd_set *)NULL, (fd_set *)NULL, (fd_set *)NULL,
&sleeptime ) < 0) {
D_PRINTF (stderr, "MS_sleep %lu returned early\n", secs);
}
#endif
}
void
MS_usleep(unsigned int microsecs)
{
#ifdef _WIN32
Sleep(microsecs / 1000);
#else
struct timeval sleeptime;
/*D_PRINTF(stderr, "MS_usleep(%d)\n", microsecs);*/
sleeptime.tv_sec = USECS_2_SECS(microsecs);
sleeptime.tv_usec = microsecs % USECINSEC;
if (select( (int)NULL, (fd_set *)NULL, (fd_set *)NULL, (fd_set *)NULL,
&sleeptime ) < 0) {
D_PRINTF (stderr, "MS_usleep %lu returned early\n", microsecs);
}
#endif
}
/* strerror() */
#ifndef HAVE_STRERROR
/* strerror is not available on SunOS 4.1.3 and others */
extern int sys_nerr;
extern char *sys_errlist[];
extern int errno;
char *strerror(int errnum)
{
if (errnum<sys_nerr) {
return(sys_errlist[errnum]);
}
return(NULL);
}
#endif /* strerror() */
/* stub routines for NT */
#ifdef WIN32
#include <winsock.h>
#include <process.h>
int getpid(void) {
return GetCurrentThreadId();
}
#include <sys/timeb.h> /* For prototype of "_ftime()" */
/*
* gettimeofday() -- gets the current time in elapsed seconds and
* microsends since GMT Jan 1, 1970.
*
* ARGUMENTS: - Pointer to a timeval struct to return the time into
*
* RETURN CODES: - 0 on success
* -1 on failure
*/
int gettimeofday(struct timeval *curTimeP)
{
struct _timeb localTime;
if (curTimeP == (struct timeval *) NULL) {
errno = EFAULT;
return (-1);
}
/*
* Compute the elapsed time since Jan 1, 1970 by first
* obtaining the elapsed time from the system using the
* _ftime(..) call and then convert to the "timeval"
* equivalent.
*/
_ftime(&localTime);
curTimeP->tv_sec = localTime.time;
curTimeP->tv_usec = localTime.millitm * 1000;
return(0);
}
void
crank_limits(void)
{}
void
setup_signal_handlers(void)
{}
int
sysdep_thread_create(THREAD_ID *id, thread_fn_t tfn, void *arg)
{
if (_beginthread(tfn, NT_STACKSIZE, arg) == -1) {
errexit(stderr, "_beginthread failed: %d", GetLastError());
return -1;
}
return 0;
}
int
sysdep_thread_join(THREAD_ID id, int *pstatus)
{
return 0;
}
#else /* !_WIN32 */
#define MAX_TRYFDS (64*1024)
void
crank_limits(void)
{
struct rlimit rlim;
int cur_lim;
int rc;
#ifdef __OSF1__
D_PRINTF(stderr, "attempting to enable support for up to 64k file descriptors\n");
rc = setsysinfo(SSI_FD_NEWMAX, NULL, 0, NULL, 1);
if (rc == -1) {
perror("setsysinfo()");
}
#endif /* __OSF1__ */
D_PRINTF(stderr, "attempting to increase our hard limit (up to %d)\n", MAX_TRYFDS);
rc = getrlimit(RLIMIT_NOFILE, &rlim);
if (rc == -1) {
returnerr(stderr, "getrlimit()");
exit(-1);
}
for (cur_lim = rlim.rlim_max; cur_lim < MAX_TRYFDS; cur_lim += 1024) {
rlim.rlim_max = cur_lim;
rc = setrlimit(RLIMIT_NOFILE, &rlim);
if (rc == -1) {
D_PRINTF (stderr, "setrlimit(RLIMIT_NOFILE, [rlim_max=%d]): errno=%d: %s\n",
rlim.rlim_max, errno, strerror(errno));
break;
}
}
D_PRINTF(stderr, "attempting to increase our soft limit\n");
rc = getrlimit(RLIMIT_NOFILE, &rlim);
if (rc == -1) {
returnerr(stderr, "getrlimit()");
exit(-1);
}
rlim.rlim_cur = rlim.rlim_max;
rc = setrlimit(RLIMIT_NOFILE, &rlim);
if (rc == -1) {
D_PRINTF (stderr, "setrlimit(RLIMIT_NOFILE, [rlim_cur=%d]): errno=%d: %s\n",
rlim.rlim_cur, errno, strerror(errno));
exit(-1);
}
getrlimit(RLIMIT_NOFILE, &rlim);
if (rlim.rlim_cur < 256) { /* show if lower than docs suggest */
returnerr (stderr, "RLIMIT_NOFILE = %d. max processes/threads ~ %d\n",
rlim.rlim_cur, rlim.rlim_cur-10);
} else {
D_PRINTF (stderr, "RLIMIT_NOFILE = %d. max processes/threads ~ %d\n",
rlim.rlim_cur, rlim.rlim_cur-10);
}
}
static void
nullHandler(int sig)
{
/* Dont do anything, (trap SIGPIPE) */
return;
}
static void
alarmHandler(int sig)
{
/* Dont do anything, mainly break system calls */
if (gf_timeexpired < EXIT_SOON) gf_timeexpired = EXIT_SOON;
return;
}
static void
hupHandler(int sig)
{
if (gf_timeexpired < EXIT_SOON) { /* first time, go to clean stop */
beginShutdown ();
} else if (gf_timeexpired < EXIT_FAST) { /* second time, faster */
gf_timeexpired = EXIT_FAST;
} else if (gf_timeexpired < EXIT_FASTEST) { /* second time, fastest */
gf_timeexpired = EXIT_FASTEST;
} else { /* third time, exit */
exit (sig);
}
}
#if 0 /* not used */
/* Received a signal that a child process has exited */
void
childHandler(int sig)
{
int status;
/*D_PRINTF(stderr, "A child process has exited\n" );*/
while (wait3(&status, WNOHANG, (struct rusage *)0) > 0) {
/* do nothing */
/*D_PRINTF(stderr, "wait3() says %d died\n", status);;*/
}
}
#endif
void
setup_signal_handlers(void)
{
/* We will loop until the alarm goes off (should abort system calls). */
#ifdef __LINUX__
{ /* setup signal handler */
struct sigaction sig;
sig.sa_flags = 0;
sig.sa_restorer = 0;
sigemptyset (&sig.sa_mask);
sig.sa_handler = alarmHandler;
sigaction (SIGALRM, &sig, NULL);
sig.sa_handler = hupHandler;
sigaction (SIGHUP, &sig, NULL);
sigaction (SIGTERM, &sig, NULL);
sig.sa_handler = nullHandler;
sigaction (SIGPIPE, &sig, NULL);
}
#else
sigset(SIGALRM, alarmHandler);
sigset(SIGHUP, hupHandler);
sigset(SIGTERM, hupHandler);
sigset(SIGPIPE, nullHandler);
#endif
}
int
sysdep_thread_create(THREAD_ID *id, thread_fn_t tfn, void *arg)
{
#ifdef USE_PTHREADS
int ret;
pthread_attr_t attr;
if ((ret=pthread_attr_init(&attr)) != 0) {
returnerr(stderr, "pthread_attr_init() ret=%d errno=%d: %s\n",
ret, errno, strerror(errno));
return -1;
}
#if 0 /* the default thread attributes */
pthread_attr_setscope(&attr, PTHREAD_SCOPE_PROCESS);
pthread_attr_setstackaddr(&attr, NULL); /* allocated by system */
pthread_attr_setstacksize(&attr, NULL); /* 1 MB */
pthread_attr_setschedparam(&attr, _PARENT_); /* priority of parent */
pthread_attr_setschedpolicy(&attr, SCHED_OTHER); /* determined by system */
/* also have SCHED_FIFO and SCHED_RR */
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
#endif
#ifdef __AIX__
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_UNDETACHED);
#else
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
#endif
#ifdef THREADS_SCOPE_SYSTEM
/* bound threads, one thread per LWP */
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
#endif
if ((ret=pthread_create(id, &attr, tfn, arg)) != 0) {
returnerr(stderr, "pthread_create() failed ret=%d errno=%d: %s\n",
ret, errno, strerror(errno));
return -1;
}
if ((ret=pthread_attr_destroy(&attr)) != 0) {
returnerr(stderr, "pthread_attr_destroy() ret=%d errno=%d: %s\n",
ret, errno, strerror(errno));
return -1;
}
#endif
return 0;
}
int
sysdep_thread_join(THREAD_ID id, int *pstatus)
{
int ret;
for (;;) {
errno = 0;
*pstatus = 0;
if ((ret = pthread_join(id, (void **)pstatus)) == 0)
break;
D_PRINTF(stderr, "pthread_join(%d) error ret=%d status=%d: errno=%d: %s\n",
id, ret, *pstatus, errno, strerror(errno));
}
return 0;
}
#endif /* WIN32 */

Разница между файлами не показана из-за своего большого размера Загрузить разницу