<commit_before>/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SampleCode.h"
#include "SkView.h"
#include "SkBlurMask.h"
#include "SkCanvas.h"
#include "SkCornerPathEffect.h"
#include "SkGradientShader.h"
#include "SkGraphics.h"
#include "SkImageDecoder.h"
#include "SkPath.h"
#include "SkRandom.h"
#include "SkRegion.h"
#include "SkShader.h"
#include "SkUtils.h"
#include "SkColorPriv.h"
#include "SkColorFilter.h"
#include "SkTime.h"
#include "SkTypeface.h"
#include "SkXfermode.h"

#include "SkStream.h"
#include "SkColorPriv.h"
#include "SkImageDecoder.h"
#include "SkBlurMaskFilter.h"

static void setNamedTypeface(SkPaint* paint, const char name[]) {
    SkTypeface* face = SkTypeface::CreateFromName(name, SkTypeface::kNormal);
    paint->setTypeface(face);
    SkSafeUnref(face);
}

static uint16_t gBG[] = { 0xFFFF, 0xCCCF, 0xCCCF, 0xFFFF };

class XfermodesBlurView : public SampleView {
    SkBitmap    fBG;
    SkBitmap    fSrcB, fDstB;

    void draw_mode(SkCanvas* canvas, SkXfermode* mode, int alpha,
                   SkScalar x, SkScalar y) {
        SkPaint p;
        SkMaskFilter* mf = SkBlurMaskFilter::Create(kNormal_SkBlurStyle,
                                       SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(5)),
                                       SkBlurMaskFilter::kNone_BlurFlag);
        p.setMaskFilter(mf)->unref();

        SkScalar ww = SkIntToScalar(W);
        SkScalar hh = SkIntToScalar(H);

        // draw a circle covering the upper
        // left three quarters of the canvas
        p.setColor(0xFFCC44FF);
        SkRect r;
        r.set(0, 0, ww*3/4, hh*3/4);
        r.offset(x, y);
        canvas->drawOval(r, p);

        p.setXfermode(mode);

        // draw a square overlapping the circle
        // in the lower right of the canvas
        p.setColor(0x00AA6633 | alpha << 24);
        r.set(ww/3, hh/3, ww*19/20, hh*19/20);
        r.offset(x, y);
        canvas->drawRect(r, p);
    }

public:
    const static int W = 64;
    const static int H = 64;
    XfermodesBlurView() {
        fBG.installPixels(SkImageInfo::Make(2, 2, kARGB_4444_SkColorType, kPremul_SkAlphaType),
                          gBG, 4);
    }

protected:
    // overrides from SkEventSink
    virtual bool onQuery(SkEvent* evt) {
        if (SampleCode::TitleQ(*evt)) {
            SampleCode::TitleR(evt, "XfermodesBlur");
            return true;
        }
        return this->INHERITED::onQuery(evt);
    }

    virtual void onDrawContent(SkCanvas* canvas) {
        canvas->translate(SkIntToScalar(10), SkIntToScalar(20));

        if (false) {
            SkPaint paint;
            paint.setAntiAlias(true);
            paint.setTextSize(50);
            paint.setTypeface(SkTypeface::CreateFromName("Arial Unicode MS", SkTypeface::kNormal));
            SkSafeUnref(paint.getTypeface());
            char buffer[10];
            size_t len = SkUTF8_FromUnichar(0x8500, buffer);
            canvas->drawText(buffer, len, 40, 40, paint);
            return;
        }
        if (false) {
            SkPaint paint;
            paint.setAntiAlias(true);

            SkRect r0 = { 0, 0, 10.5f, 20 };
            SkRect r1 = { 10.5f, 10, 20, 30 };
            paint.setColor(SK_ColorRED);
            canvas->drawRect(r0, paint);
            paint.setColor(SK_ColorBLUE);
            canvas->drawRect(r1, paint);
            return;
        }

        const struct {
            SkXfermode::Mode  fMode;
            const char*         fLabel;
        } gModes[] = {
            { SkXfermode::kClear_Mode,    "Clear"     },
            { SkXfermode::kSrc_Mode,      "Src"       },
            { SkXfermode::kDst_Mode,      "Dst"       },
            { SkXfermode::kSrcOver_Mode,  "SrcOver"   },
            { SkXfermode::kDstOver_Mode,  "DstOver"   },
            { SkXfermode::kSrcIn_Mode,    "SrcIn"     },
            { SkXfermode::kDstIn_Mode,    "DstIn"     },
            { SkXfermode::kSrcOut_Mode,   "SrcOut"    },
            { SkXfermode::kDstOut_Mode,   "DstOut"    },
            { SkXfermode::kSrcATop_Mode,  "SrcATop"   },
            { SkXfermode::kDstATop_Mode,  "DstATop"   },
            { SkXfermode::kXor_Mode,      "Xor"       },

            { SkXfermode::kPlus_Mode,         "Plus"          },
            /*{ SkXfermode::kModulate_Mode,     "Modulate"      },
            { SkXfermode::kScreen_Mode,       "Screen"        },
            { SkXfermode::kOverlay_Mode,      "Overlay"       },
            { SkXfermode::kDarken_Mode,       "Darken"        },
            { SkXfermode::kLighten_Mode,      "Lighten"       },
            { SkXfermode::kColorDodge_Mode,   "ColorDodge"    },
            { SkXfermode::kColorBurn_Mode,    "ColorBurn"     },
            { SkXfermode::kHardLight_Mode,    "HardLight"     },
            { SkXfermode::kSoftLight_Mode,    "SoftLight"     },
            { SkXfermode::kDifference_Mode,   "Difference"    },
            { SkXfermode::kExclusion_Mode,    "Exclusion"     },*/
        };

        const SkScalar w = SkIntToScalar(W);
        const SkScalar h = SkIntToScalar(H);
        SkMatrix m;
        m.setScale(SkIntToScalar(6), SkIntToScalar(6));
        auto s = SkShader::MakeBitmapShader(fBG, SkShader::kRepeat_TileMode,
                                            SkShader::kRepeat_TileMode, &m);

        SkPaint labelP;
        labelP.setAntiAlias(true);
        labelP.setLCDRenderText(true);
        labelP.setTextAlign(SkPaint::kCenter_Align);
        setNamedTypeface(&labelP, "Menlo Regular");

        const int W = 5;

        SkScalar x0 = 0;
        for (int twice = 0; twice < 2; twice++) {
            SkScalar x = x0, y = 0;
            for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); i++) {
                SkXfermode* mode = SkXfermode::Create(gModes[i].fMode);
                SkAutoUnref aur(mode);
                SkRect r;
                r.set(x, y, x+w, y+h);

                SkPaint p;
                p.setStyle(SkPaint::kFill_Style);
                p.setShader(s);
                canvas->drawRect(r, p);

                canvas->saveLayer(&r, nullptr);
                draw_mode(canvas, mode, twice ? 0x88 : 0xFF, r.fLeft, r.fTop);
                canvas->restore();

                r.inset(-SK_ScalarHalf, -SK_ScalarHalf);
                p.setStyle(SkPaint::kStroke_Style);
                p.setShader(nullptr);
                canvas->drawRect(r, p);

                canvas->drawText(gModes[i].fLabel, strlen(gModes[i].fLabel),
                                 x + w/2, y - labelP.getTextSize()/2, labelP);
                x += w + SkIntToScalar(10);
                if ((i % W) == W - 1) {
                    x = x0;
                    y += h + SkIntToScalar(30);
                }
            }
            x0 += SkIntToScalar(400);
        }
        s->unref();
    }

private:
    typedef SampleView INHERITED;
};

//////////////////////////////////////////////////////////////////////////////

static SkView* MyFactory() { return new XfermodesBlurView; }
static SkViewRegister reg(MyFactory);
<commit_msg>Fix GM:XfermodesBlur double unref<commit_after>/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SampleCode.h"
#include "SkView.h"
#include "SkBlurMask.h"
#include "SkCanvas.h"
#include "SkCornerPathEffect.h"
#include "SkGradientShader.h"
#include "SkGraphics.h"
#include "SkImageDecoder.h"
#include "SkPath.h"
#include "SkRandom.h"
#include "SkRegion.h"
#include "SkShader.h"
#include "SkUtils.h"
#include "SkColorPriv.h"
#include "SkColorFilter.h"
#include "SkTime.h"
#include "SkTypeface.h"
#include "SkXfermode.h"

#include "SkStream.h"
#include "SkColorPriv.h"
#include "SkImageDecoder.h"
#include "SkBlurMaskFilter.h"

static void setNamedTypeface(SkPaint* paint, const char name[]) {
    SkTypeface* face = SkTypeface::CreateFromName(name, SkTypeface::kNormal);
    paint->setTypeface(face);
    SkSafeUnref(face);
}

static uint16_t gBG[] = { 0xFFFF, 0xCCCF, 0xCCCF, 0xFFFF };

class XfermodesBlurView : public SampleView {
    SkBitmap    fBG;
    SkBitmap    fSrcB, fDstB;

    void draw_mode(SkCanvas* canvas, SkXfermode* mode, int alpha,
                   SkScalar x, SkScalar y) {
        SkPaint p;
        SkMaskFilter* mf = SkBlurMaskFilter::Create(kNormal_SkBlurStyle,
                                       SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(5)),
                                       SkBlurMaskFilter::kNone_BlurFlag);
        p.setMaskFilter(mf)->unref();

        SkScalar ww = SkIntToScalar(W);
        SkScalar hh = SkIntToScalar(H);

        // draw a circle covering the upper
        // left three quarters of the canvas
        p.setColor(0xFFCC44FF);
        SkRect r;
        r.set(0, 0, ww*3/4, hh*3/4);
        r.offset(x, y);
        canvas->drawOval(r, p);

        p.setXfermode(mode);

        // draw a square overlapping the circle
        // in the lower right of the canvas
        p.setColor(0x00AA6633 | alpha << 24);
        r.set(ww/3, hh/3, ww*19/20, hh*19/20);
        r.offset(x, y);
        canvas->drawRect(r, p);
    }

public:
    const static int W = 64;
    const static int H = 64;
    XfermodesBlurView() {
        fBG.installPixels(SkImageInfo::Make(2, 2, kARGB_4444_SkColorType, kPremul_SkAlphaType),
                          gBG, 4);
    }

protected:
    // overrides from SkEventSink
    virtual bool onQuery(SkEvent* evt) {
        if (SampleCode::TitleQ(*evt)) {
            SampleCode::TitleR(evt, "XfermodesBlur");
            return true;
        }
        return this->INHERITED::onQuery(evt);
    }

    virtual void onDrawContent(SkCanvas* canvas) {
        canvas->translate(SkIntToScalar(10), SkIntToScalar(20));

        if (false) {
            SkPaint paint;
            paint.setAntiAlias(true);
            paint.setTextSize(50);
            paint.setTypeface(SkTypeface::CreateFromName("Arial Unicode MS", SkTypeface::kNormal));
            SkSafeUnref(paint.getTypeface());
            char buffer[10];
            size_t len = SkUTF8_FromUnichar(0x8500, buffer);
            canvas->drawText(buffer, len, 40, 40, paint);
            return;
        }
        if (false) {
            SkPaint paint;
            paint.setAntiAlias(true);

            SkRect r0 = { 0, 0, 10.5f, 20 };
            SkRect r1 = { 10.5f, 10, 20, 30 };
            paint.setColor(SK_ColorRED);
            canvas->drawRect(r0, paint);
            paint.setColor(SK_ColorBLUE);
            canvas->drawRect(r1, paint);
            return;
        }

        const struct {
            SkXfermode::Mode  fMode;
            const char*         fLabel;
        } gModes[] = {
            { SkXfermode::kClear_Mode,    "Clear"     },
            { SkXfermode::kSrc_Mode,      "Src"       },
            { SkXfermode::kDst_Mode,      "Dst"       },
            { SkXfermode::kSrcOver_Mode,  "SrcOver"   },
            { SkXfermode::kDstOver_Mode,  "DstOver"   },
            { SkXfermode::kSrcIn_Mode,    "SrcIn"     },
            { SkXfermode::kDstIn_Mode,    "DstIn"     },
            { SkXfermode::kSrcOut_Mode,   "SrcOut"    },
            { SkXfermode::kDstOut_Mode,   "DstOut"    },
            { SkXfermode::kSrcATop_Mode,  "SrcATop"   },
            { SkXfermode::kDstATop_Mode,  "DstATop"   },
            { SkXfermode::kXor_Mode,      "Xor"       },

            { SkXfermode::kPlus_Mode,         "Plus"          },
            /*{ SkXfermode::kModulate_Mode,     "Modulate"      },
            { SkXfermode::kScreen_Mode,       "Screen"        },
            { SkXfermode::kOverlay_Mode,      "Overlay"       },
            { SkXfermode::kDarken_Mode,       "Darken"        },
            { SkXfermode::kLighten_Mode,      "Lighten"       },
            { SkXfermode::kColorDodge_Mode,   "ColorDodge"    },
            { SkXfermode::kColorBurn_Mode,    "ColorBurn"     },
            { SkXfermode::kHardLight_Mode,    "HardLight"     },
            { SkXfermode::kSoftLight_Mode,    "SoftLight"     },
            { SkXfermode::kDifference_Mode,   "Difference"    },
            { SkXfermode::kExclusion_Mode,    "Exclusion"     },*/
        };

        const SkScalar w = SkIntToScalar(W);
        const SkScalar h = SkIntToScalar(H);
        SkMatrix m;
        m.setScale(SkIntToScalar(6), SkIntToScalar(6));
        auto s = SkShader::MakeBitmapShader(fBG, SkShader::kRepeat_TileMode,
                                            SkShader::kRepeat_TileMode, &m);

        SkPaint labelP;
        labelP.setAntiAlias(true);
        labelP.setLCDRenderText(true);
        labelP.setTextAlign(SkPaint::kCenter_Align);
        setNamedTypeface(&labelP, "Menlo Regular");

        const int W = 5;

        SkScalar x0 = 0;
        for (int twice = 0; twice < 2; twice++) {
            SkScalar x = x0, y = 0;
            for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); i++) {
                SkXfermode* mode = SkXfermode::Create(gModes[i].fMode);
                SkAutoUnref aur(mode);
                SkRect r;
                r.set(x, y, x+w, y+h);

                SkPaint p;
                p.setStyle(SkPaint::kFill_Style);
                p.setShader(s);
                canvas->drawRect(r, p);

                canvas->saveLayer(&r, nullptr);
                draw_mode(canvas, mode, twice ? 0x88 : 0xFF, r.fLeft, r.fTop);
                canvas->restore();

                r.inset(-SK_ScalarHalf, -SK_ScalarHalf);
                p.setStyle(SkPaint::kStroke_Style);
                p.setShader(nullptr);
                canvas->drawRect(r, p);

                canvas->drawText(gModes[i].fLabel, strlen(gModes[i].fLabel),
                                 x + w/2, y - labelP.getTextSize()/2, labelP);
                x += w + SkIntToScalar(10);
                if ((i % W) == W - 1) {
                    x = x0;
                    y += h + SkIntToScalar(30);
                }
            }
            x0 += SkIntToScalar(400);
        }
    }

private:
    typedef SampleView INHERITED;
};

//////////////////////////////////////////////////////////////////////////////

static SkView* MyFactory() { return new XfermodesBlurView; }
static SkViewRegister reg(MyFactory);
<|endoftext|>


<commit_before>#include <libpq-fe.h>
#include <node.h>
#include <node_events.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>

#define LOG(msg) printf("%s\n",msg)
#define TRACE(msg) //printf("%s\n", msg);

#define THROW(msg) return ThrowException(Exception::Error(String::New(msg)));

using namespace v8;
using namespace node;

static Persistent<String> connect_symbol;
static Persistent<String> error_symbol;
static Persistent<String> ready_symbol;
static Persistent<String> row_symbol;
static Persistent<String> notice_symbol;
static Persistent<String> severity_symbol;
static Persistent<String> code_symbol;
static Persistent<String> message_symbol;
static Persistent<String> detail_symbol;
static Persistent<String> hint_symbol;
static Persistent<String> position_symbol;
static Persistent<String> internalPosition_symbol;
static Persistent<String> internalQuery_symbol;
static Persistent<String> where_symbol;
static Persistent<String> file_symbol;
static Persistent<String> line_symbol;
static Persistent<String> routine_symbol;

class Connection : public EventEmitter {

public:

  //creates the V8 objects & attaches them to the module (target)
  static void
  Init (Handle<Object> target)
  {
    HandleScope scope;
    Local<FunctionTemplate> t = FunctionTemplate::New(New);

    t->Inherit(EventEmitter::constructor_template);
    t->InstanceTemplate()->SetInternalFieldCount(1);
    t->SetClassName(String::NewSymbol("Connection"));

    connect_symbol = NODE_PSYMBOL("connect");
    error_symbol = NODE_PSYMBOL("_error");
    ready_symbol = NODE_PSYMBOL("_readyForQuery");
    notice_symbol = NODE_PSYMBOL("notice");
    row_symbol = NODE_PSYMBOL("_row");
    severity_symbol = NODE_PSYMBOL("severity");
    code_symbol = NODE_PSYMBOL("code");
    message_symbol = NODE_PSYMBOL("message");
    detail_symbol = NODE_PSYMBOL("detail");
    hint_symbol = NODE_PSYMBOL("hint");
    position_symbol = NODE_PSYMBOL("position");
    internalPosition_symbol = NODE_PSYMBOL("internalPosition");
    internalQuery_symbol = NODE_PSYMBOL("internalQuery");
    where_symbol = NODE_PSYMBOL("where");
    file_symbol = NODE_PSYMBOL("file");
    line_symbol = NODE_PSYMBOL("line");
    routine_symbol = NODE_PSYMBOL("routine");

    NODE_SET_PROTOTYPE_METHOD(t, "connect", Connect);
    NODE_SET_PROTOTYPE_METHOD(t, "_sendQuery", SendQuery);
    NODE_SET_PROTOTYPE_METHOD(t, "_sendQueryWithParams", SendQueryWithParams);
    NODE_SET_PROTOTYPE_METHOD(t, "end", End);

    target->Set(String::NewSymbol("Connection"), t->GetFunction());
    TRACE("created class");
  }

  //static function called by libev as callback entrypoint
  static void
  io_event(EV_P_ ev_io *w, int revents)
  {
    TRACE("Received IO event");
    Connection *connection = static_cast<Connection*>(w->data);
    connection->HandleIOEvent(revents);
  }

  //v8 entry point into Connection#connect
  static Handle<Value>
  Connect(const Arguments& args)
  {
    HandleScope scope;
    Connection *self = ObjectWrap::Unwrap<Connection>(args.This());
    if(args.Length() == 0 || !args[0]->IsString()) {
      THROW("Must include connection string as only argument to connect");
    }

    String::Utf8Value conninfo(args[0]->ToString());
    self->Connect(*conninfo);

    return Undefined();
  }

  //v8 entry point into Connection#_sendQuery
  static Handle<Value>
  SendQuery(const Arguments& args)
  {
    HandleScope scope;
    Connection *self = ObjectWrap::Unwrap<Connection>(args.This());
    if(!args[0]->IsString()) {
      return ThrowException(Exception::Error(String::New("First parameter must be a string query")));
    }

    char* queryText = MallocCString(args[0]);
    int result = self->Send(queryText);
    free(queryText);
    if(result == 0) {
      THROW("PQsendQuery returned error code");
    }
    //TODO should we flush before throw?
    self->Flush();
    return Undefined();
  }

  //v8 entry point into Connection#_sendQueryWithParams
  static Handle<Value>
  SendQueryWithParams(const Arguments& args)
  {
    HandleScope scope;
    Connection *self = ObjectWrap::Unwrap<Connection>(args.This());
    if(!args[0]->IsString()) {
      return ThrowException(Exception::Error(String::New("First parameter must be a string query")));
    }

    if(!args[1]->IsArray()) {
      return ThrowException(Exception::Error(String::New("Values must be array")));
    }

    char* queryText = MallocCString(args[0]);
    Local<Array> params = Local<Array>::Cast(args[1]);
    int len = params->Length();
    char* *paramValues = new char*[len];
    for(int i = 0; i < len; i++) {
      Handle<Value> val = params->Get(i);
      if(!val->IsString()) {
        //TODO this leaks mem
        delete [] paramValues;
        return ThrowException(Exception::Error(String::New("Only string parameters supported")));
      }
      char* cString = MallocCString(val);
      paramValues[i] = cString;
    }

    int result = self->SendQueryParams(queryText, len, paramValues);

    free(queryText);
    for(int i = 0; i < len; i++) {
      free(paramValues[i]);
    }
    delete [] paramValues;
    if(result == 1) {
      return Undefined();
    }
    return ThrowException(Exception::Error(String::New("Could not dispatch parameterized query")));
  }

  static char* MallocCString(v8::Handle<Value> v8String)
  {
    String::Utf8Value utf8String(v8String->ToString());
    char *cString = (char *) malloc(strlen(*utf8String) + 1);
    strcpy(cString, *utf8String);
    return cString;
  }

  //v8 entry point into Connection#end
  static Handle<Value>
  End(const Arguments& args)
  {
    HandleScope scope;

    Connection *self = ObjectWrap::Unwrap<Connection>(args.This());

    self->End();
    return Undefined();
  }

  ev_io read_watcher_;
  ev_io write_watcher_;
  PGconn *connection_;
  bool connecting_;
  Connection () : EventEmitter ()
  {
    connection_ = NULL;
    connecting_ = false;

    TRACE("Initializing ev watchers");
    ev_init(&read_watcher_, io_event);
    read_watcher_.data = this;
    ev_init(&write_watcher_, io_event);
    write_watcher_.data = this;
  }

  ~Connection ()
  {
  }

protected:

  //v8 entry point to constructor
  static Handle<Value>
  New (const Arguments& args)
  {
    HandleScope scope;
    Connection *connection = new Connection();
    connection->Wrap(args.This());

    return args.This();
  }

  int Send(const char *queryText)
  {
    return PQsendQuery(connection_, queryText);
  }

  int SendQueryParams(const char *command, const int nParams, const char * const *paramValues)
  {
    return PQsendQueryParams(connection_, command, nParams, NULL, paramValues, NULL, NULL, 0);
  }

  //flushes socket
  void Flush()
  {
    if(PQflush(connection_) == 1) {
      TRACE("Flushing");
      ev_io_start(EV_DEFAULT_ &write_watcher_);
    }
  }

  //initializes initial async connection to postgres via libpq
  //and hands off control to libev
  bool Connect(const char* conninfo)
  {
    connection_ = PQconnectStart(conninfo);

    if (!connection_) {
      LOG("Connection couldn't be created");
    } else {
      TRACE("Native connection created");
    }

    if (PQsetnonblocking(connection_, 1) == -1) {
      LOG("Unable to set connection to non-blocking");
      PQfinish(connection_);
      connection_ = NULL;
    }

    ConnStatusType status = PQstatus(connection_);

    if(CONNECTION_BAD == status) {
      PQfinish(connection_);
      LOG("Bad connection status");
      connection_ = NULL;
    }

    int fd = PQsocket(connection_);
    if(fd < 0) {
      LOG("socket fd was negative. error");
      return false;
    }

    assert(PQisnonblocking(connection_));

    PQsetNoticeProcessor(connection_, NoticeReceiver, this);

    TRACE("Setting watchers to socket");
    ev_io_set(&read_watcher_, fd, EV_READ);
    ev_io_set(&write_watcher_, fd, EV_WRITE);

    connecting_ = true;
    StartWrite();

    Ref();
    return true;
  }

  static void NoticeReceiver(void *arg, const char *message)
  {
    Connection *self = (Connection*)arg;
    self->HandleNotice(message);
  }

  void HandleNotice(const char *message)
  {
    HandleScope scope;
    Handle<Value> notice = String::New(message);
    Emit(notice_symbol, 1, &notice);
  }

  //called to process io_events from libev
  void HandleIOEvent(int revents)
  {
    if(revents & EV_ERROR) {
      LOG("Connection error.");
      return;
    }

    if(connecting_) {
      TRACE("Processing connecting_ io");
      HandleConnectionIO();
      return;
    }

    if(revents & EV_READ) {
      TRACE("revents & EV_READ");
      if(PQconsumeInput(connection_) == 0) {
        LOG("Something happened, consume input is 0");
        return;
      }

      //declare handlescope as this method is entered via a libev callback
      //and not part of the public v8 interface
      HandleScope scope;

      if (PQisBusy(connection_) == 0) {
        PGresult *result;
        bool didHandleResult = false;
        while ((result = PQgetResult(connection_))) {
          HandleResult(result);
          didHandleResult = true;
          PQclear(result);
        }
        if(didHandleResult) {
          //might have fired from notification
          Emit(ready_symbol, 0, NULL);
        }
      }

      //TODO look at this later
      PGnotify *notify;
      while ((notify = PQnotifies(connection_))) {
        Local<Object> result = Object::New();
        result->Set(String::New("channel"), String::New(notify->relname));
        Handle<Value> res = (Handle<Value>)result;
        Emit((Handle<String>)String::New("notification"), 1, &res);
        PQfreemem(notify);
      }

    }

    if(revents & EV_WRITE) {
      TRACE("revents & EV_WRITE");
      if (PQflush(connection_) == 0) {
        StopWrite();
      }
    }
  }

  void HandleResult(const PGresult* result)
  {
    ExecStatusType status = PQresultStatus(result);
    switch(status) {
    case PGRES_TUPLES_OK:
      HandleTuplesResult(result);
      break;
    case PGRES_FATAL_ERROR:
      HandleErrorResult(result);
      break;
    case PGRES_COMMAND_OK:
    case PGRES_EMPTY_QUERY:
      //do nothing
      break;
    default:
      printf("Unrecogized query status: %s\n", PQresStatus(status));
      break;
    }
  }

  void HandleTuplesResult(const PGresult* result)
  {
    int rowCount = PQntuples(result);
    for(int rowNumber = 0; rowNumber < rowCount; rowNumber++) {
      //create result object for this row
      Local<Array> row = Array::New();
      int fieldCount = PQnfields(result);
      for(int fieldNumber = 0; fieldNumber < fieldCount; fieldNumber++) {
        Local<Object> field = Object::New();
        char* fieldName = PQfname(result, fieldNumber);
        int fieldType = PQftype(result, fieldNumber);
        char* fieldValue = PQgetvalue(result, rowNumber, fieldNumber);
        //TODO use symbols here
        field->Set(String::New("name"), String::New(fieldName));
        field->Set(String::New("value"), String::New(fieldValue));
        field->Set(String::New("type"), Integer::New(fieldType));
        row->Set(Integer::New(fieldNumber), field);
      }

      //not sure about what to dealloc or scope#Close here
      Handle<Value> e = (Handle<Value>)row;
      Emit(row_symbol, 1, &e);
    }
  }

  Handle<Value> WrapFieldValue(const PGresult* result, int rowNumber, int fieldNumber)
  {
    int fieldType = PQftype(result, fieldNumber);
    char* fieldValue = PQgetvalue(result, rowNumber, fieldNumber);
    switch(fieldType) {
    case 23:
      return Integer::New(atoi(fieldValue));
    default:
      return String::New(fieldValue);
    }
  }

  void HandleErrorResult(const PGresult* result)
  {
    HandleScope scope;
    Local<Object> msg = Object::New();
    AttachErrorField(result, msg, severity_symbol, PG_DIAG_SEVERITY);
    AttachErrorField(result, msg, code_symbol, PG_DIAG_SQLSTATE);
    AttachErrorField(result, msg, message_symbol, PG_DIAG_MESSAGE_PRIMARY);
    AttachErrorField(result, msg, detail_symbol, PG_DIAG_MESSAGE_DETAIL);
    AttachErrorField(result, msg, hint_symbol, PG_DIAG_MESSAGE_HINT);
    AttachErrorField(result, msg, position_symbol, PG_DIAG_STATEMENT_POSITION);
    AttachErrorField(result, msg, internalPosition_symbol, PG_DIAG_INTERNAL_POSITION);
    AttachErrorField(result, msg, internalQuery_symbol, PG_DIAG_INTERNAL_QUERY);
    AttachErrorField(result, msg, where_symbol, PG_DIAG_CONTEXT);
    AttachErrorField(result, msg, file_symbol, PG_DIAG_SOURCE_FILE);
    AttachErrorField(result, msg, line_symbol, PG_DIAG_SOURCE_LINE);
    AttachErrorField(result, msg, routine_symbol, PG_DIAG_SOURCE_FUNCTION);
    Handle<Value> m = msg;
    Emit(error_symbol, 1, &m);
  }

  void AttachErrorField(const PGresult *result, const Local<Object> msg, const Persistent<String> symbol, int fieldcode)
  {
    char *val = PQresultErrorField(result, fieldcode);
    if(val) {
      msg->Set(symbol, String::New(val));
    }
  }

  void End()
  {
    StopRead();
    StopWrite();
    PQfinish(connection_);
  }

private:
  void HandleConnectionIO()
  {
    PostgresPollingStatusType status = PQconnectPoll(connection_);
    switch(status) {
    case PGRES_POLLING_READING:
      TRACE("Polled: PGRES_POLLING_READING");
      StopWrite();
      StartRead();
      break;
    case PGRES_POLLING_WRITING:
      TRACE("Polled: PGRES_POLLING_WRITING");
      StopRead();
      StartWrite();
      break;
    case PGRES_POLLING_FAILED:
      StopRead();
      StopWrite();
      TRACE("Polled: PGRES_POLLING_FAILED");
      EmitLastError();
      break;
    case PGRES_POLLING_OK:
      TRACE("Polled: PGRES_POLLING_OK");
      connecting_ = false;
      StartRead();
      Emit(connect_symbol, 0, NULL);
    default:
      //printf("Unknown polling status: %d\n", status);
      break;
    }
  }

  void EmitError(const char *message)
  {
    Local<Value> exception = Exception::Error(String::New(message));
    Emit(error_symbol, 1, &exception);
  }

  void EmitLastError()
  {
    EmitError(PQerrorMessage(connection_));
  }

  void StopWrite()
  {
    TRACE("Stoping write watcher");
    ev_io_stop(EV_DEFAULT_ &write_watcher_);
  }

  void StartWrite()
  {
    TRACE("Starting write watcher");
    ev_io_start(EV_DEFAULT_ &write_watcher_);
  }

  void StopRead()
  {
    TRACE("Stoping read watcher");
    ev_io_stop(EV_DEFAULT_ &read_watcher_);
  }

  void StartRead()
  {
    TRACE("Starting read watcher");
    ev_io_start(EV_DEFAULT_ &read_watcher_);
  }

};

extern "C" void
init (Handle<Object> target)
{
  HandleScope scope;
  Connection::Init(target);
}
<commit_msg>use symbols in row value object property names<commit_after>#include <libpq-fe.h>
#include <node.h>
#include <node_events.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>

#define LOG(msg) printf("%s\n",msg)
#define TRACE(msg) //printf("%s\n", msg);

#define THROW(msg) return ThrowException(Exception::Error(String::New(msg)));

using namespace v8;
using namespace node;

static Persistent<String> connect_symbol;
static Persistent<String> error_symbol;
static Persistent<String> ready_symbol;
static Persistent<String> row_symbol;
static Persistent<String> notice_symbol;
static Persistent<String> severity_symbol;
static Persistent<String> code_symbol;
static Persistent<String> message_symbol;
static Persistent<String> detail_symbol;
static Persistent<String> hint_symbol;
static Persistent<String> position_symbol;
static Persistent<String> internalPosition_symbol;
static Persistent<String> internalQuery_symbol;
static Persistent<String> where_symbol;
static Persistent<String> file_symbol;
static Persistent<String> line_symbol;
static Persistent<String> routine_symbol;
static Persistent<String> name_symbol;
static Persistent<String> value_symbol;
static Persistent<String> type_symbol;

class Connection : public EventEmitter {

public:

  //creates the V8 objects & attaches them to the module (target)
  static void
  Init (Handle<Object> target)
  {
    HandleScope scope;
    Local<FunctionTemplate> t = FunctionTemplate::New(New);

    t->Inherit(EventEmitter::constructor_template);
    t->InstanceTemplate()->SetInternalFieldCount(1);
    t->SetClassName(String::NewSymbol("Connection"));

    connect_symbol = NODE_PSYMBOL("connect");
    error_symbol = NODE_PSYMBOL("_error");
    ready_symbol = NODE_PSYMBOL("_readyForQuery");
    notice_symbol = NODE_PSYMBOL("notice");
    row_symbol = NODE_PSYMBOL("_row");
    severity_symbol = NODE_PSYMBOL("severity");
    code_symbol = NODE_PSYMBOL("code");
    message_symbol = NODE_PSYMBOL("message");
    detail_symbol = NODE_PSYMBOL("detail");
    hint_symbol = NODE_PSYMBOL("hint");
    position_symbol = NODE_PSYMBOL("position");
    internalPosition_symbol = NODE_PSYMBOL("internalPosition");
    internalQuery_symbol = NODE_PSYMBOL("internalQuery");
    where_symbol = NODE_PSYMBOL("where");
    file_symbol = NODE_PSYMBOL("file");
    line_symbol = NODE_PSYMBOL("line");
    routine_symbol = NODE_PSYMBOL("routine");
    name_symbol = NODE_PSYMBOL("name");
    value_symbol = NODE_PSYMBOL("value");
    type_symbol = NODE_PSYMBOL("type");

    NODE_SET_PROTOTYPE_METHOD(t, "connect", Connect);
    NODE_SET_PROTOTYPE_METHOD(t, "_sendQuery", SendQuery);
    NODE_SET_PROTOTYPE_METHOD(t, "_sendQueryWithParams", SendQueryWithParams);
    NODE_SET_PROTOTYPE_METHOD(t, "end", End);

    target->Set(String::NewSymbol("Connection"), t->GetFunction());
    TRACE("created class");
  }

  //static function called by libev as callback entrypoint
  static void
  io_event(EV_P_ ev_io *w, int revents)
  {
    TRACE("Received IO event");
    Connection *connection = static_cast<Connection*>(w->data);
    connection->HandleIOEvent(revents);
  }

  //v8 entry point into Connection#connect
  static Handle<Value>
  Connect(const Arguments& args)
  {
    HandleScope scope;
    Connection *self = ObjectWrap::Unwrap<Connection>(args.This());
    if(args.Length() == 0 || !args[0]->IsString()) {
      THROW("Must include connection string as only argument to connect");
    }

    String::Utf8Value conninfo(args[0]->ToString());
    self->Connect(*conninfo);

    return Undefined();
  }

  //v8 entry point into Connection#_sendQuery
  static Handle<Value>
  SendQuery(const Arguments& args)
  {
    HandleScope scope;
    Connection *self = ObjectWrap::Unwrap<Connection>(args.This());
    if(!args[0]->IsString()) {
      return ThrowException(Exception::Error(String::New("First parameter must be a string query")));
    }

    char* queryText = MallocCString(args[0]);
    int result = self->Send(queryText);
    free(queryText);
    if(result == 0) {
      THROW("PQsendQuery returned error code");
    }
    //TODO should we flush before throw?
    self->Flush();
    return Undefined();
  }

  //v8 entry point into Connection#_sendQueryWithParams
  static Handle<Value>
  SendQueryWithParams(const Arguments& args)
  {
    HandleScope scope;
    Connection *self = ObjectWrap::Unwrap<Connection>(args.This());
    if(!args[0]->IsString()) {
      return ThrowException(Exception::Error(String::New("First parameter must be a string query")));
    }

    if(!args[1]->IsArray()) {
      return ThrowException(Exception::Error(String::New("Values must be array")));
    }

    char* queryText = MallocCString(args[0]);
    Local<Array> params = Local<Array>::Cast(args[1]);
    int len = params->Length();
    char* *paramValues = new char*[len];
    for(int i = 0; i < len; i++) {
      Handle<Value> val = params->Get(i);
      if(!val->IsString()) {
        //TODO this leaks mem
        delete [] paramValues;
        return ThrowException(Exception::Error(String::New("Only string parameters supported")));
      }
      char* cString = MallocCString(val);
      paramValues[i] = cString;
    }

    int result = self->SendQueryParams(queryText, len, paramValues);

    free(queryText);
    for(int i = 0; i < len; i++) {
      free(paramValues[i]);
    }
    delete [] paramValues;
    if(result == 1) {
      return Undefined();
    }
    return ThrowException(Exception::Error(String::New("Could not dispatch parameterized query")));
  }

  static char* MallocCString(v8::Handle<Value> v8String)
  {
    String::Utf8Value utf8String(v8String->ToString());
    char *cString = (char *) malloc(strlen(*utf8String) + 1);
    strcpy(cString, *utf8String);
    return cString;
  }

  //v8 entry point into Connection#end
  static Handle<Value>
  End(const Arguments& args)
  {
    HandleScope scope;

    Connection *self = ObjectWrap::Unwrap<Connection>(args.This());

    self->End();
    return Undefined();
  }

  ev_io read_watcher_;
  ev_io write_watcher_;
  PGconn *connection_;
  bool connecting_;
  Connection () : EventEmitter ()
  {
    connection_ = NULL;
    connecting_ = false;

    TRACE("Initializing ev watchers");
    ev_init(&read_watcher_, io_event);
    read_watcher_.data = this;
    ev_init(&write_watcher_, io_event);
    write_watcher_.data = this;
  }

  ~Connection ()
  {
  }

protected:

  //v8 entry point to constructor
  static Handle<Value>
  New (const Arguments& args)
  {
    HandleScope scope;
    Connection *connection = new Connection();
    connection->Wrap(args.This());

    return args.This();
  }

  int Send(const char *queryText)
  {
    return PQsendQuery(connection_, queryText);
  }

  int SendQueryParams(const char *command, const int nParams, const char * const *paramValues)
  {
    return PQsendQueryParams(connection_, command, nParams, NULL, paramValues, NULL, NULL, 0);
  }

  //flushes socket
  void Flush()
  {
    if(PQflush(connection_) == 1) {
      TRACE("Flushing");
      ev_io_start(EV_DEFAULT_ &write_watcher_);
    }
  }

  //initializes initial async connection to postgres via libpq
  //and hands off control to libev
  bool Connect(const char* conninfo)
  {
    connection_ = PQconnectStart(conninfo);

    if (!connection_) {
      LOG("Connection couldn't be created");
    } else {
      TRACE("Native connection created");
    }

    if (PQsetnonblocking(connection_, 1) == -1) {
      LOG("Unable to set connection to non-blocking");
      PQfinish(connection_);
      connection_ = NULL;
    }

    ConnStatusType status = PQstatus(connection_);

    if(CONNECTION_BAD == status) {
      PQfinish(connection_);
      LOG("Bad connection status");
      connection_ = NULL;
    }

    int fd = PQsocket(connection_);
    if(fd < 0) {
      LOG("socket fd was negative. error");
      return false;
    }

    assert(PQisnonblocking(connection_));

    PQsetNoticeProcessor(connection_, NoticeReceiver, this);

    TRACE("Setting watchers to socket");
    ev_io_set(&read_watcher_, fd, EV_READ);
    ev_io_set(&write_watcher_, fd, EV_WRITE);

    connecting_ = true;
    StartWrite();

    Ref();
    return true;
  }

  static void NoticeReceiver(void *arg, const char *message)
  {
    Connection *self = (Connection*)arg;
    self->HandleNotice(message);
  }

  void HandleNotice(const char *message)
  {
    HandleScope scope;
    Handle<Value> notice = String::New(message);
    Emit(notice_symbol, 1, &notice);
  }

  //called to process io_events from libev
  void HandleIOEvent(int revents)
  {
    if(revents & EV_ERROR) {
      LOG("Connection error.");
      return;
    }

    if(connecting_) {
      TRACE("Processing connecting_ io");
      HandleConnectionIO();
      return;
    }

    if(revents & EV_READ) {
      TRACE("revents & EV_READ");
      if(PQconsumeInput(connection_) == 0) {
        LOG("Something happened, consume input is 0");
        return;
      }

      //declare handlescope as this method is entered via a libev callback
      //and not part of the public v8 interface
      HandleScope scope;

      if (PQisBusy(connection_) == 0) {
        PGresult *result;
        bool didHandleResult = false;
        while ((result = PQgetResult(connection_))) {
          HandleResult(result);
          didHandleResult = true;
          PQclear(result);
        }
        if(didHandleResult) {
          //might have fired from notification
          Emit(ready_symbol, 0, NULL);
        }
      }

      //TODO look at this later
      PGnotify *notify;
      while ((notify = PQnotifies(connection_))) {
        Local<Object> result = Object::New();
        result->Set(String::New("channel"), String::New(notify->relname));
        Handle<Value> res = (Handle<Value>)result;
        Emit((Handle<String>)String::New("notification"), 1, &res);
        PQfreemem(notify);
      }

    }

    if(revents & EV_WRITE) {
      TRACE("revents & EV_WRITE");
      if (PQflush(connection_) == 0) {
        StopWrite();
      }
    }
  }

  void HandleResult(const PGresult* result)
  {
    ExecStatusType status = PQresultStatus(result);
    switch(status) {
    case PGRES_TUPLES_OK:
      HandleTuplesResult(result);
      break;
    case PGRES_FATAL_ERROR:
      HandleErrorResult(result);
      break;
    case PGRES_COMMAND_OK:
    case PGRES_EMPTY_QUERY:
      //do nothing
      break;
    default:
      printf("Unrecogized query status: %s\n", PQresStatus(status));
      break;
    }
  }

  void HandleTuplesResult(const PGresult* result)
  {
    int rowCount = PQntuples(result);
    for(int rowNumber = 0; rowNumber < rowCount; rowNumber++) {
      //create result object for this row
      Local<Array> row = Array::New();
      int fieldCount = PQnfields(result);
      for(int fieldNumber = 0; fieldNumber < fieldCount; fieldNumber++) {
        Local<Object> field = Object::New();
        char* fieldName = PQfname(result, fieldNumber);
        int fieldType = PQftype(result, fieldNumber);
        char* fieldValue = PQgetvalue(result, rowNumber, fieldNumber);
        //TODO use symbols here
        field->Set(name_symbol, String::New(fieldName));
        field->Set(value_symbol, String::New(fieldValue));
        field->Set(type_symbol, Integer::New(fieldType));
        row->Set(Integer::New(fieldNumber), field);
      }

      //not sure about what to dealloc or scope#Close here
      Handle<Value> e = (Handle<Value>)row;
      Emit(row_symbol, 1, &e);
    }
  }

  Handle<Value> WrapFieldValue(const PGresult* result, int rowNumber, int fieldNumber)
  {
    int fieldType = PQftype(result, fieldNumber);
    char* fieldValue = PQgetvalue(result, rowNumber, fieldNumber);
    switch(fieldType) {
    case 23:
      return Integer::New(atoi(fieldValue));
    default:
      return String::New(fieldValue);
    }
  }

  void HandleErrorResult(const PGresult* result)
  {
    HandleScope scope;
    Local<Object> msg = Object::New();
    AttachErrorField(result, msg, severity_symbol, PG_DIAG_SEVERITY);
    AttachErrorField(result, msg, code_symbol, PG_DIAG_SQLSTATE);
    AttachErrorField(result, msg, message_symbol, PG_DIAG_MESSAGE_PRIMARY);
    AttachErrorField(result, msg, detail_symbol, PG_DIAG_MESSAGE_DETAIL);
    AttachErrorField(result, msg, hint_symbol, PG_DIAG_MESSAGE_HINT);
    AttachErrorField(result, msg, position_symbol, PG_DIAG_STATEMENT_POSITION);
    AttachErrorField(result, msg, internalPosition_symbol, PG_DIAG_INTERNAL_POSITION);
    AttachErrorField(result, msg, internalQuery_symbol, PG_DIAG_INTERNAL_QUERY);
    AttachErrorField(result, msg, where_symbol, PG_DIAG_CONTEXT);
    AttachErrorField(result, msg, file_symbol, PG_DIAG_SOURCE_FILE);
    AttachErrorField(result, msg, line_symbol, PG_DIAG_SOURCE_LINE);
    AttachErrorField(result, msg, routine_symbol, PG_DIAG_SOURCE_FUNCTION);
    Handle<Value> m = msg;
    Emit(error_symbol, 1, &m);
  }

  void AttachErrorField(const PGresult *result, const Local<Object> msg, const Persistent<String> symbol, int fieldcode)
  {
    char *val = PQresultErrorField(result, fieldcode);
    if(val) {
      msg->Set(symbol, String::New(val));
    }
  }

  void End()
  {
    StopRead();
    StopWrite();
    PQfinish(connection_);
  }

private:
  void HandleConnectionIO()
  {
    PostgresPollingStatusType status = PQconnectPoll(connection_);
    switch(status) {
    case PGRES_POLLING_READING:
      TRACE("Polled: PGRES_POLLING_READING");
      StopWrite();
      StartRead();
      break;
    case PGRES_POLLING_WRITING:
      TRACE("Polled: PGRES_POLLING_WRITING");
      StopRead();
      StartWrite();
      break;
    case PGRES_POLLING_FAILED:
      StopRead();
      StopWrite();
      TRACE("Polled: PGRES_POLLING_FAILED");
      EmitLastError();
      break;
    case PGRES_POLLING_OK:
      TRACE("Polled: PGRES_POLLING_OK");
      connecting_ = false;
      StartRead();
      Emit(connect_symbol, 0, NULL);
    default:
      //printf("Unknown polling status: %d\n", status);
      break;
    }
  }

  void EmitError(const char *message)
  {
    Local<Value> exception = Exception::Error(String::New(message));
    Emit(error_symbol, 1, &exception);
  }

  void EmitLastError()
  {
    EmitError(PQerrorMessage(connection_));
  }

  void StopWrite()
  {
    TRACE("Stoping write watcher");
    ev_io_stop(EV_DEFAULT_ &write_watcher_);
  }

  void StartWrite()
  {
    TRACE("Starting write watcher");
    ev_io_start(EV_DEFAULT_ &write_watcher_);
  }

  void StopRead()
  {
    TRACE("Stoping read watcher");
    ev_io_stop(EV_DEFAULT_ &read_watcher_);
  }

  void StartRead()
  {
    TRACE("Starting read watcher");
    ev_io_start(EV_DEFAULT_ &read_watcher_);
  }

};

extern "C" void
init (Handle<Object> target)
{
  HandleScope scope;
  Connection::Init(target);
}
<|endoftext|>


<commit_before>/**
 * @author See Contributors.txt for code contributors and overview of BadgerDB.
 *
 * @section LICENSE
 * Copyright (c) 2012 Database Group, Computer Sciences Department, University of Wisconsin-Madison.
 */

#include <memory>
#include <iostream>
#include "buffer.h"
#include "exceptions/buffer_exceeded_exception.h"
#include "exceptions/page_not_pinned_exception.h"
#include "exceptions/page_pinned_exception.h"
#include "exceptions/bad_buffer_exception.h"
#include "exceptions/hash_not_found_exception.h"

namespace badgerdb {

//----------------------------------------
// Constructor of the class BufMgr
//----------------------------------------

BufMgr::BufMgr(std::uint32_t bufs)
	: numBufs(bufs) {
	bufDescTable = new BufDesc[bufs];

  for (FrameId i = 0; i < bufs; i++)
  {
  	bufDescTable[i].frameNo = i;
  	bufDescTable[i].valid = false;
  }

  bufPool = new Page[bufs];

  int htsize = ((((int) (bufs * 1.2))*2)/2)+1;
  hashTable = new BufHashTbl (htsize);  // allocate the buffer hash table

  clockHand = bufs - 1;
}

//flush all the frames and clear all memory
BufMgr::~BufMgr() {
}

void BufMgr::advanceClock()
{
    clockHand = (clockHand + 1) % numBufs;
}

//Implement the clock algorithm
//add a pinned count, if pinned count = numBufs, then throw exception
//run through each buf and check for validity following diagram.
void BufMgr::allocBuf(FrameId & frame)
{
    //track if a frame has been found
    bool frameFound = false;

    std::uint32_t pinnedCount = 0;

    //start loop, until frame is found. Only time it will leave loop is if frame is found
    //or bufferexceededexception occurs
    while(!frameFound && pinnedCount < numBufs){

        advanceClock();

        //found a buffer frame that can be used, exit loop
        if(!bufDescTable[clockHand].valid){

            frameFound = true;
            break;

        } //check the refbit, if it is false then frame is found and the entry in the hashtable needs to be removed
        else if(bufDescTable[clockHand].refbit){
            bufDescTable[clockHand].refbit = false;
            continue;
        } else if(bufDescTable[clockHand].pinCnt > 0) {
            pinnedCount++;
            continue;
        }else{

            if(bufDescTable[clockHand].dirty){
                bufDescTable[clockHand].file->writePage(bufPool[clockHand]);
            }
            frameFound = true;
            //remove the hashtable entry
            hashTable->remove(bufDescTable[clockHand].file, bufDescTable[clockHand].pageNo);
        }

    }
    //All pages are pinned
    if(pinnedCount == numBufs){
        throw BufferExceededException();
    } else {
        frame = clockHand;

        bufDescTable[clockHand].Clear();
    }

}

void BufMgr::readPage(File* file, const PageId pageNo, Page*& page)
{
}

//set the frame that the page is allocated to
void BufMgr::unPinPage(File* file, const PageId pageNo, const bool dirty)
{

}

void BufMgr::allocPage(File* file, PageId &pageNo, Page*& page)
{
}

//
void BufMgr::flushFile(const File* file)
{
}

//
void BufMgr::disposePage(File* file, const PageId PageNo)
{
}

void BufMgr::printSelf(void)
{
  BufDesc* tmpbuf;
	int validFrames = 0;

  for (std::uint32_t i = 0; i < numBufs; i++)
	{
  	tmpbuf = &(bufDescTable[i]);
		std::cout << "FrameNo:" << i << " ";
		tmpbuf->Print();

  	if (tmpbuf->valid == true)
    	validFrames++;
  }

	std::cout << "Total Number of Valid Frames:" << validFrames << "\n";
}

}
<commit_msg>implemnted allocPage<commit_after>/**
 * @author See Contributors.txt for code contributors and overview of BadgerDB.
 *
 * @section LICENSE
 * Copyright (c) 2012 Database Group, Computer Sciences Department, University of Wisconsin-Madison.
 */

#include <memory>
#include <iostream>
#include "buffer.h"
#include "exceptions/buffer_exceeded_exception.h"
#include "exceptions/page_not_pinned_exception.h"
#include "exceptions/page_pinned_exception.h"
#include "exceptions/bad_buffer_exception.h"
#include "exceptions/hash_not_found_exception.h"

namespace badgerdb {

//----------------------------------------
// Constructor of the class BufMgr
//----------------------------------------

BufMgr::BufMgr(std::uint32_t bufs)
	: numBufs(bufs) {
	bufDescTable = new BufDesc[bufs];

  for (FrameId i = 0; i < bufs; i++)
  {
  	bufDescTable[i].frameNo = i;
  	bufDescTable[i].valid = false;
  }

  bufPool = new Page[bufs];

  int htsize = ((((int) (bufs * 1.2))*2)/2)+1;
  hashTable = new BufHashTbl (htsize);  // allocate the buffer hash table

  clockHand = bufs - 1;
}

//flush all the frames and clear all memory
BufMgr::~BufMgr() {
}

void BufMgr::advanceClock()
{
    clockHand = (clockHand + 1) % numBufs;
}

//Implement the clock algorithm
//add a pinned count, if pinned count = numBufs, then throw exception
//run through each buf and check for validity following diagram.
void BufMgr::allocBuf(FrameId & frame)
{
    //track if a frame has been found
    bool frameFound = false;

    std::uint32_t pinnedCount = 0;

    //start loop, until frame is found. Only time it will leave loop is if frame is found
    //or bufferexceededexception occurs
    while(!frameFound && pinnedCount < numBufs){

        advanceClock();

        //found a buffer frame that can be used, exit loop
        if(!bufDescTable[clockHand].valid){

            frameFound = true;
            break;

        } //check the refbit, if it is false then frame is found and the entry in the hashtable needs to be removed
        else if(bufDescTable[clockHand].refbit){
            bufDescTable[clockHand].refbit = false;
            continue;
        } else if(bufDescTable[clockHand].pinCnt > 0) {
            pinnedCount++;
            continue;
        }else{

            if(bufDescTable[clockHand].dirty){
                bufDescTable[clockHand].file->writePage(bufPool[clockHand]);
            }
            frameFound = true;
            //remove the hashtable entry
            hashTable->remove(bufDescTable[clockHand].file, bufDescTable[clockHand].pageNo);
        }

    }
    //All pages are pinned
    if(pinnedCount == numBufs){
        throw BufferExceededException();
    } else {
        frame = clockHand;

        bufDescTable[clockHand].Clear();
    }

}

void BufMgr::readPage(File* file, const PageId pageNo, Page*& page)
{
}

//set the frame that the page is allocated to
void BufMgr::unPinPage(File* file, const PageId pageNo, const bool dirty)
{

}

void BufMgr::allocPage(File* file, PageId &pageNo, Page*& page)
{
	FrameId frameNumber = 0;

	//allocate page and get buffer frame pool
	Page filePage = file->allocatePage();
	allocBuf(frameNumber);
	pageNo = filePage.page_number();

	//insert into hashtable then set frame
	hashTable->insert(file, pageNo, frameNumber);
	bufDescTable[frameNumber].Set(file, pageNo);
	bufPool[frameNumber] = filePage;
	//passs correct pointer
	page = &bufPool[frameNumber];

}

//
void BufMgr::flushFile(const File* file)
{
}

//
void BufMgr::disposePage(File* file, const PageId PageNo)
{
}

void BufMgr::printSelf(void)
{
  BufDesc* tmpbuf;
	int validFrames = 0;

  for (std::uint32_t i = 0; i < numBufs; i++)
	{
  	tmpbuf = &(bufDescTable[i]);
		std::cout << "FrameNo:" << i << " ";
		tmpbuf->Print();

  	if (tmpbuf->valid == true)
    	validFrames++;
  }

	std::cout << "Total Number of Valid Frames:" << validFrames << "\n";
}

}
<|endoftext|>


<commit_before>#include <array>
#include <sstream>
#include <istream>
#include <iostream>

#include "builtin.hh"
#include "util.hh"
#include "number.hh"
#include "procedure.hh"
#include "lisp_ptr.hh"
#include "eval.hh"
#include "builtin_util.hh"
#include "reader.hh"
#include "printer.hh"
#include "vm.hh"
#include "port.hh"

#include "builtin_boolean.hh"
#include "builtin_char.hh"
#include "builtin_cons.hh"
#include "builtin_equal.hh"
#include "builtin_extra.hh"
#include "builtin_numeric.hh"
#include "builtin_port.hh"
#include "builtin_procedure.hh"
#include "builtin_string.hh"
#include "builtin_symbol.hh"
#include "builtin_syntax.hh"
#include "builtin_vector.hh"

using namespace std;
using namespace Procedure;

namespace {

static const char null_env_symname[] = "null-env-value";
static const char r5rs_env_symname[] = "r5rs-env-value";
static const char interaction_env_symname[] = "interaction-env-value";

static
Lisp_ptr env_pick_2(const char* name){
  ZsArgs args{1};
  auto num = args[0].get<Number*>();
  if(!num){
    throw builtin_type_check_failed(name, Ptr_tag::number, args[0]);
  }

  if(num->type() != Number::Type::integer){
    throw make_zs_error("native func: %s: passed number is not exact integer\n", name);
  }

  auto ver = num->get<Number::integer_type>();
  if(ver != 5l){
    throw make_zs_error("native func: %s: passed number is not 5 (supplied %ld)\n",
                        name, ver);
  }

  return vm.find(intern(vm.symtable(), name));
}

Lisp_ptr env_r5rs(){
  return env_pick_2(r5rs_env_symname);
}

Lisp_ptr env_null(){
  return env_pick_2(null_env_symname);
}

Lisp_ptr env_interactive(){
  ZsArgs args{0};
  return vm.find(intern(vm.symtable(), interaction_env_symname));
}

Lisp_ptr eval_func(){
  ZsArgs args{2};
  auto env = args[1].get<Env*>();
  if(!env){
    throw builtin_type_check_failed("eval", Ptr_tag::env, args[1]);
  }

  auto oldenv = vm.frame();
  vm.set_frame(env);
  vm.code.insert(vm.code.end(),
                 {oldenv, vm_op_leave_frame, args[0]});
  return vm_op_nop;
}

Lisp_ptr load_func(){
  ZsArgs args{1};
  auto str = args[0].get<String*>();
  if(!str){
    throw builtin_type_check_failed("load", Ptr_tag::string, args[0]);
  }

  stringstream f(*str, ios_base::in);
  if(!f){
    throw zs_error("load error: failed at opening file\n");
  }

  load(&f);
  return vm_op_nop;
}

} //namespace

static const BuiltinFunc
builtin_syntax_funcs[] = {
#include "builtin_equal.defs.hh"
#include "builtin_syntax.defs.hh"
};

static const BuiltinFunc
builtin_funcs[] = {
  {"eval", {
      eval_func,
      {Calling::function, 2}}},

  {"scheme-report-environment", {
      env_r5rs,
      {Calling::function, 1}}},
  {"null-environment", {
      env_null,
      {Calling::function, 1}}},
  {"interaction-environment", {
      env_interactive,
      {Calling::function, 0}}},

  {"load", {
      load_func,
      {Calling::function, 1}}},

#include "builtin_boolean.defs.hh"
#include "builtin_char.defs.hh"
#include "builtin_cons.defs.hh"
#include "builtin_numeric.defs.hh"
#include "builtin_port.defs.hh"
#include "builtin_procedure.defs.hh"
#include "builtin_string.defs.hh"
#include "builtin_symbol.defs.hh"
#include "builtin_vector.defs.hh"
};

static const BuiltinFunc
builtin_extra_funcs[] = {
#include "builtin_extra.defs.hh"
};

static void install_builtin_native(const BuiltinFunc bf[], size_t s){
  for(size_t i = 0; i < s; ++i){
    vm.local_set(intern(vm.symtable(), bf[i].name), {&bf[i].func});
  }
}

static void install_builtin_load(const char* ld[], size_t s){
  for(size_t i = 0; i < s; ++i){
    stringstream ss({ld[i]}, ios_base::in);
    load(&ss);
  }
}

void install_builtin(){
  install_builtin_native(builtin_syntax_funcs,
                         sizeof(builtin_syntax_funcs) / sizeof(builtin_syntax_funcs[0]));
  vm.local_set(intern(vm.symtable(), null_env_symname), vm.frame());

  vm.set_frame(vm.frame()->push());
  install_builtin_native(builtin_funcs, sizeof(builtin_funcs) / sizeof(builtin_funcs[0]));
  install_builtin_load(builtin_cons_load, builtin_cons_load_size);
  install_builtin_load(builtin_procedure_load, builtin_procedure_load_size);
  install_builtin_port_value();
  install_builtin_load(builtin_port_load, builtin_port_load_size);
  vm.local_set(intern(vm.symtable(), r5rs_env_symname), vm.frame());

  vm.set_frame(vm.frame()->push());
  install_builtin_native(builtin_extra_funcs,
                         sizeof(builtin_extra_funcs) / sizeof(builtin_extra_funcs[0]));
  install_builtin_load(builtin_extra_load, builtin_extra_load_size);
  vm.local_set(intern(vm.symtable(), interaction_env_symname), vm.frame());
}

void load(InputPort* p){
  while(1){
    auto form = read(*p);
    if(!form){
      if(!*p){
        // cerr << "load error: failed at reading a form. abandoned.\n";
      }
      break;
    }

    vm.code.push_back(form);
    eval();
    if(!vm.return_value[0]){
      cerr << "load error: failed at evaluating a form. skipped.\n";
      cerr << "\tform: \n";
      print(cerr, form);
      continue;
    }
  }
}

<commit_msg>trivial startup change<commit_after>#include <sstream>
#include <istream>
#include <iostream>
#include <algorithm>

#include "builtin.hh"
#include "util.hh"
#include "number.hh"
#include "procedure.hh"
#include "lisp_ptr.hh"
#include "eval.hh"
#include "builtin_util.hh"
#include "reader.hh"
#include "printer.hh"
#include "vm.hh"
#include "port.hh"

#include "builtin_boolean.hh"
#include "builtin_char.hh"
#include "builtin_cons.hh"
#include "builtin_equal.hh"
#include "builtin_extra.hh"
#include "builtin_numeric.hh"
#include "builtin_port.hh"
#include "builtin_procedure.hh"
#include "builtin_string.hh"
#include "builtin_symbol.hh"
#include "builtin_syntax.hh"
#include "builtin_vector.hh"

using namespace std;
using namespace Procedure;

namespace {

static const char null_env_symname[] = "null-env-value";
static const char r5rs_env_symname[] = "r5rs-env-value";
static const char interaction_env_symname[] = "interaction-env-value";

static
Lisp_ptr env_pick_2(const char* name){
  ZsArgs args{1};
  auto num = args[0].get<Number*>();
  if(!num){
    throw builtin_type_check_failed(name, Ptr_tag::number, args[0]);
  }

  if(num->type() != Number::Type::integer){
    throw make_zs_error("native func: %s: passed number is not exact integer\n", name);
  }

  auto ver = num->get<Number::integer_type>();
  if(ver != 5l){
    throw make_zs_error("native func: %s: passed number is not 5 (supplied %ld)\n",
                        name, ver);
  }

  return vm.find(intern(vm.symtable(), name));
}

Lisp_ptr env_r5rs(){
  return env_pick_2(r5rs_env_symname);
}

Lisp_ptr env_null(){
  return env_pick_2(null_env_symname);
}

Lisp_ptr env_interactive(){
  ZsArgs args{0};
  return vm.find(intern(vm.symtable(), interaction_env_symname));
}

Lisp_ptr eval_func(){
  ZsArgs args{2};
  auto env = args[1].get<Env*>();
  if(!env){
    throw builtin_type_check_failed("eval", Ptr_tag::env, args[1]);
  }

  auto oldenv = vm.frame();
  vm.set_frame(env);
  vm.code.insert(vm.code.end(),
                 {oldenv, vm_op_leave_frame, args[0]});
  return vm_op_nop;
}

Lisp_ptr load_func(){
  ZsArgs args{1};
  auto str = args[0].get<String*>();
  if(!str){
    throw builtin_type_check_failed("load", Ptr_tag::string, args[0]);
  }

  stringstream f(*str, ios_base::in);
  if(!f){
    throw zs_error("load error: failed at opening file\n");
  }

  load(&f);
  return vm_op_nop;
}

} //namespace

static const BuiltinFunc
builtin_syntax_funcs[] = {
#include "builtin_equal.defs.hh"
#include "builtin_syntax.defs.hh"
};

static const BuiltinFunc
builtin_funcs[] = {
  {"eval", {
      eval_func,
      {Calling::function, 2}}},

  {"scheme-report-environment", {
      env_r5rs,
      {Calling::function, 1}}},
  {"null-environment", {
      env_null,
      {Calling::function, 1}}},
  {"interaction-environment", {
      env_interactive,
      {Calling::function, 0}}},

  {"load", {
      load_func,
      {Calling::function, 1}}},

#include "builtin_boolean.defs.hh"
#include "builtin_char.defs.hh"
#include "builtin_cons.defs.hh"
#include "builtin_numeric.defs.hh"
#include "builtin_port.defs.hh"
#include "builtin_procedure.defs.hh"
#include "builtin_string.defs.hh"
#include "builtin_symbol.defs.hh"
#include "builtin_vector.defs.hh"
};

static const BuiltinFunc
builtin_extra_funcs[] = {
#include "builtin_extra.defs.hh"
};

static void install_builtin_load(const char* ld[], size_t s){
  for(size_t i = 0; i < s; ++i){
    stringstream ss({ld[i]}, ios_base::in);
    load(&ss);
  }
}

void install_builtin(){
  static constexpr auto install_builtin_native = [](const BuiltinFunc& bf){
    vm.local_set(intern(vm.symtable(), bf.name), {&bf.func});
  };

  for_each(std::begin(builtin_syntax_funcs), std::end(builtin_syntax_funcs),
           install_builtin_native);
  vm.local_set(intern(vm.symtable(), null_env_symname), vm.frame());

  vm.set_frame(vm.frame()->push());
  for_each(std::begin(builtin_funcs), std::end(builtin_funcs),
           install_builtin_native);
  install_builtin_load(builtin_cons_load, builtin_cons_load_size);
  install_builtin_load(builtin_procedure_load, builtin_procedure_load_size);
  install_builtin_port_value();
  install_builtin_load(builtin_port_load, builtin_port_load_size);
  vm.local_set(intern(vm.symtable(), r5rs_env_symname), vm.frame());

  vm.set_frame(vm.frame()->push());
  for_each(std::begin(builtin_extra_funcs), std::end(builtin_extra_funcs),
           install_builtin_native);
  install_builtin_load(builtin_extra_load, builtin_extra_load_size);
  vm.local_set(intern(vm.symtable(), interaction_env_symname), vm.frame());
}

void load(InputPort* p){
  while(1){
    auto form = read(*p);
    if(!form){
      if(!*p){
        // cerr << "load error: failed at reading a form. abandoned.\n";
      }
      break;
    }

    vm.code.push_back(form);
    eval();
    if(!vm.return_value[0]){
      cerr << "load error: failed at evaluating a form. skipped.\n";
      cerr << "\tform: \n";
      print(cerr, form);
      continue;
    }
  }
}

<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkDataObject.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 2001 Insight Consortium
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

 * The name of the Insight Consortium, nor the names of any consortium members,
   nor of any contributors, may be used to endorse or promote products derived
   from this software without specific prior written permission.

  * Modified source versions must be plainly marked as such, and must not be
    misrepresented as being the original software.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================*/
#include "itkDataObject.h"
#include "itkProcessObject.h"
#include "itkObjectFactory.h"
#include "itkSmartPointerForwardReference.txx"

// Manual instantiation is necessary to prevent link errors
template class itk::SmartPointerForwardReference<itk::ProcessObject>;

namespace itk
{

// after use by filter
bool DataObject::m_GlobalReleaseDataFlag = false;

DataObjectError
::DataObjectError()
  : ExceptionObject(), m_DataObject(0)
{
}

DataObjectError
::DataObjectError(const char *file, unsigned int lineNumber)
  : ExceptionObject(file, lineNumber), m_DataObject(0)
{
}

DataObjectError
::DataObjectError(const std::string& file, unsigned int lineNumber)
  : ExceptionObject(file, lineNumber), m_DataObject(0)
{
}

DataObjectError
::DataObjectError(const DataObjectError &orig)
  : ExceptionObject( orig )
{
  m_DataObject = orig.m_DataObject;
}

DataObjectError&
DataObjectError
::operator=( const DataObjectError& orig)
{
  ExceptionObject::operator= (orig);
  m_DataObject = orig.m_DataObject;
  return *this;
}

void
DataObjectError
::SetDataObject(DataObject *dobj)
{
  m_DataObject = dobj;
}

SmartPointer<DataObject>
DataObjectError
::GetDataObject()
{
  return m_DataObject;
}

void
DataObjectError
::PrintSelf(std::ostream& os, Indent indent) const
{
  ExceptionObject::PrintSelf( os, indent );

  os << indent << "Data object: ";
  if (m_DataObject)
    {
    os << std::endl;
    m_DataObject->PrintSelf(os, indent.GetNextIndent());
    }
  else
    {
    os << "(None)" << std::endl;
    }
}

InvalidRequestedRegionError
::InvalidRequestedRegionError()
  : DataObjectError()
{
}

InvalidRequestedRegionError
::InvalidRequestedRegionError(const char *file, unsigned int lineNumber)
  : DataObjectError(file, lineNumber)
{
}

InvalidRequestedRegionError
::InvalidRequestedRegionError(const std::string& file, unsigned int lineNumber)
  : DataObjectError(file, lineNumber)
{
}

InvalidRequestedRegionError
::InvalidRequestedRegionError(const InvalidRequestedRegionError &orig)
  : DataObjectError( orig )
{
}

InvalidRequestedRegionError&
InvalidRequestedRegionError
::operator=( const InvalidRequestedRegionError& orig)
  {
    DataObjectError::operator= (orig);
    return *this;
  }

void
InvalidRequestedRegionError
::PrintSelf(std::ostream& os, Indent indent) const
{
  DataObjectError::PrintSelf( os, indent );
}

//----------------------------------------------------------------------------
DataObject::
DataObject()
{
  m_Source = 0;
  m_SourceOutputIndex = 0;

  // We have to assume that if a user is creating the data on their own,
  // then they will fill it with valid data.
  m_DataReleased = false;

  m_ReleaseDataFlag = false;

  m_PipelineMTime = 0;

  m_RequestedRegionInitialized = false;
}

//----------------------------------------------------------------------------
DataObject
::~DataObject()
{
}

//----------------------------------------------------------------------------
void
DataObject
::Initialize()
{
// We don't modify ourselves because the "ReleaseData" methods depend upon
// no modification when initialized.
//
}

//----------------------------------------------------------------------------
void
DataObject
::SetGlobalReleaseDataFlag(bool val)
{
  if (val == m_GlobalReleaseDataFlag)
    {
    return;
    }
  m_GlobalReleaseDataFlag = val;
}

//----------------------------------------------------------------------------
bool
DataObject
::GetGlobalReleaseDataFlag()
{
  return m_GlobalReleaseDataFlag;
}

//----------------------------------------------------------------------------
void
DataObject
::ReleaseData()
{
  this->Initialize();
  m_DataReleased = true;
}

//----------------------------------------------------------------------------
bool
DataObject
::ShouldIReleaseData() const
{
  return ( m_GlobalReleaseDataFlag || m_ReleaseDataFlag );
}

//----------------------------------------------------------------------------
// Set the process object that generates this data object.
//
void
DataObject
::DisconnectPipeline() const
{
  itkDebugMacro( "disconnecting from the pipeline." );

  // disconnect ourselves from the current process object
  if (m_Source)
    {
    m_Source->SetNthOutput(m_SourceOutputIndex, 0);
    }

  this->Modified();
}

void
DataObject
::DisconnectSource(ProcessObject *arg, unsigned int idx) const
{
  itkDebugMacro( "disconnecting source  " << arg
                 << ", source output index " << idx);

  if ( m_Source == arg && m_SourceOutputIndex == idx)
    {
    m_Source = 0;
    m_SourceOutputIndex = 0;
    this->Modified();
    }
}

void
DataObject
::ConnectSource(ProcessObject *arg, unsigned int idx) const
{
  itkDebugMacro( "connecting source  " << arg
                 << ", source output index " << idx);

  if ( m_Source != arg || m_SourceOutputIndex != idx)
    {
    m_Source = arg;
    m_SourceOutputIndex = idx;
    this->Modified();
    }
}

//----------------------------------------------------------------------------

SmartPointerForwardReference<ProcessObject>
DataObject
::GetSource() const
{
  itkDebugMacro("returning Source address " << m_Source );
  return m_Source.GetPointer();
}

unsigned int
DataObject
::GetSourceOutputIndex() const
{
  itkDebugMacro("returning Source index " << m_SourceOutputIndex );
  return m_SourceOutputIndex;
}

//----------------------------------------------------------------------------
void
DataObject
::PrintSelf(std::ostream& os, Indent indent) const
{
  Object::PrintSelf(os,indent);

  if ( m_Source )
    {
    os << indent << "Source: (" << m_Source.GetPointer() << ") \n";
    os << indent << "Source output index: " << m_SourceOutputIndex << "\n";
    }
  else
    {
    os << indent << "Source: (none)\n";
    os << indent << "Source output index:  0\n";
    }

  os << indent << "Release Data: "
     << (m_ReleaseDataFlag ? "On\n" : "Off\n");

  os << indent << "Data Released: "
     << (m_DataReleased ? "True\n" : "False\n");

  os << indent << "Global Release Data: "
     << (m_GlobalReleaseDataFlag ? "On\n" : "Off\n");

  os << indent << "PipelineMTime: " << m_PipelineMTime << std::endl;
  os << indent << "UpdateTime: " << m_UpdateTime << std::endl;

  os << indent << "LastRequestedRegionWasOutsideOfTheBufferedRegion: " <<
    m_LastRequestedRegionWasOutsideOfTheBufferedRegion << std::endl;
}

// The following methods are used for updating the data processing pipeline.
//

//----------------------------------------------------------------------------
void
DataObject
::Update()
{
  this->UpdateOutputInformation();
  this->PropagateRequestedRegion();
  this->UpdateOutputData();
}

void
DataObject
::ResetPipeline()
{
  this->PropagateResetPipeline();
}

void
DataObject
::PropagateResetPipeline()
{
  if (m_Source)
    {
    m_Source->PropagateResetPipeline();
    }
}

//----------------------------------------------------------------------------
void
DataObject
::PropagateRequestedRegion()
{
  // If we need to update due to PipelineMTime, or the fact that our
  // data was released, then propagate the update region to the source
  // if there is one.
  if ( m_UpdateTime < m_PipelineMTime || m_DataReleased ||
       this->RequestedRegionIsOutsideOfTheBufferedRegion() ||
       m_LastRequestedRegionWasOutsideOfTheBufferedRegion)
    {

    if ( m_Source )
      {
      m_Source->PropagateRequestedRegion(this);
      }
    }

  // update the value of this ivar
  m_LastRequestedRegionWasOutsideOfTheBufferedRegion =
    this->RequestedRegionIsOutsideOfTheBufferedRegion();

  // Check that the requested region lies within the largest possible region
  if ( ! this->VerifyRequestedRegion() )
    {
    // invalid requested region, throw an exception
    InvalidRequestedRegionError e(__FILE__, __LINE__);
    std::ostrstream msg;
    msg << (char *)this->GetNameOfClass()
        << "::PropagateRequestedRegion()" << std::ends;
    e.SetLocation(msg.str());
    e.SetDescription("Requested region is (at least partially) outside the largest possible region.");
    e.SetDataObject(this);

    throw e;
    // return;
    }
}

//----------------------------------------------------------------------------
void
DataObject
::UpdateOutputData()
{
  // If we need to update due to PipelineMTime, or the fact that our
  // data was released, then propagate the UpdateOutputData to the source
  // if there is one.
  if ( m_UpdateTime < m_PipelineMTime || m_DataReleased ||
       this->RequestedRegionIsOutsideOfTheBufferedRegion())
    {
    if ( m_Source )
      {
      m_Source->UpdateOutputData(this);
      }
    }
}

//----------------------------------------------------------------------------
void
DataObject
::DataHasBeenGenerated()
{
  m_DataReleased = 0;
  m_UpdateTime.Modified();
}

//----------------------------------------------------------------------------
void
DataObject
::ComputeEstimatedPipelineMemorySize(unsigned long sizes[3])
{
  if ( m_Source )
    {
    m_Source->ComputeEstimatedPipelineMemorySize( this, sizes );
    }
  else
    {
    unsigned long size = this->GetActualMemorySize();
    sizes[0] = size;
    sizes[1] = size;
    sizes[2] = size;
    }
}

//----------------------------------------------------------------------------
unsigned long
DataObject
::GetEstimatedPipelineMemorySize()
{
  unsigned long sizes[3];
  unsigned long memorySize = 0;

  if ( m_Source )
    {
    m_Source->ComputeEstimatedPipelineMemorySize( this, sizes );
    memorySize = sizes[2];
    }

  return memorySize;
}

//----------------------------------------------------------------------------
unsigned long
DataObject
::GetEstimatedMemorySize()
{
  // This should be implemented in a subclass. If not, default to
  // estimating that no memory is used.
  return 0;
}

//----------------------------------------------------------------------------
unsigned long
DataObject
::GetActualMemorySize()
{
  return 0;
}

} // end namespace itk
<commit_msg>ERR: throw must be on method signature.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkDataObject.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 2001 Insight Consortium
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

 * The name of the Insight Consortium, nor the names of any consortium members,
   nor of any contributors, may be used to endorse or promote products derived
   from this software without specific prior written permission.

  * Modified source versions must be plainly marked as such, and must not be
    misrepresented as being the original software.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================*/
#include "itkDataObject.h"
#include "itkProcessObject.h"
#include "itkObjectFactory.h"
#include "itkSmartPointerForwardReference.txx"

// Manual instantiation is necessary to prevent link errors
template class itk::SmartPointerForwardReference<itk::ProcessObject>;

namespace itk
{

// after use by filter
bool DataObject::m_GlobalReleaseDataFlag = false;

DataObjectError
::DataObjectError()
  : ExceptionObject(), m_DataObject(0)
{
}

DataObjectError
::DataObjectError(const char *file, unsigned int lineNumber)
  : ExceptionObject(file, lineNumber), m_DataObject(0)
{
}

DataObjectError
::DataObjectError(const std::string& file, unsigned int lineNumber)
  : ExceptionObject(file, lineNumber), m_DataObject(0)
{
}

DataObjectError
::DataObjectError(const DataObjectError &orig)
  : ExceptionObject( orig )
{
  m_DataObject = orig.m_DataObject;
}

DataObjectError&
DataObjectError
::operator=( const DataObjectError& orig)
{
  ExceptionObject::operator= (orig);
  m_DataObject = orig.m_DataObject;
  return *this;
}

void
DataObjectError
::SetDataObject(DataObject *dobj)
{
  m_DataObject = dobj;
}

SmartPointer<DataObject>
DataObjectError
::GetDataObject()
{
  return m_DataObject;
}

void
DataObjectError
::PrintSelf(std::ostream& os, Indent indent) const
{
  ExceptionObject::PrintSelf( os, indent );

  os << indent << "Data object: ";
  if (m_DataObject)
    {
    os << std::endl;
    m_DataObject->PrintSelf(os, indent.GetNextIndent());
    }
  else
    {
    os << "(None)" << std::endl;
    }
}

InvalidRequestedRegionError
::InvalidRequestedRegionError()
  : DataObjectError()
{
}

InvalidRequestedRegionError
::InvalidRequestedRegionError(const char *file, unsigned int lineNumber)
  : DataObjectError(file, lineNumber)
{
}

InvalidRequestedRegionError
::InvalidRequestedRegionError(const std::string& file, unsigned int lineNumber)
  : DataObjectError(file, lineNumber)
{
}

InvalidRequestedRegionError
::InvalidRequestedRegionError(const InvalidRequestedRegionError &orig)
  : DataObjectError( orig )
{
}

InvalidRequestedRegionError&
InvalidRequestedRegionError
::operator=( const InvalidRequestedRegionError& orig)
  {
    DataObjectError::operator= (orig);
    return *this;
  }

void
InvalidRequestedRegionError
::PrintSelf(std::ostream& os, Indent indent) const
{
  DataObjectError::PrintSelf( os, indent );
}

//----------------------------------------------------------------------------
DataObject::
DataObject()
{
  m_Source = 0;
  m_SourceOutputIndex = 0;

  // We have to assume that if a user is creating the data on their own,
  // then they will fill it with valid data.
  m_DataReleased = false;

  m_ReleaseDataFlag = false;

  m_PipelineMTime = 0;

  m_RequestedRegionInitialized = false;
}

//----------------------------------------------------------------------------
DataObject
::~DataObject()
{
}

//----------------------------------------------------------------------------
void
DataObject
::Initialize()
{
// We don't modify ourselves because the "ReleaseData" methods depend upon
// no modification when initialized.
//
}

//----------------------------------------------------------------------------
void
DataObject
::SetGlobalReleaseDataFlag(bool val)
{
  if (val == m_GlobalReleaseDataFlag)
    {
    return;
    }
  m_GlobalReleaseDataFlag = val;
}

//----------------------------------------------------------------------------
bool
DataObject
::GetGlobalReleaseDataFlag()
{
  return m_GlobalReleaseDataFlag;
}

//----------------------------------------------------------------------------
void
DataObject
::ReleaseData()
{
  this->Initialize();
  m_DataReleased = true;
}

//----------------------------------------------------------------------------
bool
DataObject
::ShouldIReleaseData() const
{
  return ( m_GlobalReleaseDataFlag || m_ReleaseDataFlag );
}

//----------------------------------------------------------------------------
// Set the process object that generates this data object.
//
void
DataObject
::DisconnectPipeline() const
{
  itkDebugMacro( "disconnecting from the pipeline." );

  // disconnect ourselves from the current process object
  if (m_Source)
    {
    m_Source->SetNthOutput(m_SourceOutputIndex, 0);
    }

  this->Modified();
}

void
DataObject
::DisconnectSource(ProcessObject *arg, unsigned int idx) const
{
  itkDebugMacro( "disconnecting source  " << arg
                 << ", source output index " << idx);

  if ( m_Source == arg && m_SourceOutputIndex == idx)
    {
    m_Source = 0;
    m_SourceOutputIndex = 0;
    this->Modified();
    }
}

void
DataObject
::ConnectSource(ProcessObject *arg, unsigned int idx) const
{
  itkDebugMacro( "connecting source  " << arg
                 << ", source output index " << idx);

  if ( m_Source != arg || m_SourceOutputIndex != idx)
    {
    m_Source = arg;
    m_SourceOutputIndex = idx;
    this->Modified();
    }
}

//----------------------------------------------------------------------------

SmartPointerForwardReference<ProcessObject>
DataObject
::GetSource() const
{
  itkDebugMacro("returning Source address " << m_Source );
  return m_Source.GetPointer();
}

unsigned int
DataObject
::GetSourceOutputIndex() const
{
  itkDebugMacro("returning Source index " << m_SourceOutputIndex );
  return m_SourceOutputIndex;
}

//----------------------------------------------------------------------------
void
DataObject
::PrintSelf(std::ostream& os, Indent indent) const
{
  Object::PrintSelf(os,indent);

  if ( m_Source )
    {
    os << indent << "Source: (" << m_Source.GetPointer() << ") \n";
    os << indent << "Source output index: " << m_SourceOutputIndex << "\n";
    }
  else
    {
    os << indent << "Source: (none)\n";
    os << indent << "Source output index:  0\n";
    }

  os << indent << "Release Data: "
     << (m_ReleaseDataFlag ? "On\n" : "Off\n");

  os << indent << "Data Released: "
     << (m_DataReleased ? "True\n" : "False\n");

  os << indent << "Global Release Data: "
     << (m_GlobalReleaseDataFlag ? "On\n" : "Off\n");

  os << indent << "PipelineMTime: " << m_PipelineMTime << std::endl;
  os << indent << "UpdateTime: " << m_UpdateTime << std::endl;

  os << indent << "LastRequestedRegionWasOutsideOfTheBufferedRegion: " <<
    m_LastRequestedRegionWasOutsideOfTheBufferedRegion << std::endl;
}

// The following methods are used for updating the data processing pipeline.
//

//----------------------------------------------------------------------------
void
DataObject
::Update()
{
  this->UpdateOutputInformation();
  this->PropagateRequestedRegion();
  this->UpdateOutputData();
}

void
DataObject
::ResetPipeline()
{
  this->PropagateResetPipeline();
}

void
DataObject
::PropagateResetPipeline()
{
  if (m_Source)
    {
    m_Source->PropagateResetPipeline();
    }
}

//----------------------------------------------------------------------------
void
DataObject
::PropagateRequestedRegion() throw (InvalidRequestedRegionError)
{
  // If we need to update due to PipelineMTime, or the fact that our
  // data was released, then propagate the update region to the source
  // if there is one.
  if ( m_UpdateTime < m_PipelineMTime || m_DataReleased ||
       this->RequestedRegionIsOutsideOfTheBufferedRegion() ||
       m_LastRequestedRegionWasOutsideOfTheBufferedRegion)
    {

    if ( m_Source )
      {
      m_Source->PropagateRequestedRegion(this);
      }
    }

  // update the value of this ivar
  m_LastRequestedRegionWasOutsideOfTheBufferedRegion =
    this->RequestedRegionIsOutsideOfTheBufferedRegion();

  // Check that the requested region lies within the largest possible region
  if ( ! this->VerifyRequestedRegion() )
    {
    // invalid requested region, throw an exception
    InvalidRequestedRegionError e(__FILE__, __LINE__);
    std::ostrstream msg;
    msg << (char *)this->GetNameOfClass()
        << "::PropagateRequestedRegion()" << std::ends;
    e.SetLocation(msg.str());
    e.SetDescription("Requested region is (at least partially) outside the largest possible region.");
    e.SetDataObject(this);

    throw e;
    // return;
    }
}

//----------------------------------------------------------------------------
void
DataObject
::UpdateOutputData()
{
  // If we need to update due to PipelineMTime, or the fact that our
  // data was released, then propagate the UpdateOutputData to the source
  // if there is one.
  if ( m_UpdateTime < m_PipelineMTime || m_DataReleased ||
       this->RequestedRegionIsOutsideOfTheBufferedRegion())
    {
    if ( m_Source )
      {
      m_Source->UpdateOutputData(this);
      }
    }
}

//----------------------------------------------------------------------------
void
DataObject
::DataHasBeenGenerated()
{
  m_DataReleased = 0;
  m_UpdateTime.Modified();
}

//----------------------------------------------------------------------------
void
DataObject
::ComputeEstimatedPipelineMemorySize(unsigned long sizes[3])
{
  if ( m_Source )
    {
    m_Source->ComputeEstimatedPipelineMemorySize( this, sizes );
    }
  else
    {
    unsigned long size = this->GetActualMemorySize();
    sizes[0] = size;
    sizes[1] = size;
    sizes[2] = size;
    }
}

//----------------------------------------------------------------------------
unsigned long
DataObject
::GetEstimatedPipelineMemorySize()
{
  unsigned long sizes[3];
  unsigned long memorySize = 0;

  if ( m_Source )
    {
    m_Source->ComputeEstimatedPipelineMemorySize( this, sizes );
    memorySize = sizes[2];
    }

  return memorySize;
}

//----------------------------------------------------------------------------
unsigned long
DataObject
::GetEstimatedMemorySize()
{
  // This should be implemented in a subclass. If not, default to
  // estimating that no memory is used.
  return 0;
}

//----------------------------------------------------------------------------
unsigned long
DataObject
::GetActualMemorySize()
{
  return 0;
}

} // end namespace itk
<|endoftext|>