bool RemoteDataSource::getARow(MemoryBuffer & out, RowCache & cache, byte cmd, __int64 row)
{
    RowLocation location;

    if (cache.getCacheRow(row, location))
    {
        out.append(location.matchLength, location.matchRow);
        return true;
    }

    CMessageBuffer msg;
    msg.setEndian(__BIG_ENDIAN);
    msg.append(cmd);
    msg.append(id);
    msg.append(row);

    sendReceive(msg);

    bool ok;
    msg.read(ok);
    if (!ok) return false;

    __int64 start;
    msg.read(start);

    VariableRowBlock * next = new VariableRowBlock(msg, start);
    cache.addRowsOwn(next);

    if (!cache.getCacheRow(row, location))
        assertex(!"Internal Error!");
    out.append(location.matchLength, location.matchRow);
    return true;
}
IFvDataSource * createRemoteFileDataSource(const SocketEndpoint & server, const char * username, const char * password, const char * logicalName)
{
    Owned<INode> serverNode = createINode(server);

    CMessageBuffer msg;
    msg.setEndian(__BIG_ENDIAN);
    msg.append((byte)FVCMDcreatefile);
    msg.append(myProcessSession());
    msg.append(username);
    msg.append(password);
    msg.append(logicalName);

    sendReceive(serverNode, msg);

    unsigned short version;
    unique_id_t id;
    __int64 numRows;
    bool isIndex;
    msg.read(version);
    msg.read(id);
    msg.read(numRows);
    Owned<IFvDataSourceMetaData> meta = deserializeDataSourceMeta(msg);
    msg.read(isIndex);

    if (id)
        return new RemoteDataSource(server, id, meta, numRows, isIndex);
    return 0;
}
void RemoteDataSource::beforeDispose()
{
    CMessageBuffer msg;
    msg.setEndian(__BIG_ENDIAN);
    msg.append((byte)FVCMDdestroy);
    msg.append(id);

    sendReceive(msg);
}
static void sendReceive(INode * serverNode, CMessageBuffer & msg)
{
    if (!queryWorldCommunicator().sendRecv(msg, serverNode, MPTAG_FILEVIEW, TIMEOUT))
        throwError(FVERR_TimeoutRemoteFileView);

    msg.setEndian(__BIG_ENDIAN);
    IException * error = deserializeException(msg);
    if (error)
        throw error;
}
__int64 RemoteDataSource::numRows(bool force)
{
    if (!force)
        return cachedNumRows;
    CMessageBuffer msg;
    msg.setEndian(__BIG_ENDIAN);
    msg.append((byte)FVCMDnumrows);
    msg.append(id);

    sendReceive(msg);

    __int64 result;
    msg.read(result);
    return result;
}
bool RemoteDataSource::fetchRawRow(MemoryBuffer & out, __int64 offset)
{
    CMessageBuffer msg;
    msg.setEndian(__BIG_ENDIAN);
    msg.append(FVCMDfetchraw);
    msg.append(id);
    msg.append(offset);

    sendReceive(msg);

    bool ok;
    msg.read(ok);
    if (!ok) return false;
    size32_t len;
    msg.read(len);
    out.append(len, msg.readDirect(len));
    return true;
}